Search code examples
swiftswiftdate

How to get the current date and time of another timezone in Swift?


I have a scheduled job that needs to run against different time windows in different timezones. Ultimately, knowing UTC time when it's (for example) 20:00 in Australia, in order to kick off the job for this area.

UPDATE

More details about my use case: I have a scheduled job that needs to run every i.e few hours. Which does some Redis cache cleaning for different clients.

This job needs to run when it is after office hours for each of my clients, which is in respect to their timezones.

I have the timezone of each of my clients. However, I need to find out the time for each timezones in order to be able to run the clean up job for each of my clients.

I was not able to find an example on how to get the time of another timezone in Swift?


Solution

  • There are a number of ways to get a local time, such as using string time zone identifiers and seconds from GMT. And there are a number of formats to express time, such as strings and native Date objects. You didn't specify much in your question, so here's a starting point:

    func localTime(in timeZone: String) -> String {
        let f = ISO8601DateFormatter()
        f.formatOptions = [.withInternetDateTime]
        f.timeZone = TimeZone(identifier: timeZone)
        return f.string(from: Date())
    }
    
    print(localTime(in: "Asia/Tehran")) // 2019-11-20T20:17:13+03:30 (8:17 PM)
    

    How many time zones there are in the world is not entirely definitive but the general consensus appears to be 38. I prefer using secondsFromGMT because it's more deterministic than using string identifiers because the string identifiers are subject to change (as this is a Swift library), while secondsFromGMT cannot (without a change in the timezone itself).

    // For a list of all time zone string identifiers
    for timeZone in TimeZone.knownTimeZoneIdentifiers {
        print(timeZone)
    }
    

    Unfortunately, secondsFromGMT does not recognize fractional time zones, and there are quite a few; therefore, we can use both methods to get a complete list of 38:

    -12:00 TimeZone(secondsFromGMT: -43200)
    -11:00 TimeZone(secondsFromGMT: -39600)
    -10:00 TimeZone(secondsFromGMT: -36000)
    -09:30 TimeZone(identifier: "Pacific/Marquesas")
    -09:00 TimeZone(secondsFromGMT: -32400)
    -08:00 TimeZone(secondsFromGMT: -28800)
    -07:00 TimeZone(secondsFromGMT: -25200)
    -06:00 TimeZone(secondsFromGMT: -21600)
    -05:00 TimeZone(secondsFromGMT: -18000)
    -04:00 TimeZone(secondsFromGMT: -14400)
    -03:30 TimeZone(identifier: "America/St_Johns")
    -03:00 TimeZone(secondsFromGMT: -10800)
    -02:00 TimeZone(secondsFromGMT: -7200)
    -01:00 TimeZone(secondsFromGMT: -3600)
    +00:00 TimeZone(secondsFromGMT: 0)
    +01:00 TimeZone(secondsFromGMT: 3600)
    +02:00 TimeZone(secondsFromGMT: 7200)
    +03:00 TimeZone(secondsFromGMT: 10800)
    +03:30 TimeZone(identifier: "Asia/Tehran")
    +04:00 TimeZone(secondsFromGMT: 14400)
    +04:30 TimeZone(identifier: "Asia/Kabul")
    +05:00 TimeZone(secondsFromGMT: 18000)
    +05:30 TimeZone(identifier: "Asia/Colombo")
    +05:45 TimeZone(identifier: "Asia/Kathmandu")
    +06:00 TimeZone(secondsFromGMT: 21600)
    +06:30 TimeZone(identifier: "Asia/Yangon")
    +07:00 TimeZone(secondsFromGMT: 25200)
    +08:00 TimeZone(secondsFromGMT: 28800)
    +08:45 TimeZone(identifier: "Australia/Eucla")
    +09:00 TimeZone(secondsFromGMT: 32400)
    +09:30 TimeZone(identifier: "Australia/Adelaide")
    +10:00 TimeZone(secondsFromGMT: 36000)
    +10:30 TimeZone(identifier: "Australia/Lord_Howe")
    +11:00 TimeZone(secondsFromGMT: 39600)
    +12:00 TimeZone(secondsFromGMT: 43200)
    +12:45 TimeZone(identifier: "Pacific/Chatham")
    +13:00 TimeZone(secondsFromGMT: 46800)
    +14:00 TimeZone(secondsFromGMT: 50400)