在我们的应用程序中,存在从字符串创建日期的问题,但只能通过非常特定的组合进行复制.不幸的是,无法从遇到问题的用户那里获得它,因此我决定try 各种可能的组合:

import Foundation

var dateOnlyDateFormatter: (String, String) -> DateFormatter = { timeZoneS, localeS in
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    formatter.timeZone = TimeZone(identifier: timeZoneS)
    formatter.locale = Locale(identifier: localeS)
    return formatter
}

let date = "2022-05-27"
let time = "06:15"

for timeZone in TimeZone.knownTimeZoneIdentifiers {
    for locale in Locale.availableIdentifiers {
        let dateFormatter = dateOnlyDateFormatter(timeZone, locale)
        let printDate = dateFormatter.date(from: date)
        if printDate == nil {
            print("TimeZone: \(timeZone), Locale: \(locale)")
        }
    }
}

结果:

TimeZone: America/Asuncion, Locale: ar_SA
TimeZone: America/Asuncion, Locale: en_SA

我不太确定处理这个问题的最佳方式是什么.很明显,我们的BE可以使用一个特定的区域设置返回日期,比如en_US_POSIX,但我几乎无法控制它,因为它是一个更大的旧系统的一部分.有没有人经历过这样的问题?

推荐答案

如果您阅读DateFormatter份文档中的"Working With Fixed Format Date Representations"部分,您会发现:

对于大多数固定格式,还应将locale属性设置为POSIX语言环境("en\u US\u POSIX"),并将timeZone属性设置为UTC.

你应该听从这里的建议...但这可能是SA和巴拉圭时区产生零的原因.

在该部分的下一部分,有一个指向technical Q&A的链接,其中对这一点进行了更详细的解释.与您的问题最相关的部分是:

用户可以更改日历(在OS X上使用"系统首选项">;"语言"&地区">;"日历",或在iOS上使用"设置">;"常规">;"国际">;"日历").在这种情况下,NSDateFormatter将把您解析的字符串中的数字视为用户 Select 的日历中的数字.例如,如果用户 Select 佛历,解析"2010"年将在1467中生成NSDate,因为佛历上的2010年是我们每天使用的(公历)日历上的1467年.

在区域设置SA中,日期字符串的数字似乎是使用Islamic Calendar来解释的.使用en\u SA和America/New\u York格式查看今天的日期.

let dateFormatter = dateOnlyDateFormatter("America/New_York", "en_SA")
let printDate = dateFormatter.string(from: .init())
print(printDate)
// 1443-10-26

还可以查看由en\u SA和America/New\u York解析的非零日期

let dateFormatter = dateOnlyDateFormatter("America/New_York", "en_SA")
let printDate = dateFormatter.date(from: date)
print(printDate)
// 2583-10-05 04:00:00 +0000

请注意,10-05是2583年的第一个星期日(请参见this calendar).如果巴拉圭仍像现在2583年那样使用the same DST rules,则意味着在2583-10-05 00:00:00,即DST周期开始时,存在DST缺口过渡.将跳过从00:00:00开始的小时,因此00:00:00将不存在.

仅解析日期时,DateFormatter将try 在格式化程序的时区中将时间组件设置为00:00:00,但00:00:00不存在,因此解析失败.


在任何情况下,设置dateFormat后,只需将locale设置为posix,将timeZone设置为UTC.

Ios相关问答推荐

如何从ipad获取用户定义的设备名称,IOS版本应大于16在flutter

Xcode15.3上的生成错误:调用的对象类型';facebook::flipper::SocketCertificateProvider';不是函数或函数指针

SWIFT设备方向更新不正确

如何修复使用EFCore和SQLite的.Net MAUI iOS应用程序上的当前应用程序不支持NullabilityInfoContext?

设置托管在DigitalOcean上的iOS通用链接

自定义UIControl不适用于UITapGestureRecognizer

OBJC @selector 在另一个实现中不起作用

为什么在Actor内部使用withTaskGroupwork并行运行?

SwiftUI HStack 文本字段对齐

DllImport with .a file for iOS in MAUI

SwiftUI 中的描边图像边框

来自 c++ 的runtime_error未在 iOS 中捕获

SwiftUI - 在ForEach的每个元素之间自动添加分隔符

iPhone 6 和 6 Plus 媒体查询

iOS 中是否有用于自定义振动的 API?

用 PC 调试 ipad safari

如何在 OS X 或 iOS(不使用格式塔)中确定运行时的操作系统版本?

Xcode 8:函数类型不能有参数标签 destruct 我的构建

SLComposeViewController 分享教程

如果我的分发证书过期会怎样?