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

时间:2013-02-14 14:52:21

标签: ios objective-c

我正在尝试使用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视为可选项?

感谢您的帮助

3 个答案:

答案 0 :(得分:19)

据我所知,无法制作可选参数。

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

  1. 计算日期字符串中的字符数(如Parsing a RFC 822 date with NSDateFormatter中所示)

  2. 只需尝试两种格式化工具,即可获得第一个非nil结果。

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

答案 1 :(得分:1)

自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];

答案 2 :(得分:0)

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

@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