Swift - 从 ISO8601 日期字符串中检索时区
Posted
技术标签:
【中文标题】Swift - 从 ISO8601 日期字符串中检索时区【英文标题】:Swift - Retrieve timezone from ISO8601 date string 【发布时间】:2018-05-17 06:12:52 【问题描述】:我有日期以这种格式保存在数据库中 - “yyyy-MM-dd'T'HH:mm:ssZ”。例如,“2018-05-17T11:15:00+0330”。时区各不相同,无论用户的本地时区是什么。
我想检索并显示像“2018 年 5 月 17 日 11.15AM”这样的日期,将日期/时间与保存时保持在同一时区。我该怎么做?
我试过了。
let dateString = "2018-05-17T11:15:00+0330"
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
//formatter.timeZone = ???
print(formatter.date(from: dateString))
但是我得到了本地时区的 Date 对象,并将其转换为日期字符串也会显示我本地时区的日期。
在 Swift 中有这样的东西吗,https://***.com/a/46216251/1373592?
谢谢。
【问题讨论】:
【参考方案1】:你真正想做的是忽略时区。
您可以从日期字符串中去掉最后 5 个字符,以一种格式对其进行解析,然后将其格式化为另一种格式:
let dateString = "2018-05-17T11:15:00+0330"
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
let date = formatter.date(from: String(dateString.dropLast(5)))! // note the stripping off here
formatter.dateFormat = "MMMM d, yyyy hh.mma"
print(formatter.string(from: date))
请注意,您无法将该日期与其他日期进行比较,因为您已经剥离了它的时区。
另外,SwiftDate 是一个类似于 JodaTime 的库。
【讨论】:
这给出了最终字符串的正确输出,但date
位于错误的时区,如果需要与其他日期进行任何比较,您将得到意想不到的结果。
@rmaddy 是的,这是真的。添加了警告。【参考方案2】:
这是对TimeZone
的一个小扩展,我刚刚开始。您可以使用它从 ISO8601 日期字符串创建 TimeZone
。它将以下列格式处理字符串中的时区:
这是扩展名:
extension TimeZone
init?(iso8601: String)
let tz = iso8601.dropFirst(19) // remove yyyy-MM-ddTHH:mm:ss part
if tz == "Z"
self.init(secondsFromGMT: 0)
else if tz.count == 3 // assume +/-HH
if let hour = Int(tz)
self.init(secondsFromGMT: hour * 3600)
return
else if tz.count == 5 // assume +/-HHMM
if let hour = Int(tz.dropLast(2)), let min = Int(tz.dropFirst(3))
self.init(secondsFromGMT: (hour * 60 + min) * 60)
return
else if tz.count == 6 // assime +/-HH:MM
let parts = tz.components(separatedBy: ":")
if parts.count == 2
if let hour = Int(parts[0]), let min = Int(parts[1])
self.init(secondsFromGMT: (hour * 60 + min) * 60)
return
return nil
还有一个测试:
print(TimeZone(iso8601: "2018-05-17T11:15:00+0330"))
您可以结合此解析和格式化,以便最终结果在原始时区中。
let dateString = "2018-05-17T11:15:00+0330"
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
formatter.locale = Locale(identifier: "en_US_POSIX")
if let date = formatter.date(from: dateString), let tz = TimeZone(iso8601: dateString)
let newFmt = DateFormatter()
newFmt.dateStyle = .medium
newFmt.timeStyle = .short
newFmt.timeZone = tz
let newString = newFmt.string(from: date)
print(newString)
【讨论】:
我认为这处理负偏移不正确。例如。 “2020-01-01T09:15:00-02:15”从 GMT 产生 -6300 秒而不是 -8100 秒,因为此代码将小时部分视为负数,而将分钟部分视为正数。以上是关于Swift - 从 ISO8601 日期字符串中检索时区的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 中解析/创建格式为小数秒 UTC 时区(ISO 8601、RFC 3339)的日期时间戳?