代码之家  ›  专栏  ›  技术社区  ›  shim

如何在日期格式化程序的日期和时间设置中正确支持iOS 12小时/24小时时间覆盖?

  •  12
  • shim  · 技术社区  · 6 年前

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

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

    然后,如果打开“24小时时间”开关,它将以24小时格式输出时间 在…上 输入日期(&N);iOS设置中的时间。

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

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

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

    我想在这里吃蛋糕的唯一方法就是事先检查用户的偏好(你可以 can't really do directly ,据我所知)或者可能是语言环境的默认值(我不知道 any way to do that 然后相应地调整格式

    我做了 this Xcode project 为了更清楚地演示问题(显然,它必须在设备上运行,因为模拟器上没有24小时时间开关)。

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

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

    1 回复  |  直到 3 年前
        1
  •  24
  •   shim    6 年前

    从…起 the documentation for dateFormat on DateFormatter :

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

    我仍然不明白,如果您在日期格式化程序中没有使用固定的区域设置,为什么Foundation会费心修改日期格式,但文档似乎不建议对非固定格式表示使用自定义日期格式。

    setLocalizedDateFormatFromTemplate 如果你不能仅仅依靠 dateStyle timeStyle ,虽然它似乎不会随用户的24小时时间设置自动更改,因此可以在指定模板之前检查24小时时间是否已打开

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

    编辑苹果开发者关系部的回复(想法相同,但更详细):

    正确的处理方法是避免指定“hh”或“hh” 基于区域设置,而不是在中使用“jj”骨架符号 与一起使用 -[NSDateFormatter setLocalizedDateFormatFromTemplate:]

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

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

    通过使用“jj”,您可以获得与用户的 当前设置:

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

    结果在

    • en\u-US(12小时):“en\u-US:‘jj:mm’=>‘h:mm a’(‘下午1:44’)
    • en\u-US(24小时):“en\u-US:‘jj:mm’=>‘HH:mm’('13:44’)
    • en\U GB(12小时):“en\U GB:‘jj:mm’=>‘h:mm a’(‘下午1:44’)
    • en\u GB(24小时):“en\u GB:‘jj:mm’=>‘HH:mm’('13:44’)

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