简体   繁体   English

从 TimeZone.abbreviation() 初始化 TimeZone 时遇到问题

[英]Trouble Initializing TimeZone from TimeZone.abbreviation()

I am storing user birth dates on my backend via storing a date component dictionary.我通过存储日期组件字典在后端存储用户出生日期。 It looks something like this:它看起来像这样:

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

To store this object, it grabs the user's birth day, month, and year from user input.为了存储这个 object,它从用户输入中获取用户的生日、月份和年份。 The user time zone, however, is gathered via TimeZone.current.abbreviation() .但是,用户时区是通过TimeZone.current.abbreviation()收集的。

Now, some of my user birthdate objects on my backend have their "timeZone" formatted as "CST" , "BST" , or "PDT" .现在,我后端的一些用户生日对象的"timeZone"格式为"CST""BST""PDT" "timeZone" s that are formatted this way successfully initialize a TimeZone on the front end via let timeZone = TimeZone(abbreviation: "CST")!以这种方式格式化的"timeZone"通过let timeZone = TimeZone(abbreviation: "CST")!成功地在前端初始化了一个TimeZone , let timeZone = TimeZone(abbreviation: "BST")! , let timeZone = TimeZone(abbreviation: "BST")! , or let timeZone = TimeZone(abbreviation: "PDT")! , 或者let timeZone = TimeZone(abbreviation: "PDT")! , respectively. , 分别。

The problem is, other user birthdate objects on my backend have their "timeZone" formatted as "GMT+8" .问题是,我后端的其他用户生日对象的"timeZone"格式为"GMT+8" When trying to initialize "timeZone" s formatted like this via let timeZone = TimeZone(abbreviation: "GMT+8")!当尝试通过let timeZone = TimeZone(abbreviation: "GMT+8")!初始化像这样格式化的"timeZone"时! , the initialization returns nil . ,初始化返回nil I also tried let timeZone = TimeZone(identifier: "GMT+8")!我也试过let timeZone = TimeZone(identifier: "GMT+8")! , but this returns nil as well. , 但这也返回nil

Is there a way to initialize a TimeZone when it is formatted with respect to its offset to GMT as opposed to its unique abbreviation?TimeZone相对于 GMT 的偏移量而不是其唯一的缩写进行格式化时,有没有办法初始化它? I've seen a TimeZone initializer that is TimeZone(secondsFromGMT: Int) .我见过一个TimeZone初始化程序,它是TimeZone(secondsFromGMT: Int) Could I simply take the 8 from "GMT+8" and multiply it by 3600 (the number of seconds in an hour) and pass this result to TimeZone(secondsFromGMT: Int) ?我可以简单地将“GMT+ 8 "GMT+8"中的 8 乘以3600 (一小时的秒数)并将结果传递给TimeZone(secondsFromGMT: Int)吗?

I ended up writing code that adapts my application to account for these unexpected fringe cases where a TimeZone's abbreviation is formatted like "GMT+8" rather than "SGT" .我最终编写了代码来调整我的应用程序,以解决这些意外的边缘情况,其中 TimeZone 的缩写格式类似于"GMT+8"而不是"SGT" I created an extension to TimeZone :我创建了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
        }
    }
}

It is used like so:它是这样使用的:

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

My BirthDate class for context:我的出生日期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
    }
}

Time zones are funny things to work with.时区是有趣的事情。 If anybody sees issue with the TimeZone extension above, please let me know.如果有人发现上面的TimeZone扩展存在问题,请告诉我。 I think I've accounted for all scenarios, but could be mistaken.我想我已经考虑了所有情况,但可能会出错。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM