Разбор даты JSON на IPhone

Простите меня, поскольку я новичок в Objective C.

Я возвращаюсь к датам веб-службы .NET в формате /Date (xxxxxxxxxxxxx-xxxx)/. Я ищу какое-то направление, как лучше всего разобрать это в объект NSDate. Я пробовал использовать dateWithTimeIntervalSince1970, но он возвращается с датой в 1969 году на дату, которую я знаю в 2006 году.

Ищете какое-то направление для правильной обработки дат JSON.

Спасибо заранее!

Ответ 1

Как изучение .NET-программиста Objective-C У меня была такая же проблема, когда я пытался использовать .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];
}

Надеюсь, кто-то может обеспечить лучшее решение Obj-C. Если нет, я могу сохранить это или искать способ изменить формат сериализации в .NET

EDIT:

Об этом формате JSON DateTime... Если у вас есть какой-либо контроль над сервисом, вероятно, лучше всего преобразовать дату в строку в объекты DataContract.

Форматирование в RFC1123 кажется для меня хорошей идеей прямо сейчас. Как я могу, вероятно, легко поднять его, используя NSDateFormatter.

Цитата из Рик Страл

Нет букв даты JavaScript, и Microsoft разработала собственный формат даты, который по существу является помеченной строкой. Формат - это строка, которая закодирована и содержит стандартное новое значение Date (миллисекунды с 1970 года).

Ответ 2

Я только что написал это для 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;
}

Ответ 3

Я был на одной лодке, используя json-framework, который не поддерживает формат даты, поскольку он не является официальным JSON. Мой источник - это API, построенный с использованием JSON.Net. Вот что я придумал:

- (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];
}

У меня нет добавленной части в формате даты, который вы делаете, поэтому я не рассматривал это как ответ выше. Никакой ошибки не поймать, это все новое для меня в этот момент.

Ответ 4

Я действительно нашел фрагмент с 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;
}

Сохраняет большую часть ручной обработки строк и делает код намного чище.

Ответ 5

Теория: MS кодировала С# DateTime в 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];

Это кратчайшее решение, о котором я могу думать.

Ответ 7

- (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) интервал;   NSInteger minutes = (ti/60)% 60;   NSInteger hours = (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];
    }
}

}