Locale.autoupdatingCurrent与固定Locale的行为差异及hourCycle失效问题
手动设置Locale的hourCycle后DateFormatter不生效的原因及解决办法
原因
- 区域默认格式优先级更高:
en-GB这类区域本身默认使用24小时制,即使通过Locale.Components手动指定hourCycle = .oneToTwelve,系统的本地化规则会覆盖这个单独设置——区域整体的格式规则优先级高于单个属性。 - 预定义timeStyle的限制:当使用
DateFormatter的预定义时间样式(比如.medium)时,Formatter会直接采用区域默认的时间模板,不会单独读取hourCycle属性。
解决办法
方法一:使用自定义本地化日期模板
放弃预定义的timeStyle,直接指定包含12小时制的格式模板,让Formatter遵循自定义规则:
var components = Locale.Components(languageCode: "en", languageRegion: "GB") components.hourCycle = .oneToTwelve let locale = Locale(components: components) let timeZone = TimeZone(secondsFromGMT: 0)! let iso = ISO8601DateFormatter() iso.formatOptions = [.withInternetDateTime] let date = iso.date(from: "2000-01-01T13:16:45Z")! let df = DateFormatter() df.locale = locale df.timeZone = timeZone // 用setLocalizedDateFormatFromTemplate指定12小时制模板 df.setLocalizedDateFormatFromTemplate("h:mm:ss a") let s = df.string(from: date) print(s) // 输出:1:16:45 PM
方法二:切换到默认12小时制的区域
如果不需要保留en-GB的其他本地化特性,直接使用默认12小时制的区域标识(比如en-US),配合预定义timeStyle即可生效:
let locale = Locale(identifier: "en-US") let timeZone = TimeZone(secondsFromGMT: 0)! let iso = ISO8601DateFormatter() iso.formatOptions = [.withInternetDateTime] let date = iso.date(from: "2000-01-01T13:16:45Z")! let df = DateFormatter() df.locale = locale df.timeZone = timeZone df.timeStyle = .medium let s = df.string(from: date) print(s) // 输出:1:16:45 PM
方法三:给关联的Calendar设置hourCycle
通过给DateFormatter绑定的Calendar也设置hourCycle,让Formatter遵循Calendar的配置:
var components = Locale.Components(languageCode: "en", languageRegion: "GB") components.hourCycle = .oneToTwelve let locale = Locale(components: components) let timeZone = TimeZone(secondsFromGMT: 0)! var calendar = Calendar(identifier: .gregorian) calendar.locale = locale calendar.timeZone = timeZone calendar.hourCycle = .oneToTwelve // 同步设置Calendar的hourCycle let iso = ISO8601DateFormatter() iso.formatOptions = [.withInternetDateTime] let date = iso.date(from: "2000-01-01T13:16:45Z")! let df = DateFormatter() df.locale = locale df.timeZone = timeZone df.calendar = calendar // 绑定配置好的Calendar df.timeStyle = .medium let s = df.string(from: date) print(s) // 输出:1:16:45 PM
内容的提问来源于stack exchange,提问作者john07
相关产品推荐
相关产品推荐

