我试图为调度应用编写一些代码,这些调度需要基于用户的当前时间。例如,当天下午5点到9点之间可以找到一些东西。当我通过使用NSDate()获取当前时间时,打印结果为utc:2016-12-15 13:12:05 +0000。我知道它在utc中,因为如果我在脑海中添加我的本地时区偏移量,它可能是我手机上的实际时间。我遇到的问题是在尝试创建这些时间窗口时,有时结束时间会进入第二天,因为没有负偏移量。例如,用户的时区偏移-5和当前时间当前时间晚上9点。这将显示第二天凌晨2点,因为我需要它才能在同一天工作。你如何管理这种事情?我不确定print()函数是否打印正确的日期。它是否适应我机器的时区?我需要查看实际日期,因为我必须处理世界各地的时区。我尝试更改为+5倍区域,并且所有调度代码都中断。如何确保我的调度程序始终与用户的本地时间一起使用?
如果有人做过这种事情,那么如果您可以展示如何创建开始日期,结束日期,然后如何与当前日期进行比较以查看它是否属于窗口,将会很有帮助。这需要适用于所有时区。
编辑:这是我不明白的事情。如何处理字符串形式的日期,如下所示:" 2016-12-15T22:16:11 + 05:00"日期和时间在"当地时间"?我知道日期是在当地时间,因为这是我生成电话时显示的内容(12月15日晚上10点)。现在我有那个约会,我想知道它是否落在12月15日晚上8点到晚上11点的窗口之间。我怎么做?当我将该字符串转换为NSDate时,它会将其转换为UTC(这是我在调试器中看到的),现在日期距离本地时间(进入第二天)的时间为+5小时。现在的问题是我将第二天的土地日期与当前日期进行比较,例如,当前日期/时间是12月15日晚9点。但我需要知道日期代表12月15日晚上10点。
答案 0 :(得分:2)
第一个要理解的关键是NSDate
并不代表您可能正在考虑的任何方式的“约会”。它代表了一个奇异的瞬间(不考虑相对论效应或其他诸如此类的东西;正是你直觉上所说的“瞬间”)。
这意味着,例如,NSDate
没有时区。它没有位置。它本身并不知道“天”,“小时”或“月”的任何信息。它只是特定时刻以来经过的秒数。
为什么我继续谈论这件事?因为NSDate
几乎不是您想要的调度应用程序。当您说“2017年3月15日2:00p”时,您的意思是基于某些日历的名义时间。由于日历可能会随着时间的推移而发生变化(事实上,DST规则做会以不可预测的方式随时间发生变化),因此您无法确切知道未来任何标称时间所代表的瞬间。您可以猜测,但您无法知道,因为将名称映射到瞬间的规则可能会在此之前发生变化。当然,即使知道规则,标称时间也将代表不同的时刻,具体取决于必须应用的时区。甚至可能在标称时间内根本不存在(因为DST可能会跳过它),或者它可以映射到多个瞬间(因为DST可能会向后跳过)。
如果您正在进行日程安排,则需要使用NSCalendar
和NSDateComponents
。这些工具允许您对标称时间进行编码,应用时区,以及处理日历系统的混乱。您应该只在必要时将这些转换为NSDate
,并意识到如果它是未来日期,转换是不确定的。
NSDateComponents
还允许您跟踪您对日期和您不知道的内容,因为大部分内容都是可选的。例如,可以创建NSDateComponents
nil
时区且没有时间。这让你可以表达“无论你在哪个时区,万圣节都在10月31日”。但也表示“这次会议是在美国东部时间2点00分,即1点00分CST。”将这些东西转换为NSDate
过早地导致万圣节从10月30日的10p开始,以及其他类似的废话。
关于你的编辑,我认为你所有的困惑都在于“2016-12-15T22:16:11 + 05:00”的含义。这是一个绝对的时间点。这不是当地时间。这不是UTC。这是一个特定的时间点,每个人都会同意那个时间。世界上任何人都会同意这是Unix Epoch后的1481822171秒。月球上或火星上的人也会同意。这是一个绝对的时间点。原因是“+05:00”。这将标称时间(“2016年12月15日下午10:16:11”)抵消为绝对时间(大纪元后1481822171秒)。
当您将其转换为NSDate时,存储的唯一信息是1481822171.没有别的。这不是“在一个时区。”它不是“本地的”。这是1481822171.当你打印日期的描述时,这只是为了方便,它为我打印“2016年12月15日,下午12:16”。但这只是为了方便而在当地时间打印。这并不意味着NSDate是“当地时间”。如果要打印此文件,则始终使用NSDateFormatter并应用要应用的时区。永远不要依赖description
。
我知道我一遍又一遍地说同样的话,但对于人们来说,真正“获得”似乎是最困难的。 绝对时间没有时区。时区存在纯的标称时间,因为它让人类感到高兴。名义时代与人类如何思考日历有关。他们与时间的工作方式关系有限(不关心你在这个星球上的位置,或者你所处的政治体系以及他们喜欢的日历)。
如果你想知道这是否在某些标称时间之间,你需要找出这些时间实际上是什么时候。所以你会做这样的事情:
// 8pm and 11pm on the 15th of December (in the +05:00 timezone).
var startComp = DateComponents()
startComp.year = 2016
startComp.month = 12
startComp.day = 15
startComp.hour = 20
startComp.timeZone = TimeZone(secondsFromGMT: 5*60*60)! // +05:00
var endComp = startComp
endComp.hour = 23
let calendar = Calendar(identifier: .gregorian)
let startDate = calendar.date(from: startComp)!
let endDate = calendar.date(from: endComp)!
let targetDate = ISO8601DateFormatter().date(from: "2016-12-15T22:16:11+05:00")!
startDate < targetDate && targetDate < endDate // true
答案 1 :(得分:0)
NSDate(或Swift 3中的Date)对象保存一个双精度数据,记录地球上任何时间的瞬间,与时区无关。在封面下,这两倍是自2001年1月1日午夜以来在英国格林威治(“纪元日期”)的秒数,但这是一个任意的“零点”,并没有将NSDate对象与特定时区联系起来。 / p>
您需要使用日期格式化程序才能在当地时区显示日期。
您可以使用以下代码:
print(NSDateFormatter.localizedStringFromDate(date,
dateStyle: .MediumStyle,
timeStyle: .MediumStyle))
这将在用户的本地时区显示日期date
并使用他们的区域设置。
至于在日期上做数学,有很多方法可以让你在日期中添加时间单位。看一下NSCalendar
课程的文档。例如,看一下方法nextDateAfterDate(_:matchingComponents:options:)
例如,这将让你今天下午5点创建一个NSDate。