【问题标题】:Trouble Initializing TimeZone from TimeZone.abbreviation()从 TimeZone.abbreviation() 初始化 TimeZone 时遇到问题
【发布时间】:2019-11-05 18:54:34
【问题描述】:

我通过存储日期组件字典在后端存储用户出生日期。它看起来像这样:

{
    "day": 1,
    "month": 1,
    "year": 1970,
    "timeZone": "GMT"
}

为了存储这个对象,它从用户输入中获取用户的生日、月份和年份。但是,用户时区是通过TimeZone.current.abbreviation() 收集的。

现在,我后端的一些用户生日对象的"timeZone" 格式为"CST""BST""PDT"。以这种方式格式化的"timeZone"s 分别通过let timeZone = TimeZone(abbreviation: "CST")!let timeZone = TimeZone(abbreviation: "BST")!let timeZone = TimeZone(abbreviation: "PDT")! 在前端成功初始化TimeZone

问题是,我后端的其他用户生日对象的"timeZone" 格式为"GMT+8"。当尝试通过let timeZone = TimeZone(abbreviation: "GMT+8")! 初始化像这样格式化的"timeZone"s 时,初始化返回nil。我也试过let timeZone = TimeZone(identifier: "GMT+8")!,但这也返回nil

TimeZone 的格式是相对于其与 GMT 的偏移量而不是其唯一的缩写时,有没有办法初始化它?我见过TimeZone 初始化程序是TimeZone(secondsFromGMT: Int)。我可以简单地从"GMT+8" 中取出8 并乘以3600(一小时的秒数)并将这个结果传递给TimeZone(secondsFromGMT: Int)

【问题讨论】:

  • 避免使用时区缩写。它们不是唯一的,也不是每个时区都有一个有用的缩写。使用时区标识符或偏移量。
  • 扩展 rmaddy 的评论 - “CST”可能是“Central Standard Time”,也可能是“China Standard Time”或“Cuba Standard Time”。 “BST”可能是“英国夏令时间”,也可能是“孟加拉国标准时间”或“布干维尔标准时间”。
  • @DavidChopin 酷。精确没有错! :)
  • @DavidChopin 是的,如果没有太多麻烦,最好发布一个有效的答案 - 可能会帮助处于类似情况的其他人。
  • 我继续发布了一些内容,以防将来对某人有所帮助。

标签: ios swift timezone nstimezone


【解决方案1】:

我最终编写了代码来调整我的应用程序,以解决这些意外的边缘情况,其中 TimeZone 的缩写格式类似于 "GMT+8" 而不是 "SGT"。我为TimeZone创建了一个扩展:

extension TimeZone {
    static func timeZone(from string: String) -> TimeZone {
        //The string format passed into this function should always be similar to "GMT+8" or "GMT-3:30"

        if string.contains("±") {
            //This case should always be "GMT±00:00", or simply GMT
            return TimeZone(secondsFromGMT: 0)!
        } else {

            //If the string doesn't contain "±", then there should be some offset. We will split the string into timeZone components. "GMT+8" would split into ["GMT", "8"]. "GMT-3:30" would split int ["GMT","3","30"]
            let timeZoneComponents = string.components(separatedBy: CharacterSet(charactersIn: "+-:"))
            var isAheadOfGMT: Bool!

            //Check if the string contains "+". This will dictate if we add or subtract seconds from GMT
            if string.contains("+") {
                isAheadOfGMT = true
            } else {
                isAheadOfGMT = false
            }

            //Grab the second element in timeZoneElements. This represents the offset in hours
            let offsetInHours = Int(timeZoneComponents[1])!

            //Convert these hours into seconds
            var offsetInSeconds: Int!
            if isAheadOfGMT {
                offsetInSeconds = offsetInHours * 3600
            } else {
                offsetInSeconds = offsetInHours * -3600
            }

            //Check if there is a colon in the passed string. If it does, then there are additional minutes we need to account for
            if string.contains(":") {
                let additionalMinutes = Int(timeZoneComponents[2])!
                let additionalSeconds = additionalMinutes * 60
                offsetInSeconds += additionalSeconds
            }

            //Create a TimeZone from this calculated offset in seconds
            let timeZoneFromOffset = TimeZone(secondsFromGMT: offsetInSeconds)!

            //Return this value
            return timeZoneFromOffset
        }
    }
}

它是这样使用的:

let json: [String:String] = ["timeZone":"GMT+8"]
let timeZone = json["timeZone"]
let birthDate: BirthDate!
if let timeZoneFromAbbrev = TimeZone(abbreviation: timeZone) {
    birthDate = BirthDate(day: birthDay, month: birthMonth, year: birthYear, timeZone: timeZoneFromAbbrev)
} else {       
    let timeZoneFromOffset = TimeZone.timeZone(from: timeZone)
    print(timeZoneFromOffset.abbreviation())
    //Prints "GMT+8"

    birthDate = BirthDate(day: birthDay, month: birthMonth, year: birthYear, timeZone: timeZoneFromOffset)
}

我的BirthDate 上下文类:

class BirthDate {
    var day: Int
    var month: Int
    var year: Int
    var timeZone: TimeZone

    init(day: Int, month: Int, year: Int, timeZone: TimeZone) {
        self.day = day
        self.month = month
        self.year = year
        self.timeZone = timeZone
    }
}

时区是很有趣的事情。如果有人发现上面的 TimeZone 扩展存在问题,请告诉我。我想我已经考虑了所有情况,但可能会出错。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-07
    相关资源
    最近更新 更多