Ios 在调试器中打印时显示UTC的Swift NSDate。我如何知道它是否';比较日期/时间时,是当地时间还是utc?

Ios 在调试器中打印时显示UTC的Swift NSDate。我如何知道它是否';比较日期/时间时,是当地时间还是utc?,ios,nsdate,xcode7.3,swift2.3,Ios,Nsdate,Xcode7.3,Swift2.3,我正在尝试为调度应用程序编写一些代码,这些调度需要基于用户的当前时间。例如,在当天下午5点到9点之间有一些东西可用。当我使用NSDate()获取当前时间时,打印结果为utc:2016-12-15 13:12:05+0000。我知道它是utc的,因为如果我在脑子里加上我的本地时区偏移量,它就是我手机上的实际时间。我遇到的问题是,当试图创建这些时间窗口时,有时结束时间会进入第二天,因为没有负偏移量。例如,用户的时区偏移量为-5,当前为当地时间晚上9点。这将显示第二天凌晨2点,这将不起作用,因为我需要

我正在尝试为调度应用程序编写一些代码,这些调度需要基于用户的当前时间。例如,在当天下午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点。

首先,要理解的关键是,
NSDate
并不代表您可能正在考虑的任何“日期”。它代表一个时间上的奇异瞬间(不考虑相对论效应或其他什么;只是你直觉上认为的“时间上的瞬间”)

这意味着,例如,
NSDate
没有时区。它没有位置。它本身对“天”或“小时”或“月”一无所知,它只知道从某个特定时刻起经过的秒数

我为什么要没完没了地谈这个?因为
NSDate
几乎从来都不是您想要的日程安排应用程序。当你说“2017年3月15日下午2点”时,你指的是基于某些日历的标称时间。因为日历可能会随着时间的推移而变化(DST规则事实上确实会以不可预测的方式随着时间的推移而变化),所以您无法准确地知道未来任何名义时间所代表的瞬间。你可以猜测,但你不知道,因为将名称映射到实例的规则在此之前可能会改变。当然,即使知道这些规则,标称时间也会代表不同的瞬间,这取决于它必须应用于哪个时区。甚至可能一个标称时间根本不存在(因为DST可能跳过它),或者它映射到多个瞬间(因为DST可能向后跳过)

如果要执行计划,则需要使用
NSCalendar
NSDateComponents
。这些工具可以让您对标称时间进行编码,应用时区,或者处理日历系统的混乱。您应该只在必要时将其转换为
NSDate
,要知道如果是未来的日期,转换是不确定的

NSDateComponents
还允许您跟踪您对日期的实际了解和不了解,因为其中大部分是可选的。例如,可以创建带有
nil
时区且没有时间的
NSDateComponents
。这可以让你表达“万圣节都是10月31日,不管你在哪个时区。”但也可以表达“这次会议是在美国东部时间下午2:00,也就是CST下午1:00。”过早地将这些内容转换为
NSDate
必然会导致万圣节从10月30日晚上10点开始,以及其他类似的废话


关于你的编辑,我认为你所有的困惑都在于“2016-12-15T22:16:11+05:00”的含义。这是一个绝对的时间点。现在不是当地时间。不是UTC。这是一个特定的时间点,每个人都会同意该时间是什么。世界上的任何人都会同意这是地震发生后1481822171秒。月球或火星上的人也会同意。这是一个绝对的时间点。这是真的原因是“+05:00”。这将标称时间(“2016年12月15日晚上10:16:11”)偏移为绝对时间(纪元后1481822171秒)

当您将其转换为NSDate时,存储的唯一信息是1481822171。没有别的了。不是“在时区”,不是“本地”,而是1481822171。当您打印日期描述时(为了方便起见),它会为我打印“2016年12月15日下午12:16”。但这是在当地时间打印的,只是为了方便。这并不意味着NSDate是“本地时间”。如果您想打印它,您应该始终使用NSDateFormatter并应用您想要应用的时区。切勿依赖
说明

我知道我一遍又一遍地说同样的话,但这似乎是人们真正“得到”的最困难的事情。绝对时间没有时区。时区纯粹是为了名义时间而存在的,因为它使时间变得复杂
// 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
print(NSDateFormatter.localizedStringFromDate(date,
  dateStyle: .MediumStyle,
  timeStyle: .MediumStyle))