iOS中NSISO8601DateFormatter解析日期返回nil的问题排查
为什么NSISO8601DateFormatter的dateFromString返回nil?
我完全搞不懂下面的代码里,dateFromString为什么会返回nil:
NSString* timeStampValue = @"20230917120009.289Z"; NSString* dateString = [timeStampValue substringToIndex:8]; NSISO8601DateFormatter* formatter = [[NSISO8601DateFormatter alloc] init]; [formatter setFormatOptions:NSISO8601DateFormatWithFullDate]; NSDate* dateOfLastVerification = [formatter dateFromString:dateString];
一开始我尝试转换整个timeStampValue字符串,还对应设置了格式选项,我原以为这能生效——因为据我所知这个字符串是有效的ISO8601格式(技术上用的是GeneralizedTime语法,但我觉得这不影响),结果还是返回nil。
后来我决定只提取日期子串(我不一定需要时间和时区数据),并指定NSISO8601DateFormatWithFullDate作为唯一选项,本以为这是最稳妥的方式,但dateFromString还是返回nil。我试过直接设置formatter.formatOptions = NSISO8601DateFormatWithFullDate,结果也没变化。
问题原因
- 提取的日期子串格式不匹配:
NSISO8601DateFormatWithFullDate对应的是带分隔符的标准ISO8601日期格式(如2023-09-17),但你提取的dateString是无分隔符的紧凑格式20230917,不在该选项的支持范围内,因此解析失败返回nil。 - 完整时间戳的格式支持问题:
20230917120009.289Z属于GeneralizedTime(ASN.1定义的ISO8601变体),默认的NSISO8601DateFormatter选项不支持这种无分隔符的紧凑日期时间格式,必须添加对应选项才能解析。
解决方案
方案1:解析提取的日期子串
如果只需要日期部分,有两种适配方式:
NSString* timeStampValue = @"20230917120009.289Z"; NSString* dateString = [timeStampValue substringToIndex:8]; // 方式1:转换为带分隔符的格式适配NSISO8601DateFormatter NSString* formattedDate = [NSString stringWithFormat:@"%@-%@-%@", [dateString substringToIndex:4], [dateString substringWithRange:NSMakeRange(4,2)], [dateString substringFromIndex:6]]; NSISO8601DateFormatter* isoFormatter = [[NSISO8601DateFormatter alloc] init]; isoFormatter.formatOptions = NSISO8601DateFormatWithFullDate; NSDate* date1 = [isoFormatter dateFromString:formattedDate]; // 方式2:直接用NSDateFormatter指定格式 NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init]; dateFormatter.dateFormat = @"yyyyMMdd"; dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; NSDate* date2 = [dateFormatter dateFromString:dateString];
方案2:解析完整的时间戳字符串
如果需要完整时间信息,分两种场景处理:
- iOS 10+/macOS 10.12+版本:用
NSISO8601DateFormatter添加紧凑格式支持选项
NSString* timeStampValue = @"20230917120009.289Z"; NSISO8601DateFormatter* formatter = [[NSISO8601DateFormatter alloc] init]; formatter.formatOptions = NSISO8601DateFormatWithFullDate | NSISO8601DateFormatWithFullTime | NSISO8601DateFormatWithFractionalSeconds | NSISO8601DateFormatWithTimeZone | NSISO8601DateFormatWithoutDashSeparatorInDate | NSISO8601DateFormatWithoutColonSeparatorInTime; NSDate* date = [formatter dateFromString:timeStampValue];
- 兼容低版本系统:用
NSDateFormatter直接指定匹配格式
NSString* timeStampValue = @"20230917120009.289Z"; NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"yyyyMMddHHmmss.SSSZ"; formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; NSDate* date = [formatter dateFromString:timeStampValue];
内容的提问来源于stack exchange,提问作者Blaire Crits-Christoph
相关产品推荐
相关产品推荐

