解析JSON在IPhone
日期原谅我,因为我是新来的目的C.解析JSON在IPhone
我取回从/日期(XXXXXXXXXXXXX-XXXX)/格式的.NET Web服务的日期。我正在寻找一些关于如何最好的解析NSDate对象的方向。我已经尝试使用dateWithTimeIntervalSince1970上它,但它回来与在1969年的日期,我知道是在2006年的日期。
寻找一些正确的方式来处理JSON日期。
在此先感谢!
作为一名.NET程序员学习Objective-C,当我尝试使用.Net WebService时,我遇到了同样的问题。
起初我还以为我将能够使用NSDateFormatter ... 我发现它的符号here一个很好的参考,但我很快意识到,我需要的数量从毫秒转换为秒。
我写的代码做... 我还在学习对象 - 但我不认为它应该一直这个硬...
- (NSDate *) getJSONDate{
NSString* header = @"/Date(";
uint headerLength = [header length];
NSString* timestampString;
NSScanner* scanner = [[NSScanner alloc] initWithString:self];
[scanner setScanLocation:headerLength];
[scanner scanUpToString:@")" intoString:×tampString];
NSCharacterSet* timezoneDelimiter = [NSCharacterSet characterSetWithCharactersInString:@"+-"];
NSRange rangeOfTimezoneSymbol = [timestampString rangeOfCharacterFromSet:timezoneDelimiter];
[scanner dealloc];
if (rangeOfTimezoneSymbol.length!=0) {
scanner = [[NSScanner alloc] initWithString:timestampString];
NSRange rangeOfFirstNumber;
rangeOfFirstNumber.location = 0;
rangeOfFirstNumber.length = rangeOfTimezoneSymbol.location;
NSRange rangeOfSecondNumber;
rangeOfSecondNumber.location = rangeOfTimezoneSymbol.location + 1;
rangeOfSecondNumber.length = [timestampString length] - rangeOfSecondNumber.location;
NSString* firstNumberString = [timestampString substringWithRange:rangeOfFirstNumber];
NSString* secondNumberString = [timestampString substringWithRange:rangeOfSecondNumber];
unsigned long long firstNumber = [firstNumberString longLongValue];
uint secondNumber = [secondNumberString intValue];
NSTimeInterval interval = firstNumber/1000;
return [NSDate dateWithTimeIntervalSince1970:interval];
}
unsigned long long firstNumber = [timestampString longLongValue];
NSTimeInterval interval = firstNumber/1000;
return [NSDate dateWithTimeIntervalSince1970:interval];
}
希望有人能提供更好的Obj-C解决方案。 如果不是我可以收下这笔或者寻找一种方式来改变序列化格式在.NET
编辑:
有关JSON DateTime格式... 如果您对本服务的任何控制它可能会最好将日期转换为DataContract对象中的字符串。
Formatting to RFC1123对我来说似乎是个好主意。正如我可以轻松地使用NSDateFormatter来捡起它。
报价从Rick Strahl
有没有JavaScript的日期文字和微软设计的自定义日期格式,本质上是一种标记的字符串。格式是经过编码并包含标准新Date(1970年以来的毫秒)值的字符串。
我在同一条船上,同时使用json-framework,它不支持日期格式,因为它不是官方的JSON。我的源代码来自使用JSON.Net构建的API。这是我想出了:
- (NSDate*) getDateFromJSON:(NSString *)dateString
{
// Expect date in this format "/Date(1268123281843)/"
int startPos = [dateString rangeOfString:@"("].location+1;
int endPos = [dateString rangeOfString:@")"].location;
NSRange range = NSMakeRange(startPos,endPos-startPos);
unsigned long long milliseconds = [[dateString substringWithRange:range] longLongValue];
NSLog(@"%llu",milliseconds);
NSTimeInterval interval = milliseconds/1000;
return [NSDate dateWithTimeIntervalSince1970:interval];
}
我没有在日期格式,你这样做,我还没有处理,像上述的答案附加部分。没有任何错误,这一点对我来说都是新的。
我刚刚写了iOS 4.0+(因为它使用NSRegularExpression)。它处理带或不带时区偏移量的日期。似乎工作得很好,你怎么看?
+ (NSDate *)mfDateFromDotNetJSONString:(NSString *)string {
static NSRegularExpression *dateRegEx = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
dateRegEx = [[NSRegularExpression alloc] initWithPattern:@"^\\/date\\((-?\\d++)(?:([+-])(\\d{2})(\\d{2}))?\\)\\/$" options:NSRegularExpressionCaseInsensitive error:nil];
});
NSTextCheckingResult *regexResult = [dateRegEx firstMatchInString:string options:0 range:NSMakeRange(0, [string length])];
if (regexResult) {
// milliseconds
NSTimeInterval seconds = [[string substringWithRange:[regexResult rangeAtIndex:1]] doubleValue]/1000.0;
// timezone offset
if ([regexResult rangeAtIndex:2].location != NSNotFound) {
NSString *sign = [string substringWithRange:[regexResult rangeAtIndex:2]];
// hours
seconds += [[NSString stringWithFormat:@"%@%@", sign, [string substringWithRange:[regexResult rangeAtIndex:3]]] doubleValue] * 60.0 * 60.0;
// minutes
seconds += [[NSString stringWithFormat:@"%@%@", sign, [string substringWithRange:[regexResult rangeAtIndex:4]]] doubleValue] * 60.0;
}
return [NSDate dateWithTimeIntervalSince1970:seconds];
}
return nil;
}
+1此函数支持1970年1月1日之前和之后的日期,这与其他方法的“无符号”毫秒不同。我的解决方案需要TZ的信息,所以我刚刚评论说部分和关闭的比赛。 – J3RM 2012-01-18 17:46:55
+1,这工作正常。什么是@“^ \\/date \\(( - ?\\ d ++)(?:([+ - ])(\\ d {2})(\\ d {2}))?\ \)\\/$“。我无法理解它正在发生什么。 – 2013-05-10 05:11:06
@ g-ganesh这是正则表达式。它解析这种格式:“/ Date(xxxxxxxxxxxxx-xxxx)/”。第一部分是unix时间,第二部分是时区。首先,所有那些双“\”,因为“\”需要在NSString对象中转义,然后单个“\”在正则表达式中转义。所以我们有“^ \/date \(”,它只在字符串的开始处匹配“/ date(”),然后我们有“( - ?\ d ++)”,它捕获可选的负秒,其中至少有两个数字(我不记得为什么它必须至少有两个) – jasongregori 2013-05-10 15:33:18
我居然发现NSRegularExpression片断非常有用的,直到我与使用NSCharecterSet为stipping关闭毫秒另一种解决方案上来。
+ (NSDate*) dateFromJSONString:(NSString *)dateString
{
NSCharacterSet *charactersToRemove = [[ NSCharacterSet decimalDigitCharacterSet ] invertedSet ];
NSString* milliseconds = [dateString stringByTrimmingCharactersInSet:charactersToRemove];
if (milliseconds != nil && ![milliseconds isEqualToString:@"62135596800000"]) {
NSTimeInterval seconds = [milliseconds doubleValue]/1000;
return [NSDate dateWithTimeIntervalSince1970:seconds];
}
return nil;
}
节省了大量的手动字符串处理,并使代码更清洁。
这是非常好的解决方案。只是想知道为什么没人赞成这个。谢谢。 – 2012-09-01 14:58:28
这不适用于时代之前的日期,因为它也会剥离最终的符号字符。 – Niels 2013-03-01 14:44:50
理论值:MS编码的C#日期时间在JSON作为毫秒自1970年以来 解决方案:
NSString*
dateAsString = @"/Date(1353720343336+0000)/";
dateAsString = [dateAsString stringByReplacingOccurrencesOfString:@"/Date("
withString:@""];
dateAsString = [dateAsString stringByReplacingOccurrencesOfString:@"+0000)/"
withString:@""];
unsigned long long milliseconds = [dateAsString longLongValue];
NSTimeInterval interval = milliseconds/1000;
NSDate* date = [NSDate dateWithTimeIntervalSince1970:interval];
这是我能想到的最短溶液。
这不是假设时间是UTC吗? – mkral 2013-01-08 14:59:30
- (的NSString *)convertToUTCTime:(的NSString *)strDate {
NSDate *currentDate = [NSDate date];
myDate = [commonDateFormatter dateFromString: strDate];
NSTimeInterval distanceBetweenDates = [currentDate timeIntervalSinceDate:myDate];
return [self stringFromTimeInterval:distanceBetweenDates];
} - (的NSString *)stringFromTimeInterval:(NSTimeInterval)间隔{ NSInteger的TI =(NSInteger的)间隔; NSIteger分钟数=(ti/60)%60; NSInteger小时=(ti/3600);
if (hours > 24) {
NSInteger days = hours/24;
if (days > 30) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"EEE d MMM, h:mm a"];
//[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"IST"]];
NSString *daydate = [dateFormatter stringFromDate:myDate];
return daydate;
}
else{
return [NSString stringWithFormat:@" %2ldd",(long)days];
}
}else{
if (hours == 0 && minutes < 1) {
return [NSString stringWithFormat:@"Today"];
}
else if (hours == 0 && minutes < 60){
return [NSString stringWithFormat:@"%2ldm ",(long)minutes];
}
else{
return [NSString stringWithFormat:@" %2ldh",(long)hours];
}
}
}
感谢您的回答。我基本上采取了与你相同的方法。这感觉像一个黑客,我希望有一个更清洁的解决方案,但哦,它现在工作。 – user213517 2009-11-19 19:09:24
[scanner dealloc];不应该是[扫描仪发布]; ! :) – 2012-11-12 17:56:04
很好的解决方案,但secondNumber被解析后根本不使用。它应该更正格林威治标准时间日期 – ajonnet 2013-08-01 07:18:46