静态让带有自动更新当前时区的日历不起作用

Ale*_*zyb 5 timezone static calendar ios swift

在我的应用程序中,我gregorianSharedCalendar类中有一个静态属性,其定义如下:

static let gregorian: Calendar = {
    var calendar = Foundation.Calendar(identifier: .gregorian)
    calendar.timeZone = TimeZone.autoupdatingCurrent
    return calendar
}()
Run Code Online (Sandbox Code Playgroud)

当我想访问特定时区中某个日期的某一天时,我正在调用:

SharedCalendar.gregorian.dateComponents([ .day ], from: someDate).day!
Run Code Online (Sandbox Code Playgroud)

让我们说someDateDate(timeIntervalSinceReferenceDate: 512658000.0)哪个是2017-03-31 13:00:00 +0000

当我开始在温哥华时区中的应用程序中的SharedCalendar.gregorian.timeZone财产具有价值America/Vancouver (autoupdatingCurrent)和的结果SharedCalendar.gregorian.dateComponents([ .day ], from: someDate).day!就是31 这是正确的

当我将应用程序置于后台并将时区切换到悉尼并再次运行该应用程序时,该SharedCalendar.gregorian.timeZone属性具有值Australia/Sydney (autoupdatingCurrent)(这是正确的),但结果SharedCalendar.gregorian.dateComponents([ .day ], from: someDate).day!31 哪个是错误的(应该是1

当我将gregorian属性的定义更改为 a 时var

var gregorian: Calendar {
    var calendar = Foundation.Calendar(identifier: .gregorian)
    calendar.timeZone = TimeZone.autoupdatingCurrent
    return calendar
}
Run Code Online (Sandbox Code Playgroud)

一切正常,这是为了America/Vancouver (autoupdatingCurrent)我得到31,为了Australia/Sydney (autoupdatingCurrent)我得到1

现在我不太明白TimeZone.autoupdatingCurrent是如何工作的。当设备的时区更改时,会SharedCalendar.gregorian.timeZone反映设备的时区,但它看起来像是SharedCalendar.gregorian以某种方式使用旧时区。

有人对这种行为有解释吗?

Ale*_*zyb 5

我报告了关于这个问题的雷达,今天苹果回应了:

static let日历的时区未更新的原因是您需要发出调用以NSTimeZone.resetSystemTimeZone()与系统时区同步。有关NSTimeZone.resetSystemTimeZone()更多信息,请参阅文档:https : //developer.apple.com/documentation/foundation/nstimezone/1387189-resetsystemtimezone?language=objc

您的var日历工作的原因是因为每次调用 calendar 属性实际上都会创建一个新的计算日历,该日历恰好设置为代表当前系统时区的新时区。

这是有道理的,因为static let缓存系统的时区,NSTimeZone.resetSystemTimeZone我们可以从文档中阅读:

如果应用程序已缓存系统时区,则此方法会清除该缓存对象。如果随后调用 systemTimeZone,NSTimeZone 将尝试重新确定系统时区,并且将创建和缓存一个新对象(请参阅 systemTimeZone)。