Home > database >  When parsing a date from a string, how can I stop it from being converted to local time?
When parsing a date from a string, how can I stop it from being converted to local time?

Time:05-25

When I convert any sort of timestamp to a date, whether it be UTC or with another offset, it converts it to my local time. How can I stop it from doing that?

As an example, the following code prints out 2022-05-24 09:40:11 0000 but it should show up as 2022-05-24 01:40:11 0000. I do not want the equivalent time in my own time zone that it is returning

let dateStr = "2022-05-024T01:40:11.126-08:00"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
let parsedDate = dateFormatter.date(from: dateStr)
print(parsedDate)

CodePudding user response:

Date is just a container for the amount of time which has passed since some anchor point (ie milliseconds since the Unix Epoch), it doesn't "convert" the value, what it does do is, when you use "print", it make use of the platforms locale/timezone to present a "human readable" presentation of the time it represents

For example...

let dateStr = "2022-05-024T01:40:11.126-08:00"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
let date = dateFormatter.date(from: dateStr)!
print(date)

prints 2022-05-24 09:40:11 0000

But, if I change the formatter's timezone, for example...

let utcFormatter = DateFormatter()
utcFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
utcFormatter.timeZone = TimeZone(abbreviation: "UTC")
let utcDate = utcFormatter.date(from: dateStr)!
print(utcDate)

it still prints 2022-05-24 09:40:11 0000

Okay, it's printing in UTC anyway, so lets trying a different timezone:

let auFormatter = DateFormatter()
auFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
auFormatter.timeZone = TimeZone(abbreviation: "AEST")
let auDate = auFormatter.date(from: dateStr)!
print(auDate)

it still prints 2022-05-24 09:40:11 0000

If we read the docs it actually says "The representation is useful for debugging only."

If you want the presentation done differently, use a different formatter, for example...

let dateStr = "2022-05-024T01:40:11.126-08:00"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
let date = dateFormatter.date(from: dateStr)!
print(date)

dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
print(dateFormatter.string(from: date))

dateFormatter.timeZone = TimeZone(secondsFromGMT: -(8 * 60 * 60))
print(dateFormatter.string(from: date))

dateFormatter.timeZone = TimeZone(abbreviation: "AEST")
print(dateFormatter.string(from: date))

Which prints...

2022-05-24 09:40:11  0000        // print(date)
2022-05-24T09:40:11.126Z         // UTC
2022-05-24T01:40:11.126-08:00    // -8
2022-05-24T19:40:11.126 10:00    // AEST

(obviously you could also configure the Locale for different representations)

They all represent the same date/time value, just at different time zones

You could also check the different date values using Date#timeIntervalSinceReferenceDate or Date#timeIntervalSince1970, for example...

let dateStr = "2022-05-024T01:40:11.126-08:00"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
print(dateFormatter.date(from: dateStr)!.timeIntervalSince1970)

dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
print(dateFormatter.date(from: dateStr)!.timeIntervalSince1970)

dateFormatter.timeZone = TimeZone(secondsFromGMT: -(8 * 60 * 60))
print(dateFormatter.date(from: dateStr)!.timeIntervalSince1970)

dateFormatter.timeZone = TimeZone(abbreviation: "AEST")
print(dateFormatter.date(from: dateStr)!.timeIntervalSince1970)

which prints...

1653385211.126
1653385211.126
1653385211.126
1653385211.126

And as the docs state, "The interval between the date value and 00:00:00 UTC on 1 January 1970."

In this case, the formatter timezone has not effect on the parsing, only the presentation (the locale can fix parsing issues, but that's another topic)

  • Related