Question

une date de Parsing RFC3339 avec NSDateFormatter semble impossible, dans le cas général. Ai-je tort? [Edit 2 ans plus tard: il y a maintenant un moyen! Voir ci-dessous et la note.]

Un service Web non particulièrement malléable me nourrit des dates comme:

2009-12-31T00:00:00-06:00

compatible RFC3339, sortie par défaut de la bibliothèque de JAXB qu'ils utilisent. Notez le côlon, qui RFC3339 nécessite lorsque le décalage n'est pas un littéral "z":

time-numoffset  = ("+" / "-") time-hour ":" time-minute
time-offset     = "Z" / time-numoffset

Je veux analyser ceux-ci dans NSDates.

NSDateFormatter veut motifs dans la syntaxe spécifiée par Unicode , qui offre symboles de champ de date pour timezones comme "PDT", "-0800", "GMT-08: 00" mais pas "-08: 00".

recherche sur Google, et d'autres questions similaires de SO, produit des formats de date seulement comme

[myDateParser setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"];
/* or: */ [myDateParser setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];

Le dernier qui exige un littéral « Z », et l'ancienne insiste soit l'absence d'un colon ou de la présence d'un « GMT ». Cependant, ils sont apparus au travail avant ios 4.x (éventuellement en éliminant le tz complètement compensé;. Mes données ne sont pas claires)

Mes options à ce stade sont beaucoup désolé:

  • Découvrez quelques spécificateur de format sans papier, ou un étrange mode pour mettre en NSDateFormatter, qui accepte le côlon parasite: Longshot, probablement inexistante. [Note]
  • persuader mon éditeur de services pour transformer toutes les dates dans le temps zulu et spécifiez « Z »:. Défi politique
  • écrire ma propre sous-classe ou de recherche NSFormatter bon vieux strptime_l: le travail. :)
  • string-manipuler mon entrée et la bande le dernier colon. Fragile et laid, mais le chemin probable de moindre résistance

Ai-je compris la situation précise que NSDateFormatter actuelle suit strictement unicode sans extensions; et les formats unicode ne suffisent pas pour décrire complètement une date de RFC3339?

[FOOTNOTE] Je reviens à ces trois ans plus tard pour virer de bord sur un petit supplément: Unicode et Apple ont ajouté cette fonctionnalité aux chaînes de format, à partir de iOS6 / OSX10.8. Comparer La dernière révision de cette écriture avec son prédécesseur immédiat, et notez l'ajout de 5 "Z" s, ce qui donne un format de zone comme "-08: 00". Donc, si vous pouvez vous en sortir avec le soutien amerrissage forcé 5.x / 10.7, il y a une nouvelle bonne façon de le faire. Je vais laisser le stand de réponse précédente, comme il est toujours la meilleure approche quand la compatibilité descendante est nécessaire.

Était-ce utile?

La solution

chaîne de date d'analyse syntaxique Cocoa peut être une douleur, surtout si vous avez à traiter avec des dates générées par les services Web .NET.

Je suggère à la recherche dans la catégorie NSDate + InternetDateTime que Michael a Waterfall sur NSDate dans le cadre de son projet de MWFeedParser sur GitHub. Il a bien fonctionné pour moi exactement le format de l'analyse de la date que vous décrivez.

https://github.com/mwaterfall/MWFeedParser/

Autres conseils

- getObjectValue: forString: Gamme: Erreur: en fait parse les dates de RFC3339 correctement. Je ne sais pas pourquoi - dateWithString: ne peut pas:

// RFC3339 date formatting
NSString *dateString = @"2012-04-11T18:34:19+00:00";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ";

NSDate *date;
NSError *error;
[formatter getObjectValue:&date forString:dateString range:nil error:&error];

Les caractères de format de chaîne sont documentées nulle part dans la documentation Apple. Au lieu de cela il y a un lien caché au plus profond dans certains pointage de documents à la norme Unicode à

http://www.unicode.org/reports/tr35/tr35 -31 / TR35-dates.html # Date_Format_Patterns

En utilisant les informations à ce lien, il est assez simple:

- (NSDate*)dateFromRFC3339String:(NSString*)aString
{
    static NSDateFormatter* sRFC3339DateFormatter = nil;
    static NSDateFormatter* sRFC3339DateFormatterSubSeconds = nil;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];

        sRFC3339DateFormatter = [[NSDateFormatter alloc] init];
        [sRFC3339DateFormatter setLocale:enUSPOSIXLocale];
        [sRFC3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssXXXXX"];
        [sRFC3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];

        sRFC3339DateFormatterSubSeconds = [[NSDateFormatter alloc] init];
        [sRFC3339DateFormatterSubSeconds setLocale:enUSPOSIXLocale];
        [sRFC3339DateFormatterSubSeconds setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSSSSXXXXX"];
        [sRFC3339DateFormatterSubSeconds setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
    });

    NSDate* date = [sRFC3339DateFormatter dateFromString:aString];
    if (date == nil)
        date = [sRFC3339DateFormatterSubSeconds dateFromString:aString];

    return date;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top