The DateFormatter is returning wrong date format 2024-04-23T7:52:49.352 AMZ, 2024-05-23T11:16:24.706 a.m.Z

import Foundation

let formatter = DateFormatter()

let displayLocalFormat = true or false

let timeZone = UTC

let dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"

let currentDate = Date()


formatter.locale = displayLocalFormat ? Locale.current : Locale(identifier: "en_US_POSIX")

formatter.dateFormat = dateFormat

formatter.timeZone = timeZone

formatter.string(from: date) // This function returns date format 2024-05-23T11:16:24.706 a.m.Z

Answered by DTS Engineer in 790710022

OK, but how are you testing it? What version of Xcode are you using to build your test? What platform are you running it on? And what version of that platform?

If you run my code in your test environment, what results do you see?


Finally, look at you code I see this:

let displayLocalFormat = true // or false

…

formatter.locale = displayLocalFormat ? Locale.current : Locale(identifier: "en_US_POSIX")

…

switch formatOrStyle {

…

case let .format(format):

    formatter.dateFormat = format
}

This is wrong. If you’re using a fixed date format then you must use en_US_POSIX. Anything else will not work the way you expect it to work.

See this post for a summary of the three valid ways to use a date formatter.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

How are you testing this?

For context, I put your code — well, with some tweaks to make it work standalone — into a command-line tool project and ran it using Xcode 15.4 on macOS 14.5 and this is what I got:

import Foundation

func main() {
    let formatter = DateFormatter()
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
    formatter.timeZone = .gmt
    let date = Date(timeIntervalSinceReferenceDate: 739928686.0)
    let s = formatter.string(from: date)
    print(s)
    // 2024-06-12T23:44:46.000Z
}

main()

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

This is our actual code.



enum DateTimeZoneMode {

    case utc

    case gmt

    case local

    

    func timeZone() -> TimeZone? {

        switch self {

        case .local:

            return TimeZone.current

        case .utc:

            return TimeZone(abbreviation: "UTC")

        case .gmt:

            return TimeZone(abbreviation: "GMT")

        }

    }

}



private final class FormatterCache {

    /// Either the string format or style of the date

    enum FormatOrStyle: Hashable {

        case format(String)

        case style(DateFormatter.Style)

    }



    /// The key to use to cache the formatters (combo of tz and format)

    private struct Key: Hashable {

        let mode: DateTimeZoneMode

        let formatOrStyle: FormatOrStyle

    }



    private var lock = os_unfair_lock()

    private var formatters = [Key: DateFormatter]()



    init() {}



    func formatter(

        forMode mode: DateTimeZoneMode,

        formatOrStyle: FormatOrStyle,

        shouldDisplayInLocalFormat: Bool = true

    ) -> DateFormatter {

        let key = Key(mode: mode, formatOrStyle: formatOrStyle)

        os_unfair_lock_lock(&lock)

        defer { os_unfair_lock_unlock(&lock) }

        let displayLocalFormat = true // or false

        if let formatter = formatters[key] {

            formatter.locale = displayLocalFormat ? Locale.current : Locale(identifier: "en_US_POSIX")

            if mode == .local {

                // always reset the timezone to keep .local up-to-date

                formatter.setLocalTimeZone()

            }

            return formatter

        } else {

            let formatter = DateFormatter()

            formatter.locale = displayLocalFormat ? Locale.current : Locale(identifier: "en_US_POSIX")

            switch formatOrStyle {

            case let .style(style):

                formatter.dateStyle = style

            case let .format(format):

                formatter.dateFormat = format

            }

            if mode == .local {

                formatter.setLocalTimeZone()

            } else {

                formatter.timeZone = mode.timeZone()

            }

            formatters[key] = formatter

            return formatter

        }

    }

    

    

}



private extension DateFormatter {

    func setLocalTimeZone() {

            self.timeZone = DateTimeZoneMode.local.timeZone()

    }

}



extension DateFormatter {

    convenience init (from format: String) {

        self.init()

        dateFormat = format

    }

}



this is how we call function. and this function gives the wrong date

formatterCache.formatter(forMode: timeZone,

                                                    formatOrStyle: .format(format)).string(from: date)

@DTS Engineer Please check above code

OK, but how are you testing it? What version of Xcode are you using to build your test? What platform are you running it on? And what version of that platform?

If you run my code in your test environment, what results do you see?


Finally, look at you code I see this:

let displayLocalFormat = true // or false

…

formatter.locale = displayLocalFormat ? Locale.current : Locale(identifier: "en_US_POSIX")

…

switch formatOrStyle {

…

case let .format(format):

    formatter.dateFormat = format
}

This is wrong. If you’re using a fixed date format then you must use en_US_POSIX. Anything else will not work the way you expect it to work.

See this post for a summary of the three valid ways to use a date formatter.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@DTS Engineer Thanks for your quick response. We have one of our users from Dublin who is facing this type of issue. let me try to implement this and I will ask for more help if needed.

Right. They have almost certainly overridden the default 12-/24-hour setting for their locale, which is one of the two most common causes of problems like this (they other being to choose a non-Gregorian calendar).

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

The DateFormatter is returning wrong date format 2024-04-23T7:52:49.352 AMZ, 2024-05-23T11:16:24.706 a.m.Z
 
 
Q