Converting date of format yyyy-MM-dd'T'HH:mm:ss.SSS

China☆狼群 提交于 2019-12-03 20:27:56

问题


I have few NSDate objects which contain values compliant to this format yyy-MM-dd'T'HH:mm:ss.SSS

When I try to convert to a different format such as MMM dd, yyyy HH:mm the formatter always returns nil.

However, if I hardcode the string value I get through the NSDate object , it is transformed to the new format without a problem.

I populate my NSDate object in the model using the setValue:forKey: method, and I feel the problem is here where the JSON library passes a string value. However, the debugging shows that the NSDate has contains the value returned via JSON.

Any idea what's causing this strange behavior?

This is my conversion code:

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

回答1:


EDIT: Rereading your question, I think you've got a conceptual misunderstanding aside from anything else:

I have few NSDate objects which contains values compliant to the following format

As far as I'm aware (I'm not an Objective-C programmer, admittedly) an NSDate object doesn't know anything about formatting. It just represents an instant in time. It isn't aware of whether it was parsed from text or created in some other way.

It's like an int - an int variable isn't in decimal or hex, it's just a number. It's when you format and parse that you specify that. Likewise, you use NSDateFormatter to describe the format you want at the point of parsing and formatting.


You've currently only got one NSDateFormatter - you're setting the format to "yyyy-MM-dd'T'HH:mm:ss.SSS" then resetting it before you've called dateFromString. The code snippet you've given formats modelObj.createdDate into ISO-8601 format, but then tries to parse it using the "MMM dd, yyyy HH:mm" format.

I suggest you have two separate NSDateFormatter objects:

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

Note that I've changed your formattedDate variable to parsedDate, as that's what it really is - an NSDate which has been created by parsing text.

As noted in comments, unless you actually need to format and parse like this, you shouldn't. I included all of your original code just to show how you can format a date and then reparse it with the same NSDateFormatter. You'll get the same result with just:

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

In general, you should avoid unnecessary conversions. Convert from text to the more natural data type (NSDate in this case, but the same applies for numbers etc) and use that data type for as much of your code as possible, only converting to text at the last moment.




回答2:


The problem is that you are creating string from date with one format and then trying to convert it back to date with different format. To create date from string you should use the same format as you've used to create that string otherwise you'll get nil. If you do need formatted string with other format, then first create date from string with correct format and then convert it back to string with format you want. The issue is the order.

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

Other approach is to use different formatters as Jon Skeet suggest just to avoid confusion...




回答3:


You've got an NSDate, modelObj.createdDate, and you want to format it as a string in a certain format, MMM dd, yyyy HH:mm. You don't need to convert the date to a string and then back to another NSDate and then back to a string again. If you use the same formatter for both operations, you'll just end up with the same date you started with.

You only need to format the date once, to your final desired appearance:

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

The NSDate itself is not "compliant to the following format". It has no format -- it's a moment in time, an offset from a reference date. If you NSLog() it, it will indeed format itself into a human-readable string (probably using a date formatter behind the scenes), but that is just one representation that it chooses.

Right now, you're getting nil from the second formatting operation, NSDate *formattedDate = [format dateFromString:createdDateStr]; because the format of the string you pass in to the formatter has to exactly match what the formatter expects. In this case, it doesn't, because you created the string using the format yyyy-MM-dd'T'HH:mm:ss.SSS, but have told the formatter to expect MMM dd, yyyy HH:mm. The formatter thus can't parse the string, and returns nil to indicate failure.



来源:https://stackoverflow.com/questions/12033892/converting-date-of-format-yyyy-mm-ddthhmmss-sss

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!