The `ISO8601DateFormatter.Options.withFractionalSeconds` option for ISO8601DateFormatter causes an exception; CFDateFormatter is fine

Originator:seergypro
Number:rdar://35660658 Date Originated:November 22 2017
Status:Open Resolved:
Product:Foundation Product Version:Xcode 9.1 (9B55)
Classification: Reproducible:Always
 
Area:
Foundation

Summary:

Setting the `ISO8601DateFormatter.Options.withFractionalSeconds` option for ISO8601DateFormatter causes an exception.

Steps to Reproduce:

Run the following code


let cfDateFormatter = CFDateFormatterCreateISO8601Formatter(kCFAllocatorDefault,
                                                            [.withFractionalSeconds, .withInternetDateTime])

let string = CFDateFormatterCreateStringWithDate(kCFAllocatorDefault,
                                                 cfDateFormatter,
                                                 CFDateCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()))!

print("CFDateFormatter: \(string)\n\n") // This works

/* ========================================================================================================== */

let isoDateFormatter = ISO8601DateFormatter()

isoDateFormatter.formatOptions = [.withFullTime, .withFractionalSeconds] // CRASH

print("ISO8601DateFormatter: \(isoDateFormatter.string(from: Date()))\n\n")

Expected Results:

The console output must be:
CFDateFormatter: 2017-11-22T01:28:13.584+03:00


ISO8601DateFormatter: 2017-11-22T01:28:13.584+03:00



Actual Results:
The app crashes with an uncaught exception, the console output is:

CFDateFormatter: 2017-11-22T01:28:13.584+03:00


2017-11-22 01:28:13.597316+0300 ISO8601Test[49583:14603924] *** Assertion failure in -[NSISO8601DateFormatter setFormatOptions:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/Foundation_Sim/Foundation-1445.30/String.subproj/NSISO8601DateFormatter.m:66
2017-11-22 01:29:16.015562+0300 ISO8601Test[49583:14603924] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: formatOptions == 0 || !(formatOptions & ~(NSISO8601DateFormatWithYear | NSISO8601DateFormatWithMonth | NSISO8601DateFormatWithWeekOfYear | NSISO8601DateFormatWithDay | NSISO8601DateFormatWithTime | NSISO8601DateFormatWithTimeZone | NSISO8601DateFormatWithSpaceBetweenDateAndTime | NSISO8601DateFormatWithDashSeparatorInDate | NSISO8601DateFormatWithColonSeparatorInTime | NSISO8601DateFormatWithColonSeparatorInTimeZone | NSISO8601DateFormatWithFullDate | NSISO8601DateFormatWithFullTime | NSISO8601DateFormatWithInternetDateTime))'

Version/Build:
Xcode 9.1 (9B55), iOS 11.1

Comments

workaround NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init];

Ivar ivar = class_getInstanceVariable([NSISO8601DateFormatter class], "_formatOptions");

CFTypeRef formatterRef = CFBridgingRetain(formatter);
int *ivarPtr = (int *)((uint8_t *)formatterRef + ivar_getOffset(ivar));
*ivarPtr = NSISO8601DateFormatWithInternetDateTime | NSISO8601DateFormatWithFractionalSeconds;
CFBridgingRelease(formatterRef);
[formatter valueForKey:@"updateFormatter"];

NSLog(@"%@", [formatter stringFromDate:[NSDate date]]);
By mndgs.paukste at Nov. 23, 2017, 9:54 a.m. (reply...)

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!