Raunak
Raunak

Reputation: 3414

Create TimeZone object from timeZoneOffset string?

What would be a clean way to initialise a Swift TimeZone object from timeZoneOffset string of the form: "+HH:MM".

I am looking for something of the form:

extension TimeZone {

    init?(UTCOffsetString ofs: String) {

        let signIndex = ofs.firstIndex(of: "+") ?? ofs.firstIndex(of: "-")
        let sign = ofs[signIndex!]

        let separatorIndex = ofs.firstIndex(of: ":")!

        let hhRange = ofs.index(signIndex!, offsetBy: 1)..<separatorIndex
        let hh = ofs[hhRange]

        let mmRange = ofs.index(separatorIndex, offsetBy: 1)..<ofs.index(separatorIndex, offsetBy: 3)
        let mm = ofs[mmRange]

        var offsetInMin = (Int(String(hh))! * 60) + Int(String(mm))!
        if sign == "-" {
            offsetInMin.negate()
        }

        let offsetInSec = offsetInMin * 60
        // Convert string to TimeZone, eg.
        self.init(secondsFromGMT: offsetInSec)
    }

}

let tz = TimeZone.init(UTCOffsetString: "-07:30")
print(tz?.identifier ?? "unknown")

The above code block is a correct solution and prints:

GMT-0730

However I am looking for a cleaner solution where I don't need to extract substrings in order to compute the offset.

Upvotes: 0

Views: 210

Answers (2)

vadian
vadian

Reputation: 285069

My suggestion is to use DateFormatter which is able to parse the time zone string format. refZoneString is the reference to UTC in the current time zone.

extension TimeZone {

    init?(UTCOffsetString ofs: String) {
        let refZoneString = "+0000"
        let formatter = DateFormatter()
        formatter.dateFormat = "Z"
        guard let refDate = formatter.date(from: refZoneString),
            let date = formatter.date(from: ofs) else { return nil }
        self.init(secondsFromGMT: Calendar.current.dateComponents([.second], from: date, to: refDate).second!)
    }
}

let tz = TimeZone.init(UTCOffsetString: "-07:30")
print(tz?.identifier ?? "unknown")

Upvotes: 2

Leo Dabus
Leo Dabus

Reputation: 236295

I don't know what you mean by a cleaner but you can combine collection methods suffix and prefix to avoid the need to use String index to access the desired values:

let time = "-02:00"
let hours = Int(time.suffix(5).prefix(2)) ?? 0
let minutes = Int(time.suffix(2)) ?? 0

var offset = hours * 3600 + minutes * 60   
if time.first == "-" { offset = -offset }

print(offset)  // -7200 

Upvotes: 0

Related Questions