在IPhone上解析JSON日期

use*_*517 36 iphone datetime json objective-c

请原谅我,因为我是Objective C的新手.

我从/ Date(xxxxxxxxxxxxx-xxxx)/格式的.NET Web服务中获取日期.我正在寻找一些关于如何最好地将其解析为NSDate对象的方向.我已经尝试过对它使用dateWithTimeIntervalSince1970,但它在1969年的日期回来了,我所知道的日期是在2006年.

寻找处理JSON日期的正确方法的一些方向.

提前致谢!

jas*_*ori 47

我刚刚为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;
}
Run Code Online (Sandbox Code Playgroud)


tox*_*xaq 18

当我使用不支持日期格式的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];
}
Run Code Online (Sandbox Code Playgroud)

我没有你所做的日期格式的附加部分,所以我没有像上面的答案那样处理.没有错误捕获,这对我来说都是新的.

  • 谢谢你的downvote.如果您阅读了这个问题,它就说他们正在寻找"某个方向",而不是每个可能的日期格式的防弹答案.评论可能已经足够了,但不管你的船是什么漂浮.为实际贡献一个有用的答案而投降,这让我想要帮助别人. (2认同)

Meh*_*fuz 11

我实际上发现NSRegularExpression的片段非常有用,直到我想出了另一个使用NSCharecterSet来解决毫秒的解决方案.

+ (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;
}
Run Code Online (Sandbox Code Playgroud)

节省了大量的手动字符串处理,使代码更加清晰.


Sta*_*man 9

作为一名学习Objective-C的.NET程序员,当我尝试使用.Net WebService时,我遇到了同样的问题.

起初我以为我可以使用NSDateFormatter ...我在这里找到了一个非常好的参考符号,但我很快意识到我需要将数字从毫秒转换为秒.

我写了代码来做它...我还在学习Obj-C,但我不认为应该这么难...

- (NSDate *) getJSONDate{
    NSString* header = @"/Date(";
    uint headerLength = [header length];

    NSString*  timestampString;

    NSScanner* scanner = [[NSScanner alloc] initWithString:self];
    [scanner setScanLocation:headerLength];
    [scanner scanUpToString:@")" intoString:&timestampString];

    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];
}
Run Code Online (Sandbox Code Playgroud)

希望有人能提供更好的Obj-C解决方案.如果不是,我可以保留它或寻找一种方法来改变.NET中的序列化格式

编辑:

关于JSON DateTime格式...如果您对服务有任何控制,最好将日期转换为DataContract对象中的字符串.

格式化为RFC1123对我来说似乎是一个好主意.因为我可以使用NSDateFormatter轻松地获取它.

引自Rick Strahl

没有JavaScript日期文字,Microsoft设计了一个自定义日期格式,本质上是一个标记字符串.格式是一个编码的字符串,包含标准的新Date(自1970年以来的毫秒)值.


小智 5

理论:自1970年以来,MS将JSON中的C#DateTime编码为毫秒.解决方案:

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];
Run Code Online (Sandbox Code Playgroud)

这是我能想到的最短的解决方案.