You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Locale.autoupdatingCurrent与固定Locale的行为差异及hourCycle失效问题

手动设置Locale的hourCycle后DateFormatter不生效的原因及解决办法

原因

  1. 区域默认格式优先级更高:en-GB这类区域本身默认使用24小时制,即使通过Locale.Components手动指定hourCycle = .oneToTwelve,系统的本地化规则会覆盖这个单独设置——区域整体的格式规则优先级高于单个属性。
  2. 预定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 19:40:29