3

我几乎没有NSDate包含符合此格式的值的对象yyy-MM-dd'T'HH:mm:ss.SSS

当我尝试转换为其他格式时,例如MMM dd, yyyy HH:mm格式化程序总是返回nil.

但是,如果我对通过NSDateobject 获得的字符串值进行硬编码,它会毫无问题地转换为新格式。

我使用该方法在模型中填充我的NSDate对象setValue:forKey:,我觉得问题出在 JSON 库传递字符串值的地方。但是,调试显示NSDatehas 包含通过 JSON 返回的值。

知道是什么导致了这种奇怪的行为吗?

这是我的转换代码:

NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS"];
NSString *createdDateStr = [format stringFromDate:modelObj.createdDate];
[format setDateFormat:@"MMM dd, yyyy HH:mm"];

NSDate *formattedDate = [format dateFromString:createdDateStr];
NSLog(@"========= REal Date %@",[format stringFromDate:formattedDate]);
4

3 回答 3

10

编辑:重读你的问题,我认为除了其他任何东西之外,你还有一个概念上的误解:

我有几个 NSDate 对象,其中包含符合以下格式的值

据我所知(诚然,我不是 Objective-C 程序员)一个NSDate对象对格式化一无所知。它只代表一个瞬间。它不知道它是从文本中解析出来的还是以其他方式创建的。

这就像int- 一个int变量不是十进制或十六进制,它只是一个数字。当你格式化和解析你指定的时候。同样,您在解析和格式化时NSDateFormatter用来描述您想要的格式。


您目前只有一个 NSDateFormatter- 您正在将格式设置为"yyyy-MM-dd'T'HH:mm:ss.SSS"然后在调用之前将其重置dateFromString。您已将格式指定modelObj.createdDate为 ISO-8601 格式的代码片段,但随后尝试使用“MMM dd, yyyy HH:mm”格式对其进行解析。

我建议你有两个单独的NSDateFormatter对象:

NSDateFormatter *isoFormat = [[NSDateFormatter alloc] init];
[isoFormat setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS"];
NSString *createdDateStr = [format stringFromDate:modelObj.createdDate];

NSDateFormatter *shortFormat = [[NSDateFormatter alloc] init];
[shortFormat setDateFormat:@"MMM dd, yyyy HH:mm"];

NSDate *parsedDate = [isoFormat dateFromString:createdDateStr];
NSLog(@"========= REal Date %@",[shortFormat stringFromDate:parsedDate]);

请注意,我已将您的formattedDate变量更改为parsedDate,因为这才是真正的 -NSDate通过解析文本创建的。

如评论中所述,除非您确实需要像这样格式化和解析,否则您不应该这样做。我包含了您所有的原始代码,只是为了展示如何格式化日期,然后用相同的NSDateFormatter. 只需:

NSDateFormatter *shortFormat = [[NSDateFormatter alloc] init];
[shortFormat setDateFormat:@"MMM dd, yyyy HH:mm"];    
NSLog(@"========= REal Date %@",[shortFormat stringFromDate:modelObj.createdDate]);

一般来说,您应该避免不必要的转换。文本转换为更自然的数据类型(NSDate在这种情况下,但同样适用于数字等)并在尽可能多的代码中使用该数据类型,仅在最后一刻转换为文本。

于 2012-08-20T07:45:36.063 回答
4

问题是您正在从具有一种格式的日期创建字符串,然后尝试将其转换回具有不同格式的日期。要从字符串创建日期,您应该使用与创建该字符串相同的格式,否则您将得到 nil。如果您确实需要其他格式的格式化字符串,则首先从具有正确格式的字符串创建日期,然后将其转换回您想要的格式的字符串。问题是顺序。

NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS"];
NSString *createdDateStr = [format stringFromDate:modelObj.createdDate];


NSDate *formattedDate = [format dateFromString:createdDateStr];

[format setDateFormat:@"MMM dd, yyyy HH:mm"];
NSLog(@"========= REal Date %@",[format stringFromDate:formattedDate]);

其他方法是使用Jon Skeet建议的不同格式化程序,以避免混淆......

于 2012-08-20T07:54:47.263 回答
1

您有一个NSDate, modelObj.createdDate,并且您想将其格式化为特定格式的字符串 , MMM dd, yyyy HH:mm。您不需要将日期转换为字符串,然后再转换回另一个字符串,然后再转换NSDate回字符串。如果您对这两个操作使用相同的格式化程序,那么您最终会得到与开始时相同的日期。

您只需将日期格式化一次,即可获得最终所需的外观:

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"MMM dd, yyyy HH:mm"];
NSLog(@"========= REal Date %@",[format stringFromDate:modelObj.createdDate]);

NSDate本身不“符合以下格式”。它没有格式——它是一个时间点,一个参考日期的偏移量。如果您NSLog()这样做,它确实会将自己格式化为人类可读的字符串(可能在幕后使用日期格式化程序),但这只是它选择的一种表示形式。

现在,您正在nil从第二个格式化操作中获得信息,NSDate *formattedDate = [format dateFromString:createdDateStr];因为您传递给格式化程序的字符串格式必须与格式化程序所期望的完全匹配。在这种情况下,它不会,因为您使用 format 创建了字符串yyyy-MM-dd'T'HH:mm:ss.SSS,但已经告诉格式化程序 expect MMM dd, yyyy HH:mm。格式化程序因此无法解析字符串,并返回nil以指示失败。

于 2012-08-20T07:52:15.030 回答