静态的autoupdatingCurrent时区日历不起作用

6
在我的应用程序中,我有一个静态的gregorian属性在SharedCalendar类中定义,如下所示:
static let gregorian: Calendar = {
    var calendar = Foundation.Calendar(identifier: .gregorian)
    calendar.timeZone = TimeZone.autoupdatingCurrent
    return calendar
}()

当我想要在特定时区访问某个日期的一天时,我会调用以下代码:

SharedCalendar.gregorian.dateComponents([ .day ], from: someDate).day!

假设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属性的定义更改为var时:
var gregorian: Calendar {
    var calendar = Foundation.Calendar(identifier: .gregorian)
    calendar.timeZone = TimeZone.autoupdatingCurrent
    return calendar
}

一切正常,对于 America/Vancouver (autoupdatingCurrent),我得到了 31,对于 Australia/Sydney (autoupdatingCurrent),我得到了 1

目前我还不太明白 TimeZone.autoupdatingCurrent 是如何工作的。当设备的时区更改时,SharedCalendar.gregorian.timeZone 反映出设备的时区,但看起来 SharedCalendar.gregorian 仍在使用旧的时区。

有人能解释一下这种行为吗?


1
与您的问题/问题无关,但如果您只需要一个组件,则可以使用日历方法SharedCalendar.gregorian.component(.day, from: someDate) - Leo Dabus
感谢@LeoDabus! - Aleksander Grzyb
1个回答

7

我报告了这个问题,关于这个问题我在radar上进行了报告,今天苹果公司回复如下:

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

你的 var 日历之所以有效是因为每次调用日历属性都会创建一个新的计算日历,该日历恰好设置为代表当前系统时区的新时区。

这很有道理,因为 static let 缓存了系统的时区,从 NSTimeZone.resetSystemTimeZone 的文档中可以看出:

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接