【问题标题】:Date since 1600 to NSDate?从 1600 年到 NSDate 的日期?
【发布时间】:2011-01-12 01:31:20
【问题描述】:

我有一个存储为自 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];

(我从不在其他任何地方更改 offset 中的任何值。)

问题是我在 iOS 和 Mac OS X 上的 rootDate 时间不同。在 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 上使用的错误方法?

【问题讨论】:

    标签: cocoa-touch ios nsdate nscalendar nsdatecomponents


    【解决方案1】:

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

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

    【讨论】:

    • 这是个好主意,但不幸的是它仍然会留下 +/- 1 小时的错误。
    【解决方案2】:

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

    初始设置:

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

    (很明显,properties 和 ivars 都进行了调整。)

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

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

    这对我来说有以下优势:

    1. 它使用的 ivars 更少。
    2. 代码更少。
    3. 无论 DST 是否生效,它总是返回当天的午夜。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-04
        • 1970-01-01
        • 1970-01-01
        • 2012-02-12
        • 2011-04-11
        相关资源
        最近更新 更多