NSCalendar 组件没有考虑时间

Posted

技术标签:

【中文标题】NSCalendar 组件没有考虑时间【英文标题】:NSCalendar components not taking time into account 【发布时间】:2011-04-01 04:04:53 【问题描述】:

我们知道 NSDate 是 UTC/GMT。换句话说,没有时区信息与之关联。

有一些高级类,例如 NSCalendar 和 NSTimeZone 以及 NSDateComponents,它们确实考虑了时区。

基于此,我使用以下代码来计算 2 个日期之间的天数差异。然而,我得到的结果似乎是计算完成时完全忽略了时间。我想知道我是否做错了什么,或者这是出于某种原因设计的。

这里是代码和数据:

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comp = [calendar components:NSDayCalendarUnit fromDate:startDate toDate:stopDate options:0];
NSInteger day = [comp day];

调试输出:

(gdb) po startDate
2011-04-01 03:52:13 +0000
(gdb) po stopDate
2011-04-03 15:52:13 +0000
(gdb) p (int) day
$1 = 2

时区为太平洋标准时间,以上转换为 PST 的日期为:

startDate = 2011-03-31 8:52:13 -7
stopDate  = 2011-04-03 8:52:13 -7

因此,我希望他们之间有 4 天,而不是 2 天。(第 31 天、第 1 天、第 2 天和第 3 天)

我认为小时数被忽略的原因是,如果将小时数添加到计算中,我们会得到 2 天 12 小时。

是我做错了什么还是这就是设计的工作原理?

谢谢你, 万斯

【问题讨论】:

【参考方案1】:

不完全是。当您在太平洋时区格式化日期时,您会得到:

Calendars[38041:707] start: 2011-03-31 20:52:13 -0700
Calendars[38041:707] stop : 2011-04-03 08:52:13 -0700

这与您发布的内容有些不同。你的似乎是上午 8 点,而不是晚上 8 点。

另外,components:fromDate:toDate:options: 将计算 整个 个单位。因此,如果您要询问天数,就会说它们之间有整整 2 天。

也许一个更好的方法来做你正在寻找的事情是这样的:

NSUInteger startOrdinal = [cal ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:startDate];
NSUInteger stopOrdinal = [cal ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:stopDate];

那么它们之间的天数将是(stopOrdinal - startOrdinal)。对于您的日期,这会产生 3(格林威治标准时间 4 月 1 日 - 格林威治标准时间 4 月 3 日)。如果你真的想忽略时间部分,你将不得不弄清楚如何在目标时区内切断日期的时间部分。这将涉及将日期转换为NSDateComponent 对象,然后将-hour-minute-second 部分设置为0。完成此操作后,您可以将它们改回NSDates,然后继续你的差异计算。

【讨论】:

以上是关于NSCalendar 组件没有考虑时间的主要内容,如果未能解决你的问题,请参考以下文章

iOS NSCalendar 崩溃 - 参考问题?

NSCalendar 一个月内的最大天数

UILocal 通知未显示

检测 [NSTimeZone localTimezone] secondsFromGMT 属性变化

Foundation框架中的NSCalendar

如何同时支持 iOS 7 和 8 的 NSCalendar?