swift 区域设置的差异,自动更新当前和固定的区域设置行为

3hvapo4f  于 2023-03-07  发布在  Swift
关注(0)|答案(1)|浏览(126)

如果我使用系统区域设置(Locale.autoupdatingCurrent),那么DateFormatter在系统设置中使用24开关。

let locale = Locale.autoupdatingCurrent;
let timeZone = TimeZone(secondsFromGMT: 0*3600)!
var calendar = Calendar.current;
calendar.locale = locale;
calendar.timeZone = timeZone;
let iso:ISO8601DateFormatter = .init();
iso.formatOptions = [.withInternetDateTime];
let date = iso.date(from: "2000-01-01T13:16:45Z")!
let df:DateFormatter = .init()
df.locale = locale
df.timeZone = timeZone
df.timeStyle = .medium        
let s = df.string(from: date)
print(s) // 1:16:45 pm
// switch to 24 Hour time in system settings
print(s) // 13:16:45

但是如果我使用固定的语言环境并手动设置hourCycle,那么DateFormatter会忽略这个属性。

var components = Locale.Components(languageCode: "en", languageRegion: "GB")
components.hourCycle = .oneToTwelve
let locale = Locale(components: components)
// .... above code
print(s) // 13:16:45 for oneToTwelve hourCycle
4ioopgfo

4ioopgfo1#

Locale.ComponentsLocale.init(components:)以及Locale.hourCycle都是iOS 16和macOS 13的新API,Foundation的遗留部分(如DateFormatter)似乎还不理解/尊重(还没有?)
不幸的是,即使是iOS 15和macOS 12中新的Date.formatted(_:)Date.FormatStyle也不支持它,所以我开始怀疑.hourCycle只是用作一个方便的只读属性,而不是实际用于定制日期时间格式。
Locale.current.autoupdatingCurrent似乎使用了某种隐藏的内部方法来检查用户设置中的12 h/24 h覆盖,因为如果您使用调试器检查_componentsBox.wrapped.hourCycle,您将看到它始终为nil,而与用户设置无关。
这与Locale.init(components:)示例不同,如果你用Locale.Components.hourCycle覆盖它,Locale.init(components:)示例将正确设置这个值。
但是,阅读Locale.hourCycle属性将为所有三种Locale示例返回正确的值。
如果你想在DateFormatter中强制使用12 h/24 h格式,你必须执行如下操作:

let locale = ...

let template: String = {
    switch locale.hourCycle {
        case .zeroToEleven: fallthrough
        case .oneToTwelve: return "hh"
        case .zeroToTwentyThree: fallthrough
        case .oneToTwentyFour: return "HH"
    }
}() + "mmss"

let formatter = DateFormatter()
formatter.locale = locale
formatter.setLocalizedDateFormatFromTemplate(template)

我不认为这是可能的强制与新的Date.formatted(_:)然而。
https://developer.apple.com/forums/thread/701972

相关问题