1

I am struggling quite a bit with dates. I have the following code:

Current Date in Amsterdam: 22-Februari-2022 - 11:40

Current Date in New York: 22-Februari-2022 - 05:40

The dateBoughtString goes in as follows: 2022-02-18T19:50:47.081Z The current date is just the current date.

let dateFormatterNew = DateFormatter()
    dateFormatterNew.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
    dateFormatterNew.timeZone = TimeZone(abbreviation: "GMT+1:00")
    dateFormatterNew.locale = Locale(identifier: "nl-NL")
    let dateBoughtTemp = dateFormatterNew.date(from: positionStatsString[0])!

    print(dateBoughtTemp) // Prints: 2022-02-18 18:50:47 +0000
    
    dateFormatterNew.timeZone = TimeZone(abbreviation: "GMT-5:00")
    dateFormatterNew.locale =  Locale(identifier: "en_US")
    let dateNowTemp = dateFormatterNew.string(from: Date())
    let dateBoughtTempTwo = dateFormatterNew.string(from: dateBoughtTemp)

    print(dateNowTemp) // Prints: 2022-02-22T05:41:49.973Z
    print(dateBoughtTempTwo) // Prints: 2022-02-18T13:50:47.081Z

    let dateNow = dateFormatterNew.date(from: dateNowTemp)
    let dateBought = dateFormatterNew.date(from: dateBoughtTempTwo)

    print(dateNow!)  // Prints: 2022-02-22 10:41:49 +0000 **INCORRECT**
    print(dateBought!) // Prints: 2022-02-18 18:50:47 +0000 **INCORRECT**

When I convert to string all seems fine and it works as it should. But when I convert those strings back to a date they just go back to Amsterdam time with the current date even being one hour off.

What am I missing here?

Mr_Bull3t
  • 67
  • 1
  • 6
  • 2
    The printed time is in UTC (GMT) time zone so it looks correct to me. – Joakim Danielson Feb 22 '22 at 10:47
  • Use `ISO8601DateFormatter` instead – Cy-4AH Feb 22 '22 at 10:54
  • @Cy-4AH This doesn't work as well. To string its fine but when I convert it back to date it goes back to the European date. Same result/ – Mr_Bull3t Feb 22 '22 at 11:57
  • Why `print(dateBought!)` is incorrect if its equal to `print(dateBoughtTemp)`? – Cy-4AH Feb 22 '22 at 13:07
  • when printing your date to get the local time you need `print(dateBoughtTemp.description(with: .current)` Note that `Z` in a date string means it is UTC timezone. If you escape it will ignore the timezone of your string and use the current timezone or the timezone specified in your date formatter if you set a fixed one. – Leo Dabus Feb 22 '22 at 15:11

2 Answers2

1

Use the below code for formatter, Change the timezone and dateFormat according to your need:

let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
            
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
Ghulam Mustafa
  • 196
  • 1
  • 7
1

The problem is in your's parameter 'Z': '' means that it's content doesn't involved in time formatting. So when you apply timeZone parameter date is printed in particular time zone without correct timeZone suffix and when it's scanned it's scanned in particular time zone, just expecting that there will by Z character at the end. So when you are formatting to date and then to string you are accumulating error caused by timezone difference.

Correct format will be "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" or better to use ISO8601DateFormatter because you can't set invalid format in it.

So your printed dates will have valid timezone suffix and timezone suffix will be considered in backward conversion.

Another moment: you shouldn't convert string back to date with localized formatter, if it's UI part, but for that you can use UIDatePicker instead of UITextField.

So full code will be:

let isoDateFormatter = ISO8601DateFormatter()
isoDateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let date = isoDateFormatter.date(from: "2022-02-18T19:50:47.081Z")!
let now = Date()

do {
    let amsterdamDateFormatter = DateFormatter()
    amsterdamDateFormatter.timeZone = .init(abbreviation: "GMT+1:00")
    amsterdamDateFormatter.dateStyle = .long
    amsterdamDateFormatter.timeStyle = .short

    print("now in Amsterdam: \(amsterdamDateFormatter.string(from: now))")
    print("time in Amsterdam: \(amsterdamDateFormatter.string(from: date))")
}

do {
    let newYourkDateFormatter = DateFormatter()
    newYourkDateFormatter.timeZone = .init(abbreviation: "GMT-5:00")
    newYourkDateFormatter.dateStyle = .long
    newYourkDateFormatter.timeStyle = .short

    print("now in NY: \(newYourkDateFormatter.string(from: now))")
    print("time in NY: \(newYourkDateFormatter.string(from: date))")
}
Cy-4AH
  • 4,370
  • 2
  • 15
  • 22