解析IPhone上的JSON日期

解析IPhone上的JSON日期,iphone,objective-c,json,datetime,Iphone,Objective C,Json,Datetime,原谅我,我对目标C还不熟悉 我正在以/Date(xxxxxxxxxxxx-xxxxx)/格式从.NET Web服务返回日期。我正在寻找一些关于如何最好地将其解析为NSDate对象的方向。我试过从1970年开始使用DateWithTimeIntervals,但它返回的日期是1969年,因为我知道日期是2006年 寻找处理JSON日期的正确方法的方向 提前谢谢 之后使用an的方法。作为一名.NET程序员学习Objective-C,我在尝试使用.NET Web服务时遇到了同样的问题 起初我以为我可以使

原谅我,我对目标C还不熟悉

我正在以/Date(xxxxxxxxxxxx-xxxxx)/格式从.NET Web服务返回日期。我正在寻找一些关于如何最好地将其解析为NSDate对象的方向。我试过从1970年开始使用DateWithTimeIntervals,但它返回的日期是1969年,因为我知道日期是2006年

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


提前谢谢

之后使用an的方法。

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

起初我以为我可以使用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];
}
希望有人能提供更好的Obj-C解决方案。 如果没有,我可以保留这个,或者寻找一种方法来更改.NET中的序列化格式

编辑:

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

现在对我来说似乎是个好主意。因为我可以使用NSDateFormatter轻松地获取它

引自

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


我在使用json框架时也遇到了同样的问题,因为它不支持日期格式,因为它不是正式的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;
}

实际上,我发现带有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;
}
节省了大量的手动字符串处理,使代码更加干净。

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

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];
这是我能想到的最短的解决方案。

-(NSString*)convertToutTime:(NSString*)strDate{

} -(NSString*)stringFromTimeInterval:(NSTimeInterval)interval{ NSInteger ti=(NSInteger)间隔; NSInteger分钟=(ti/60)%60; NSInteger小时=(ti/3600)

if(小时数>24小时){
n累计天数=小时/24;
如果(天数>30天){
NSDateFormatter*dateFormatter=[[NSDateFormatter alloc]init];
[日期格式化程序setDateFormat:@“eed MMM,h:mm a”];
//[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@“IST”];
NSString*daydate=[dateFormatter stringFromDate:myDate];
返回日期;
}
否则{
返回[NSString stringWithFormat:@“%2ldd”(长)天];
}
}否则{
如果(小时==0和分钟<1){
返回[NSString stringWithFormat:@“今天”];
}
否则如果(小时==0和分钟<60){
返回[NSString stringWithFormat:@“%2ldm”,长)分钟];
}
否则{
返回[NSString stringWithFormat:@“%2ldh”(长)小时];
}
}

}

谢谢你的回答。我基本上采取了和你一样的方法。这感觉像一个黑客,我希望有一个更干净的解决方案,但哦,好吧,它现在起作用了;不应该是[扫描仪发布];!!:)很好的解决方案,但在解析后根本不使用secondNumber。它应该是更正GMTcan的日期,你可以发布一个如何执行此操作的示例吗?-1在dave提供如何执行此操作的代码之前,我不得不说这是错误的。Json日期是自特定日期和时间起的秒数。那么,设置格式如何返回正确的NSDate呢。文档链接中没有提及如何将格式设置为除MM DD YY样式以外的其他模式。此方法中有一个缺陷,它仅支持1970年1月1日之后的日期时间。1970年1月1日之前的日期将返回非常错误的日期。发生这种情况的原因是毫秒是无符号的,这意味着它只支持正数,所以任何负数都会导致不希望的结果。谢谢你的否决票。如果你读了这个问题,它说他们在寻找“某个方向”,而不是对每一种可能的日期格式都给出一个防弹的答案。一句话也许就足够了,但不管你的船怎么漂。因为提供了一个有用的答案而被否决,这让我想帮助其他人。+1这个方法支持1970年1月1日之前和之后的日期,不像这里的其他方法是“未签名”毫秒。我的解决方案需要TZ信息,所以我只是将该部分注释掉,然后转到比赛中。+1,这很好。@“^\\/date\((?\\d++)(?:([+-])(\\d{2})(\\d{2}))?\)\/$的用法是什么。我不明白发生了什么。@g-ganesh,这是正则表达式。它正在分析以下格式:“/Date(xxxxxxxxxxxx-xxxxx)/”。第一部分是unix时间,第二部分是时区。首先,所有这些都是双“\”,因为需要在NSString对象中转义“\”,然后在正则表达式中转义单个“\”。我们在字符串的开头有“^\/date”(“它与“/date”()匹配。然后我们有“(?\d++)”,它捕获可选的负秒,其中至少有两个数字(我不记得为什么它必须至少有两个)。然后“(?:([+-])(\d{2})(\d{2}])。这是一个大的,外部部分“(?:…”创建一个组但不捕获它,这是必需的,因此结尾的“?”可以使其成为可选的。其余的捕获时间
NSDate *currentDate = [NSDate date];
myDate = [commonDateFormatter dateFromString: strDate];
NSTimeInterval distanceBetweenDates = [currentDate timeIntervalSinceDate:myDate];
return [self stringFromTimeInterval:distanceBetweenDates];
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];
    }
}