Pregunta

Tengo una cita que se almacena como un número de días desde 1 de enero 1600 que tengo que tratar. Este es un formato de fecha legado que tengo que leer muchas, muchas veces en mi solicitud.

Anteriormente, había sido la creación de un calendario, componentes de la fecha vacías y la fecha de la raíz de esta manera:

self.gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar
                    ] autorelease];
id rootComponents = [[[NSDateComponents alloc] init] autorelease];
[rootComponents setYear: 1600];
[rootComponents setMonth: 1];
[rootComponents setDay: 1];
self.rootDate = [gregorian dateFromComponents: rootComponents];
self.offset = [[[NSDateComponents alloc] init] autorelease];

A continuación, para convertir el número entero más tarde a una cita, yo uso esto:

[offset setDay: theLegacyDate];
id eventDate = [gregorian dateByAddingComponents: offset
                                          toDate: rootDate
                                         options: 0];

(nunca cambia ningún valor de desplazamiento en cualquier otro lugar.)

El problema es que estoy recibiendo un tiempo diferente para rootDate en iOS vs Mac OS X. En Mac OS X, que estoy recibiendo la medianoche. En iOS, me estoy haciendo 08:12:28. (Hasta ahora, parece ser consistente con esto.) Cuando agrego mi número de días después, las estancias de tiempo extraño.

OS       | legacyDate | rootDate                  | eventDate
======== | ========== | ==========================|==========================
Mac OS X | 143671     | 1600-01-01 00:00:00 -0800 | 1993-05-11 00:00:00 -0700
iOS      | 143671     | 1600-01-01 08:12:28 +0000 | 1993-05-11 07:12:28 +0000

En la versión anterior de mi producto, que no se preocupan por el tiempo; ahora lo hago. ¿Por qué el tiempo raro en IOS, y lo que debería hacer al respecto? (Estoy suponiendo que la diferencia de hora es el horario de verano.)

He tratado de establecer la hora, minuto y segundo de rootComponents a 0. Esto no tiene impacto. Si me los puse a algo distinto de 0, se los añade a 8:12:28. Me he estado preguntando si esto tiene algo que ver con los segundos intercalares u otros cambios de reloj acumulativo.

O se trata por completo el enfoque equivocado para su uso en iOS?

¿Fue útil?

Solución 2

Parece que la respuesta correcta es hacer las cosas más simples. En lugar de hacer un rootDate, acabo de construir la fecha a partir de componentes cada vez. Esto no debería ser más lenta, y todavía se mantiene el código muy cerca de la idea.

La configuración inicial:

self.gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar
                    ] autorelease];
self.components = [[[NSDateComponents alloc] init] autorelease];
[components setYear: 1600];
[components setMonth: 1];

(Obviamente, propiedades y ivars se ajustan.)

Más tarde, para convertir en realidad una fecha legado a un NSDate:

[components setDay: 1 + theLegacyDate];
id eventDate = [gregorian dateFromComponents: components];

Esto tiene estas ventajas para mí:

  1. los usuarios menos Ivars.
  2. Es menos código.
  3. Se vuelve siempre la medianoche de ese día, independientemente de si el horario de verano está en vigor.

Otros consejos

Te imaginar razón sobre los segundos intercalares / cambios acumulativos de reloj que explican el problema de tiempo. Son las fechas que está tratando de hecho en el pasado, o es meramente una época arbitraria?

En cualquier caso, usted podría tratar de definir una nueva época que está mucho más cerca de nuestros días (por ejemplo, la época de cacao). Calcular un delta días entre la nueva época y el viejo y guardarlo como una constante. Cuando se necesita para procesar una fecha, esta delta para la fecha y luego usar su técnica NSCalendar existente, pero con su nueva época en lugar de la vieja. Que se espera evitar el problema de la sincronización del reloj que se está viendo.

Tenga en cuenta que iOS tiene en cuenta las reglas muy oscuros para diferentes zonas horarias. Lo más probable es que la medianoche, 1 Ene. 1600 en su zona horaria en realidad estaba en 07:12:28 GMT. Ha habido muchos casos en que personas se quejaron de errores en las conversiones de fecha y luego alguien se dio cuenta de que en realidad están en una zona horaria que hizo algún cambio en el calendario extraña hace muchos años.

Es necesario averiguar primero qué exacta NSDate los datos representan. "Número de días desde ene 1600 1 ª" no tiene sentido, ya que se necesita una zona horaria! Lo que debe hacer: encontrar un número "legado" donde se sabe qué día se supone que representa. Por ejemplo, si "sabe" que 143.671 se supone que es 11ª mayo de 1993 en su zona horaria, a continuación, iniciar con esa fecha que la raíz y add (x - 143671) días a la misma.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top