如何使用NSDateFormatter和可选的毫秒部分解析ISO 8601

我正在尝试使用NSDateFormatter来解析这些格式中的任何一种格式的日期

@"2013-02-01T14:21:00" 

要么

 @"2013-02-01T14:21:56.345" 

目前我使用以下方法来解析字符串并返回日期:

 NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]]; [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"]; [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]]; NSDate *date = [dateFormatter dateFromString:dateToFormat]; 

这适用于第一种日期样式,但对于包含毫秒部分的字符串返回nil。

我想我可以测试毫秒的存在并剥离它们,但我想知道我是否可以更改日期格式以将.SSS视为可选项?

谢谢你的帮助

据我所知,没有办法制作可选参数。

通常的解决方案是使用两个格式化程序,每种格式一个。 要决定使用哪种格式化程序,您可以

  1. 计算日期字符串中的字符数(如使用NSDateFormatter解析RFC 822日期中所建议的那样)

  2. 只需尝试两种格式化程序并获得第一个非零结果。

由于您的日期格式类似,您只能使用一个格式化程序,如果日期字符串太短,请在使用格式化程序之前附加.000

我写了一个通用的解析器,它丢弃了几毫秒。

 @implementation JSONModel(NSPAdditions) - (NSDate *)NSDateFromNSString:(NSString*)string { NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]]; NSArray* parts = [string componentsSeparatedByCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@" T"]]; if ([parts count] <= 1) { return [formatter dateFromString:string]; } NSString *part0 = parts[0]; NSAssert([part0 length] == [@"yyyy-MM-dd" length], @"Date format error"); NSString *part1 = parts[1]; if ([part1 length] > [@"HH:mm:ss" length]) { part1 = [part1 substringToIndex:[@"HH:mm:ss" length]]; } NSString *fmted = [NSString stringWithFormat:@"%@ %@", part0, part1]; [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; return [formatter dateFromString:fmted]; } @end 

自iOS 10以来的正确方法是使用专门创建的ISO8601DateFormatter来处理ISO 8601日期字符串的所有变体。 请看下面的例子:

 let date = Date() var string: String let formatter = ISO8601DateFormatter() string = formatter.string(from: date) let GMT = TimeZone(abbreviation: "GMT") let options: ISO8601DateFormatOptions = [.withInternetDateTime, .withDashSeparatorInDate, .withColonSeparatorInTime, .withTimeZone] string = ISO8601DateFormatter.string(from: date, timeZone: GMT, formatOptions: options) 

和Objective-C版本:

 NSDate *date = [NSDate date]; NSString *string; NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init]; string = [formatter stringFromDate:date]; NSTimeZone *GMT = [NSTimeZone timeZoneWithAbbreviation: @"GMT"]; NSISO8601DateFormatOptions options = NSISO8601DateFormatWithInternetDateTime | NSISO8601DateFormatWithDashSeparatorInDate | NSISO8601DateFormatWithColonSeparatorInTime | NSISO8601DateFormatWithTimeZone; string = [NSISO8601DateFormatter stringFromDate:date timeZone:GMT formatOptions:options]; 
Interesting Posts