0

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?

Awad
  • 823
  • 3
  • 11
  • 33
  • Do you simply need the components to for example construct a `String`? – henrik-dmg Nov 20 '19 at 16:32
  • I am not sure I understand what you mean? – Awad Nov 20 '19 at 16:43
  • The current date and time of another time is the exact same as the current time, apart from a timezone hour offset. To me it's not really clear what you're trying to achieve. Generally it's advisable to work with UTC dates – henrik-dmg Nov 20 '19 at 16:45
  • 1
    Do you need to schedule a job in your local timezone when it's a certain time in another timezone? i.e. do you need to know the UTC time when it's (for example) 19:45 in Australia? – flanker Nov 20 '19 at 16:47
  • possible duplicate of https://stackoverflow.com/a/46660225/2303865 – Leo Dabus Nov 20 '19 at 16:50
  • related https://stackoverflow.com/questions/28332946/how-do-i-get-the-current-date-in-short-format-in-swift/28347285?r=SearchResults&s=1|22.3121#28347285 – Leo Dabus Nov 20 '19 at 16:50
  • @henrik-dmg, I am actually interested in getting the times relative to the target timezone. – Awad Nov 20 '19 at 16:51
  • @LeoDabus, please read my question again, this is totally different things I am asking for. – Awad Nov 20 '19 at 16:52
  • @flanker, this is exactly what I am trying to do at the bottom of it. – Awad Nov 20 '19 at 16:58

4 Answers4

4

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)

trndjc
  • 11,654
  • 3
  • 38
  • 51
2
func getDateAndTime(timeZoneIdentifier: String) -> String? {

    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ssZ"
    dateFormatter.timeZone = TimeZone(identifier: timeZoneIdentifier)

    return dateFormatter.string(from: Date())
}

print(getDateAndTime(timeZoneIdentifier: "UTC")) //2019-11-20 23:37:28 091
Magy Elias
  • 31
  • 4
0

You need to convert UTC time into local timezone. Here is the code to convert it.

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss SSS"
formatter.locale = Locale.current
formatter.timeZone = TimeZone.current
let date = dateFormatter.date(from: utcDate)

Here change utcDate with date you want to convert to local.

Gaurav Parvadiya
  • 149
  • 2
  • 11
0

I wanted the time in a simple format. ie 11:23pm in the users current locale setting.

Here's how I did it:

func getTimeWithLocale(with timeZone: String) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .none
        dateFormatter.timeStyle = .short
        dateFormatter.timeZone = TimeZone(identifier: timeZone)
        dateFormatter.locale = .current
        
        let time = dateFormatter.string(from: Date()).lowercased().replacingOccurrences(of: " ", with: "")
        
        return time
    }
Weston Mitchell
  • 192
  • 1
  • 12