I'm trying to parse a date and time with microseconds using DateFormatter. However the obtained instance of Date class holds the time rounded off to milliseconds.
I can show it with this code:
import Foundation
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS"
let date = formatter.date(from: "2022-02-01T19:35:49.987654")!
print(formatter.string(from: date))
print(Calendar.current.component(.nanosecond, from: date))
The output is:
2022-02-01T19:35:49.987000
986999988
So 987654 microseconds were rounded off to 987 milliseconds and I don't understand why.
What am I doing wrong and how to fix it?
Thanks in advance.
P.S. swift version:
swift-driver version: 1.26.21 Apple Swift version 5.5.2 (swiftlang-1300.0.47.5 clang-1300.0.29.30)
Target: x86_64-apple-macosx12.0
Indeed, this is a current limitation of the underlying ICU library (for long-standing backwards-compatibility reasons); from the udat.h docs:
UDAT_FRACTIONAL_SECOND_FIELD
FieldPosition and UFieldPosition selector for 'S' field alignment, corresponding to the UCAL_MILLISECOND field.
Note: Time formats that use 'S' can display a maximum of three significant digits for fractional seconds, corresponding to millisecond resolution and a fractional seconds sub-pattern of SSS. If the sub-pattern is S or SS, the fractional seconds value will be truncated (not rounded) to the number of display places specified. If the fractional seconds sub-pattern is longer than SSS, the additional display places will be filled with zeros.
If you continue to use DateFormatter to parse fixed-format date strings, make sure to pin the locale to en_US_POSIX. See QA1480 NSDateFormatter and Internet Dates for an explanation as to why this is important.