-1

我正在尝试为计划应用程序编写一些代码,这些计划需要基于用户的当前时间。例如,当天下午 5 点到 9 点之间有可用的东西。当我使用 NSDate() 获取当前时间时,将其打印为 utc:2016-12-15 13:12:05 +0000。我知道它是 UTC 格式,因为如果我在脑海中添加本地时区偏移量,那么它就是我手机上的实际时间。我遇到的问题是在尝试创建这些时间窗口时,有时结束时间会进入第二天,因为没有负偏移量。例如,用户的时区偏移量 -5 并且当前是当地时间晚上 9 点。这将显示第二天凌晨 2 点,这是行不通的,因为我需要它是同一天。你如何管理这种事情?我' m 不确定 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 点。

4

2 回答 2

2

首先要理解的关键是它NSDate并不代表您可能正在考虑的任何“日期”。它代表一个单一的时间瞬间(不考虑相对论效应或其他诸如此类的东西;正是您直觉上认为的“时间瞬间”)。

例如,这意味着 anNSDate没有时区。它没有位置。它本身对“天”、“小时”或“月”一无所知。它只是自特定时刻以来经过的秒数。

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

如果您正在安排日程,您希望使用NSCalendarand NSDateComponents。这些工具让您可以对标称时间进行编码、应用时区,并以其他方式处理日历系统的混乱。您应该只NSDate在必要时将它们转换为,意识到如果它是未来日期,则转换是不确定的。

NSDateComponents还允许您跟踪您对日期的实际了解以及您不了解的内容,因为其中大部分是可选的。例如,可以创建NSDateComponents一个nil有时区但没有时间的。这使您可以表达诸如“万圣节是整个 10 月 31 日,无论您在哪个时区”之类的内容。但也要表达“本次会议在美国东部标准时间下午 2:00,即美国中部标准时间下午 1:00”。将这些东西NSDate过早地转换为总是会导致万圣节从 10 月 30 日晚上 10 点开始,以及其他类似的废话。


关于您的编辑,我认为您的所有困惑都在于“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
于 2016-12-15T17:54:44.313 回答
0

NSDate(或 Swift 3 中的 Date)对象保存了一个 double,它记录了地球上任何地方的时间瞬间,与时区无关。在幕后,这个双倍是自 2001 年 1 月 1 日午夜在英国格林威治(“纪元日期”)以来的秒数,但这是一个任意的“零点”,并且不会将 NSDate 对象与特定时区联系起来。

您需要使用日期格式化程序才能在当地时区显示日期。

您可以使用以下代码:

print(NSDateFormatter.localizedStringFromDate(date,
  dateStyle: .MediumStyle,
  timeStyle: .MediumStyle))

这将date在用户的本地时区显示日期并使用他们的区域设置。

至于对日期进行数学运算,有许多方法可以让您将时间单位添加到日期。查看该NSCalendar课程的文档。例如看一下方法nextDateAfterDate(_:matchingComponents:options:)

例如,这将让您为今天下午 5 点创建一个 NSDate。

于 2016-12-15T18:01:45.663 回答