1

我有一个存储为自 1600 年 1 月 1 日以来我需要处理的天数的日期。这是我需要在我的应用程序中多次阅读的遗留日期格式。

以前,我一直在创建日历、空日期组件和根日期,如下所示:

self.gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar
                    ] autorelease];
id rootComponents = [[[NSDateComponents alloc] init] autorelease];
[rootComponents setYear: 1600];
[rootComponents setMonth: 1];
[rootComponents setDay: 1];
self.rootDate = [gregorian dateFromComponents: rootComponents];
self.offset = [[[NSDateComponents alloc] init] autorelease];

然后,为了稍后将整数转换为日期,我使用这个:

[offset setDay: theLegacyDate];
id eventDate = [gregorian dateByAddingComponents: offset
                                          toDate: rootDate
                                         options: 0];

(我从不在其他任何地方更改任何偏移值。)

问题是我rootDate在 iOS 和 Mac OS X 上的时间不同。在 Mac OS X 上,我要到午夜了。在 iOS 上,我得到 8:12:28。(到目前为止,这似乎是一致的。)当我添加我的天数后,奇怪的时间仍然存在。

操作系统 | 遗留日期 | 根日期 | 活动日期
======== | ========== | ===========================|======================= ===
Mac OS X | 143671 | 1600-01-01 00:00:00 -0800 | 1993-05-11 00:00:00 -0700
iOS | 143671 | 1600-01-01 08:12:28 +0000 | 1993-05-11 07:12:28 +0000

在我的产品之前的版本中,我并不关心时间;现在我知道了。为什么在 iOS 上出现奇怪的时间,我该怎么办?(我假设小时差是 DST。)

我尝试将 rootComponents 的小时、分钟和秒设置为 0。这没有影响。如果我将它们设置为 0 以外的值,它会将它们添加到 8:12:28。我一直想知道这是否与闰秒或其他累积时钟变化有关。

或者这完全是在 iOS 上使用的错误方法?

4

3 回答 3

3

我想你对闰秒/累积时钟变化解释时间问题是正确的。您正在处理的日期实际上是过去,还是纯粹是一个任意的时代?

无论哪种情况,您都可以尝试定义一个更接近现代的新纪元(例如,可可纪元)。计算新纪元和旧纪元之间的天差,并将其保存为常数。当您需要处理日期时,将此增量应用于日期,然后使用您现有的 NSCalendar 技术,但使用新纪元而不是旧纪元。这有望避免您看到的时钟漂移问题。

于 2011-01-12T01:36:47.330 回答
1

看起来正确的答案是让事情变得更简单。我没有创建 rootDate,而是每次都从组件构建日期。这应该不会更慢,并且仍然使代码非常接近想法。

初始设置:

self.gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar
                    ] autorelease];
self.components = [[[NSDateComponents alloc] init] autorelease];
[components setYear: 1600];
[components setMonth: 1];

(显然,属性和 ivars 已调整。)

稍后,将旧日期实际转换为NSDate

[components setDay: 1 + theLegacyDate];
id eventDate = [gregorian dateFromComponents: components];

这对我来说有以下优点:

  1. 它使用的 ivars 更少。
  2. 它的代码更少。
  3. 无论 DST 是否生效,它总是在当天返回午夜。
于 2011-01-12T01:49:21.687 回答
0

请注意,iOS 会考虑各种时区的非常模糊的规则。很有可能是 1 月 1 日午夜。您所在时区的 1600 实际上是 7:12:28 UTC。在很多情况下,人们抱怨日期转换中的错误,然后有人发现实际上他们所处的时区在多年前发生了一些奇怪的日历变化。

您需要首先找出您的数据代表的确切 NSDate。“自 1600 年 1 月 1 日以来的天数”是无稽之谈,因为您需要一个时区!你应该做什么:找到一个“旧”号码,你知道它应该代表哪一天。例如,如果您“知道” 143671 应该是您所在时区的 1993 年 5 月 11 日,则以该日期作为根日期开始,并添加 (x - 143671) 天。

于 2015-01-22T11:56:46.783 回答