Swift - 从 ISO8601 日期字符串中检索时区

SKT*_*SKT 6 swift

我将日期以这种格式保存在数据库中 - “yyyy-MM-dd'T'HH:mm:ssZ”。例如,“2018-05-17T11:15:00+0330”。时区各不相同,无论用户的本地时区是什么。

我想检索并显示“2018 年 5 月 17 日 11 点 15 分”之类的日期,将日期/时间保持在与保存时相同的时区。我怎样才能做到这一点?

我试过这个。

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))
Run Code Online (Sandbox Code Playgroud)

但是我在本地时区获取 Date 对象并将其转换为日期字符串也会在我的本地时区显示日期。

在 Swift 中有这样的东西吗,https ://stackoverflow.com/a/46216251/1373592?

谢谢。

Swe*_*per 5

您真正想做的是忽略时区。

您可以从日期字符串中去掉最后 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))
Run Code Online (Sandbox Code Playgroud)

请注意,您无法将此日期与其他日期进行比较,因为您已删除其时区。

此外,SwiftDate是一个与 JodaTime 类似的库。


rma*_*ddy 5

TimeZone这是我刚刚想到的一点扩展。TimeZone您可以使用它从 ISO8601 日期字符串创建一个。它将按以下格式处理字符串中的时区:

  • Z(UTC 时间)
  • +/-HH
  • +/-时时毫米
  • +/-HH:毫米

这是扩展:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个测试:

print(TimeZone(iso8601: "2018-05-17T11:15:00+0330"))
Run Code Online (Sandbox Code Playgroud)

您可以结合此解析和格式化,以便最终结果采用原始时区。

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)
}
Run Code Online (Sandbox Code Playgroud)