web-dev-qa-db-fra.com

Analyse des dates JSON sur iPhone

Pardonnez-moi car je suis nouveau sur Objective C.

Je reçois des dates d'un service Web .NET au format/Date (xxxxxxxxxxxxxxxxxxxxxxxxxxxx) Je cherche des indications sur la meilleure manière d’analyser cela dans un objet NSDate. J'ai essayé d'utiliser dateWithTimeIntervalSince1970 dessus, mais il revient avec une date datant de 1969 pour une date que je connais bien: 2006.

Vous recherchez des indications sur la manière appropriée de gérer les dates JSON.

Merci d'avance!

36
user213517

En tant que programmeur .NET apprenant Objective-C, j’ai eu le même problème lorsque j’ai essayé de consommer un WebService .Net.

Au début, je pensais pouvoir utiliser NSDateFormatter ... J'ai trouvé une très bonne référence pour ses symboles ici , mais je me suis vite rendu compte qu'il me fallait convertir le nombre de millisecondes en secondes.

J'ai écrit le code pour le faire ... J'apprends toujours Obj-C mais je ne pense pas que cela aurait dû être aussi difficile ...

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

Espérons que quelqu'un puisse fournir une meilleure solution Obj-C. Sinon, je peux garder cela ou chercher un moyen de changer le format de sérialisation dans .NET

MODIFIER:

À propos de ce format JSON DateTime ... Si vous avez le contrôle du service, il serait probablement préférable de convertir la date en chaîne dans vos objets DataContract.

Formater à RFC1123 semble être une bonne idée pour moi en ce moment. Comme je peux probablement le récupérer facilement en utilisant un NSDateFormatter.

Citation de Rick Strahl

Il n'y a pas de littéral de date JavaScript et Microsoft a conçu un format de date personnalisé qui est essentiellement une chaîne marquée. Le format est une chaîne codée contenant la nouvelle valeur standard Date (millisecondes depuis 1970).

9
Stanley.Goldman

Je viens d'écrire ceci pour iOS 4.0+ (car il utilise NSRegularExpression). Il gère les dates avec ou sans décalage horaire. Vous semblez bien travailler, qu'en pensez-vous?

+ (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;
}
47
jasongregori

J'étais dans le même bateau en utilisant json-framework, qui ne prend pas en charge le format de date car ce n'est pas JSON officiel. Mon source provient d'une API construite à l'aide de JSON.Net. Voici ce que je suis venu avec:

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

Je n'ai pas la partie ajoutée dans le format de date que vous faites, donc je n'ai pas traité cela comme la réponse ci-dessus. Aucune erreur, non plus, c'est tout nouveau pour moi à ce stade.

18
toxaq

En fait, j'ai trouvé l'extrait de code avec NSRegularExpression très utile, jusqu'à ce que je propose une autre solution utilisant NSCharecterSet pour arrêter les millisecondes.

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

Enregistre une grande partie du traitement manuel des chaînes et rend le code beaucoup plus propre.

11
Mehfuz

Théorie: MS a codé DateTime C # en JSON sous forme de millisecondes depuis 1970. Solution:

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

C’est la solution la plus courte à laquelle je puisse penser.

5
user1257012

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

NSDate *currentDate = [NSDate date];
myDate = [commonDateFormatter dateFromString: strDate];
NSTimeInterval distanceBetweenDates = [currentDate timeIntervalSinceDate:myDate];
return [self stringFromTimeInterval:distanceBetweenDates];

} - (NSString *) stringFromTimeInterval: (NSTimeInterval) intervalle {NSInteger ti = (NSInteger) intervalle; NSMoins entiers = (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];
    }
}

}

0
shankar
0
Dave DeLong