42 votes

Pourquoi NSDateFormatter renvoie-t-il la date zéro pour ces 4 fuseaux horaires?

Essayez d’exécuter ceci sur iOS6 (n’avez pas encore testé iOS6):

 NSDateFormatter *julianDayDateFormatter = nil;
julianDayDateFormatter = [[NSDateFormatter alloc] init];
[julianDayDateFormatter setDateFormat:@"g"];

for (NSString *timeZone in [NSTimeZone knownTimeZoneNames]) {
    julianDayDateFormatter.timeZone = [NSTimeZone timeZoneWithName: timeZone];
    NSDate *date = [julianDayDateFormatter dateFromString:[NSString stringWithFormat:@"%d", 2475213]];
    if (date == nil)
        NSLog(@"timeZone = %@", timeZone);
}
 

et vous obtenez le résultat suivant:

 America/Bahia
America/Campo_Grande
America/Cuiaba
America/Sao_Paulo
 

Quelqu'un peut-il expliquer pourquoi ces quatre fuseaux horaires se comportent de la sorte avec NSDateFormatter défini sur le nombre de jours julien? Tous les autres fuseaux horaires obligent NSDateFormatter à renvoyer les dates NSD réelles.

61voto

Jon Skeet Points 692016

J'ai un soupçon. Seulement un soupçon, mais un assez fort.

Cette valeur représente le 19 octobre 2064. L'heure du brésil zones d'observer l'heure d'été commençant à minuit (heure locale) - c'est lors de leurs horloges d'aller de l'avant, de sorte à minuit elle-même n'existe pas. Le 19 octobre est l'un de ces transitions.

Voici un exemple de code à l'aide de Noda Temps, mon .NET date/heure API. Il vérifie si le début de la journée, dans tous les fuseaux horaires, il sait à ce sujet est en fait de minuit:

using System;
using NodaTime;

class Test
{
    static void Main()
    {
        var localDate = new LocalDate(2064, 10, 19);
        var provider = DateTimeZoneProviders.Tzdb;
        foreach (var id in provider.Ids)
        {
            var zone = provider[id];
            var startOfDay = zone.AtStartOfDay(localDate).LocalDateTime.TimeOfDay;
            if (startOfDay != LocalTime.Midnight)
            {
                Console.WriteLine(id);
            }
        }
    }
}

Qui produit très semblable à la liste:

America/Bahia
America/Campo_Grande
America/Cuiaba
America/Sao_Paulo
Brazil/East

Je soupçonne Brésil/Est peut être un alias pour l'Amérique/Sao_Paolo, c'est pourquoi il n'est pas sur votre liste.

De toute façon, pour en revenir à votre jour Julien question - je soupçonne que le formateur veut toujours retourner un NSDate * qui est à l'minuit heure locale. Qui n' existe pas pour le 19 octobre 2064 dans ces zones de temps... donc il retourne nil. Personnellement, je suggère qu'il doit retourner la valeur à 1h du matin au lieu de cela, mais bon...

16voto

lpa Points 418

Les crédits de Jon Skeet pour me mettre sur la bonne voie. Cependant, je veux juste clarifier sa réponse dans un iOS contexte.

Lorsque vous demandez NSDateFormatter pour convertir un jour julien dans un NSDate, vous pouvez spécifier uniquement les nombres entiers (en général, vous pouvez spécifier une partie décimale pour les heures/minutes/secondes de la journée) dans la chaîne à analyser. Parce que Apple délimite julian jours à minuit (par opposition à midi, dans l'astronomie, lire la suite ici: http://www.unicode.org/reports/tr35/#Date_Field_Symbol_Table) et certains minuits simplement n'existe pas (merci pour cette remarque @JonSkeet) NSDateFormatter indique que ce point particulier dans le temps n'existe pas dans ce fuseau horaire et retourne nil.

Pour l'enregistrement, iOS5 ne se comporte pas comme cela et je suis d'accord avec Jon Skeet, que NSDateFormatter doit retourner un NSDate ajusté pour l'heure d'été à la place de néant, comme ce jour julien en fait existe! J'ai déposé un bug avec Apple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X