Swift -从ISO 8601日期字符串检索时区

yx2lnoni  于 2022-11-28  发布在  Swift
关注(0)|答案(3)|浏览(212)

我在数据库中保存的日期格式为“yyyy-MM-dd 'T'HH:mm:ssZ”。例如,“2018-05- 17 T11:15:00+0330”。时区不同,它是在用户的本地时区。
我想检索和显示日期,如“May 17,2018 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://stackoverflow.com/a/46216251/1373592的内容?

  • 谢谢-谢谢
oprakyz7

oprakyz71#

你真正想做的是忽略时区。
您可以从日期字符串中去掉最后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类似的库。

hm2xizp9

hm2xizp92#

这里是我刚刚开发的TimeZone的一个小扩展。你可以使用它从ISO 8601日期字符串创建一个TimeZone。它将以下列格式处理字符串中的时区:

  • Z(表示UTC时间)
  • +/-小时
  • +/-嗯嗯
  • +/-小时:毫米

下面是扩展名:

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)
}
lf5gs5x2

lf5gs5x23#

快速修复@rmaddy答案,因为他的答案有一个负偏移的问题,特别是@jjoelson提到的分钟分量

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)), var min = Int(tz.dropFirst(3)) {
                min = (hour < 0) ? -1 * min : min
                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]), var min = Int(parts[1]) {
                    min = (hour < 0) ? -1 * min : min
                    self.init(secondsFromGMT: (hour * 60 + min) * 60)
                    return
                }
            }
        }
        return nil
    }
}

相关问题