¿Por qué NSDateFormatter devuelve la fecha cero para estas 4 zonas horarias?


Intente ejecutar esto en iOS6 (no ha probado pre 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);
}

Y se obtiene la siguiente salida:

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

¿Puede alguien explicar por qué estas cuatro zonas horarias se comportan así con NSDateFormatter establecido en números de días julianos? Todas las demás zonas horarias hacen que NSDateFormatter devuelva NSDates reales.

Author: vcsjones, 2012-10-17

2 answers

Tengo una sospecha. Sólo una sospecha, pero bastante fuerte.

Ese valor representa el 19 de octubre de 2064. Las zonas horarias brasileñas observan el horario de verano a partir de la medianoche local - es entonces cuando sus relojes avanzan, por lo que la medianoche en sí no existe. El 19 de octubre es una de esas transiciones.

Aquí hay un código de ejemplo usando Noda Time, my.NET date/time API. Comprueba si el comienzo del día en cada zona horaria que conoce es en realidad medianoche:

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);
            }
        }
    }
}

Que produce una lista muy similar:

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

Sospecho que Brasil/Este puede ser un alias para América/Sao_Paolo, por lo que no está en su lista.

De todos modos, para volver a su edición del día juliano, sospecho que el formateador siempre quiere devolver un NSDate * que es a la medianoche local. Eso no existe para el 19 de octubre de 2064 en esas zonas horarias... por lo tanto, devuelve cero. Personalmente sugeriría que debería devolver el valor de 1am en su lugar, pero Hola...

 61
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-16 20:40:19

Créditos a Jon Skeet por ponerme en el camino correcto. Sin embargo, solo quiero aclarar su respuesta en un contexto de iOS.

Cuando le pide a NSDateFormatter que convierta un número de día juliano en una NSDate, solo puede especificar números enteros (generalmente puede especificar una parte decimal para las horas/minutos/segundos del día) en la cadena a analizar. Debido a que Apple delimita los días julianos a la medianoche (a diferencia del mediodía en astronomía, lea más aquí: http://www.unicode.org/reports/tr35/#Date_Field_Symbol_Table ) y algunas midnights simplemente no existe (gracias por señalar que @JonSkeet) NSDateFormatter identifica que ese punto en particular en el tiempo no existe en esa zona horaria y devuelve nil.

Para que conste, iOS5 no se comporta así y estoy de acuerdo con Jon Skeet, que NSDateFormatter debe devolver un NSDate ajustado para DST en lugar de cero, ya que ese día juliano en particular, de hecho, existe! Presenté un error con Manzana.

 16
Author: lpa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-17 09:01:31