Search code examples
swifttimezone-offsetdateformatter

Swift ISO8601DateFormatter not writing UTC offset when printing GMT date


I am trying to print a date and time, I would like the String representation to include the UTC offset. This seems to work for date and times which are in the BST time zone, however when the date and time is in the GMT time zone the String doesn't contain the offset, but the "Z".

The code I am using is:

let formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(identifier: timeZone). // timeZone = "Europe/London"
formatter.formatOptions = [.withInternetDateTime, .withTimeZone]
formatter.string(from: date). // date is a Date object

The output looks like:
2023-10-16T10:00:00+01:00 for a BST date and time.
2023-11-01T20:42:59Z for a GMT date and time

Is there a way to have the GMT date and time look like 2023-11-01T20:42:59+00:00?


Solution

  • Yes but you would need a custom dateFormat. ISO8601DateFormatter doesnt give that option AFAIK.

    If you would like to have timeZone without Z you would need to pass xxxxx to the date formatter's dateFormat.

    enter image description here


    extension Formatter {
        static let iso8601: DateFormatter = {
            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:ssxxxxx"
            return formatter
        }()
    }
    

    Formatter.iso8601.string(from: .now)  // "2023-11-01T22:02:10+00:00"
    

    extension TimeZone {
        static let london: TimeZone = .init(identifier: "Europe/London")!
    }
    

    if let date = Formatter.iso8601.date(from: "2023-10-16T10:00:00+01:00") {
        Formatter.iso8601.timeZone = .london
        Formatter.iso8601.string(from: date)  // "2023-10-16T10:00:00+01:00"
    }
    

    For more detailed post about iso8601 check this How can I parse / create a date time stamp formatted with fractional seconds UTC timezone (ISO 8601, RFC 3339) in Swift?