12

如果您的 iOS 设备设置为使用默认为 12 小时制的地区(例如美国),并且您的DateFormatter设置如下:

var dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateFormat = "h:mm a"
    
    return formatter
}()

然后,如果在 iOS 设置中的日期和时间中打开“24 小时制”开关,它将以 24 小时格式输出时间。

如果您的自定义日期格式是“H:mm”,即 24 小时,并且您仍处于默认 12 小时区域,那么无论 24 小时开关的开/关状态如何,它都会输出 24 小时时间。

好的,很好,很简单,我将只使用“h:mm a”,然后用户将看到根据他们喜欢的格式显示的任何时间。但是,如果您将您的区域更改为默认使用 24 小时时间的区域,则行为会相反!如果您有“H:mm”并且 24 小时时间开关处于关闭状态,它将更改为 12 小时时间(“h:mm a”)。

是的,您通常可以通过使用时间样式(formatter.timeStyle = .short例如)而不是使用自定义日期格式来避免这种情况,但是如果您需要自定义日期格式并且想要尊重用户的设置,您应该怎么做?(例如,如果您需要在字符串中插入一些自定义字符,或者只是想让组件以非标准顺序排列)

我想在这里吃蛋糕和吃蛋糕的唯一方法是提前检查用户的偏好是什么(据我所知,你不能直接做到这一点)或者语言环境的默认设置是什么(我虽然看不到任何方法)然后相应地调整格式......</p>

我制作了这个 Xcode 项目是为了更清楚地演示这个问题(显然它必须在设备上运行,因为模拟器上没有 24 小时时间开关)。

我知道有各种解决方法,但我不明白如果您正在制作一个使用自定义日期/时间格式的 UI 并且拥有来自世界不同地区的用户的应用程序,Apple 希望您做什么?我错过了什么还是这是iOS中的一个缺陷?

注意:这个问题专门关于将日期转换为字符串以进行显示,所以我想尽可能尊重用户的语言环境和其他设置。我知道您可以将语言环境设置为 en_POSIX 等,但这并不能解决问题。我还希望尽可能无缝地实现这一点,并利用内置的任何功能,但这似乎不可能,除非您只针对具有相同默认 24 小时时间设置的区域中的用户......</p >

4

1 回答 1

24

on的文档中dateFormatDateFormatter

您应该只在使用固定格式表示时设置此属性,如使用固定格式日期表示中所述。对于用户可见的表示,您应该使用 dateStyle 和 timeStyle 属性,或者如果使用预定义的样式无法实现所需的格式,则应使用 setLocalizedDateFormatFromTemplate(_:) 方法;这两个属性和此方法都提供了适合向用户显示的本地化日期表示。

如果您没有在日期格式化程序上使用固定的语言环境,我仍然不明白为什么 Foundation 会费心修改日期格式,但似乎文档不建议将自定义日期格式用于非固定格式表示。

setLocalizedDateFormatFromTemplate如果您不能仅仅依赖dateStyleand ,这似乎是您所需要的timeStyle,尽管它似乎不会随着用户的 24 小时时间设置而自动更改,因此可以在指定模板之前检查 24 小时时间是否开启…… </p>

此方法应该允许您指定格式,而不会丢失特定于每个语言环境的格式。

来自 Apple Developer Relations 的编辑回复(相同的想法,但更详细):

处理此问题的正确方法是避免根据语言环境指定“hh”或“HH”,而是将“jj”骨架符号与-[NSDateFormatter setLocalizedDateFormatFromTemplate:].

从日期字段符号表 ( https://www.unicode.org/reports/tr35/tr35-dates.html#dfst-hour )的“小时”部分:

输入骨架符号 在这样的上下文中,它请求区域设置的首选小时格式(h、H、K 或 K),由补充数据中 hours 元素的首选属性确定。

通过使用“jj”,您可以获得最符合用户当前设置的格式:

NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setLocalizedDateFormatFromTemplate:@"jj:mm"];
NSLog(@"%@: 'jj:mm' => '%@' ('%@')", formatter.locale.localeIdentifier, formatter.dateFormat, [formatter stringFromDate:[NSDate date]]);

结果是

  • en_US (12 小时): "en_US: 'jj:mm' => 'h:mm a' ('1:44 PM')
  • en_US(24 小时):“en_US: 'jj:mm' => 'HH:mm' ('13:44')
  • en_GB (12 小时): "en_GB: 'jj:mm' => 'h:mm a' ('1:44 pm')
  • en_GB (24 小时): "en_GB: 'jj:mm' => 'HH:mm' ('13:44')

这允许您匹配您的首选格式,同时与用户的首选时间设置保持一致。

于 2018-04-19T22:44:00.853 回答