c++ - puedo - ¿La zona horaria de Windows escrita en el registro es confiable?
no puedo cambiar la fecha y hora de mi pc windows 7 (2)
Estoy creando un proyecto de c ++ que debería funcionar en varias zonas horarias. La aplicación recibe un evento, con una zona horaria de referencia, y este evento se muestra gráficamente al usuario en la hora correcta, en su zona horaria local. Por ejemplo, un usuario que trabaja en Berlín recibe un evento escrito en Tokio. El evento de Tokio se convierte primero a la hora UTC, luego se reconvierte de UTC a la hora local de la computadora en Berlín, y finalmente se muestra al usuario en su interfaz gráfica.
Para realizar la conversión de UTC a la hora local de la computadora, tengo varias funciones de la API de Windows a mi disposición para hacer el trabajo. Pero para convertir una hora de otra zona horaria a UTC, necesito obtener la información de la zona horaria del registro de Windows.
Ahora, algunas zonas horarias también tienen un horario de verano para considerar. Soy capaz de crear una regla de recurrencia desde la información de Windows sin problemas. Sin embargo, noté que el día en que debería ocurrir el horario de verano es a veces incorrecto en varias zonas horarias. Por ejemplo, la "Hora estándar de E. Sudamérica". Con la repetición proporcionada por Windows, el día de inicio de DST comienza 1 semana antes.
Si entendí bien, la regla de recurrencia devuelta por Windows para esta zona horaria específica dice "cada año, en el segundo mes, en la segunda semana del mes". Sin embargo, esta regla rara vez coincide con la fecha correcta publicada en Internet para el cambio de hora, mientras que las fechas son todas correctas si la regla sería "cada año, el segundo mes, en la 3ª semana del mes". Además, como puede ver en la captura de pantalla provista, los datos del registro de Windows muestran 2 semanas para la hora de inicio del horario de verano (resaltado en azul), pero 3 semanas para la hora de finalización del horario de verano (rodeado en rojo), que se calcula correctamente con mi código . La descripción del contenido de los datos se puede encontrar aquí: http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx
Tengo varias preguntas
- ¿He entendido correctamente la regla de recurrencia? (Esto es lo que dice MSDN al respecto: https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx )
- ¿Hay problemas conocidos sobre varias zonas horarias, especialmente la "Hora estándar de América del Sur"?
- ¿Hay alguna razón por la cual una fecha de inicio del horario de verano, que obviamente ocurre regularmente cada año, en la tercera semana del décimo mes, tenga un valor establecido en la segunda semana?
- ¿La zona horaria escrita en el registro de Windows es confiable? En caso contrario, ¿qué función de la API de Windows debo utilizar para convertir una zona horaria con DST desde una fecha escrita en una zona horaria diferente a la establecida en la máquina local?
NOTA He verificado firmemente si los datos que leí del registro eran correctos antes de publicar este mensaje. Estoy bastante seguro de que no es un error de este tipo.
NOTA Estoy trabajando con Windows 7, pero el problema sigue siendo el mismo en Windows 10
Como empleado de Microsoft con una participación significativa en los datos de zona horaria de Windows, permítame asegurarle que Microsoft trabaja muy duro para asegurarse de que lanza actualizaciones para mantener los datos de zona horaria de Windows tan precisos como sea posible.
Hay varios desafíos, incluido el momento en que se producen los cambios de zona horaria según los gobiernos. Por ejemplo, recientemente publicamos un aviso sobre los próximos cambios en la zona horaria de Windows para Fiji, Chipre, Sudán, Tonga, Namibia y Turks & Caicos . En algunos casos, podemos cumplir con las fechas de vigencia establecidas por estos diferentes gobiernos. En algunos casos no podemos porque no ofrecen suficiente tiempo de entrega.
Considere el caso reciente de Sudán, quien le dijo a la lista de correo tz de la IANA el 17 de octubre de 2017 sobre un cambio que entraría en vigencia el 1 de noviembre de 2017. La IANA ha procesado este cambio, al igual que Microsoft. Pero debido al breve aviso, y el tiempo que lleva procesar tal cambio en el sistema operativo Windows, pasará un poco antes de que se cree una nueva zona "Sudan Standard Time"
en los datos de la zona horaria de Windows. Por lo tanto, emitimos una guía provisional para utilizar una zona horaria diferente por el momento, luego cambiamos de nuevo una vez que tenemos datos que reflejan adecuadamente el historial completo del tiempo en la región afectada.
Con respecto a la zona horaria de Windows que mencionó, "E. South America Standard Time"
, los datos de la zona horaria son correctos. Si expande la entrada de registro, verá que hay una subclave llamada "Dynamic DST" que contiene los cambios año por año en los datos. Para algunas zonas horarias, esto no es necesario en absoluto, y para otras zonas horarias encontrará una cantidad muy pequeña de datos porque la misma regla se repite año tras año. Pero en el caso de Brasil, notará entradas de horario de verano dinámico desde 2009 hasta 2040.
(haga clic en la imagen para ver la resolución completa y anote las áreas que marqué manualmente en rojo que cambian año tras año)
Las entradas Dynamic DST son compatibles con la estructura Win32 DYNAMIC_TIME_ZONE_INFORMATION
y las API correspondientes con "dinámico" en su nombre, como GetDynamicTimeZoneInformation
. (También son compatibles con la clase System.TimeZoneInfo
en .NET Framework). La mayoría de estas API se encuentran en lugares desde Windows Vista / Server 2008, mientras que otras están disponibles en Windows 7 / Server 2012.
Tenga en cuenta que los procesos internos de Windows TZI
entrada TZI
que está en la clave principal de la regla dinámica del año actual. Esto es compatible con las API que funcionan con las estructuras Win32 TIME_ZONE_INFORMATION
, que se han implementado desde Windows 2000.
Para responder a las preguntas específicas que hiciste:
¿He entendido correctamente la regla de recurrencia?
La regla específica que citó es solo para 2017, y dice que el horario de verano finaliza el segundo mes (febrero), el tercer sábado, a las 23: 59: 59.999 hora local, y comienza nuevamente el décimo mes (octubre), El 2do sábado, a las 23: 59: 59.999 hora local. Tenga en cuenta que Brasil está en el hemisferio sur, por lo que el horario de verano comienza a fines del año y termina a principios del próximo año.
Además, puede que se pregunte por qué son las 23: 59: 59.999 el sábado en lugar de las 00: 00: 00.000 el domingo. Este es un artefacto de la historia. En el pasado, ha habido ciertos programas y procesos que utilizaron incorrectamente <=
lugar de <
para evaluar la transición, y por lo tanto, accidentalmente moverían el reloj un milisegundo al día siguiente, volveríamos a salir de él y luego volveríamos a hacerlo. Los eventos generados por el cambio de fecha errónea podrían llevar a más problemas. Microsoft ha hecho todo lo posible para solucionar esos errores, pero aún así opta por estar a 1 ms de distancia en lugar de arriesgarse a que el problema aparezca en algún lugar nuevo un día. (Esto solo se aplica a las transiciones que ocurren exactamente a la medianoche).
¿Hay problemas conocidos sobre varias zonas horarias, especialmente la "Hora estándar de América del Sur"?
No hay problemas conocidos para esa zona horaria, sin embargo, existe un problema conocido de que las zonas horarias de Windows (incluso con los datos DST dinámicos) solo pueden admitir un máximo de dos transiciones de zona horaria en un solo año. Por lo tanto, en lugares como Marruecos que realizan la transición cuatro veces al año, existen algunas soluciones internas que mantienen sincronizados los datos de la zona horaria actual, de modo que "ahora" es una representación precisa de la hora local, pero no puede representar correctamente todos los puntos del año en cualquier momento dado.
Tampoco tenemos actualmente una zona horaria que se asigne de forma limpia a Troll Station, Antarctica . La razón es que desde 2005 hasta 2015, esta estación de investigación (población menor de 50 años) realizó la transición a través de tres compensaciones diferentes (UTC + 0, UTC + 1 y UTC + 2) cada año.
Si su aplicación depende fundamentalmente de cualquiera de los escenarios anteriores, le recomiendo que utilice una API con fuentes de datos de la IANA en lugar de las API de Win32.
¿Hay alguna razón por la cual una fecha de inicio del horario de verano, que obviamente ocurre regularmente cada año, en la tercera semana del décimo mes, tenga un valor establecido en la segunda semana?
Sí, como se mencionó anteriormente, se debe al error intencional de 1 ms. El horario de verano de 2017, en las partes de Brasil que tienen horario de verano, comienza el domingo 15 de octubre a las 00: 00: 00.000. Ese es el tercer domingo del mes. 1 ms antes es 23: 59: 59.999 el sábado 14 de octubre, que es el segundo sábado del mes. Esto puede ser diferente cada año, por lo que hay datos DST dinámicos.
¿La zona horaria escrita en el registro de Windows es confiable? En caso contrario, ¿qué función de la API de Windows debo utilizar para convertir una zona horaria con DST desde una fecha escrita en una zona horaria diferente a la establecida en la máquina local?
Si está utilizando las API de Win32, ellas usan los datos del registro, por lo que no es necesario trabajar directamente con los datos del registro. Debe preferir las versiones "dinámicas" de las API, ya que representan adecuadamente los cambios año tras año en los datos del horario de verano dinámico. A veces estos están etiquetados como "Ex". Por ejemplo, la función TzSpecificLocalTimeToSystemTimeEx
es la que mejor maneja la función TzSpecificLocalTimeToSystemTimeEx
la que ha TzSpecificLocalTimeToSystemTimeEx
.
...
Dicho todo esto, si puede evitar el uso de datos de zona horaria de Windows en su aplicación, le recomiendo que lo haga. Prefiera las fuentes de datos de la IANA o las derivadas de ellas. Hay muchas rutas para trabajar con datos de zona horaria de la IANA. Las API de Windows más recientes, como Windows.Globalization.Calendar
y Windows.Globalization.DatetimeFormatting.DateTimeFormatter
en WinRT / UWP, de hecho utilizan las zonas horarias de la IANA , y ese es claramente el camino a seguir. En el espacio estándar de C ++, recomiendo usar las bibliotecas de fechas / tz de Howard Hinnant , o las proporcionadas por el proyecto de ICU . Hay varias otras opciones viables también.
Genial ver el nivel de detalle en la publicación de Matt.
Sobre la pregunta "¿Hay problemas conocidos sobre varias zonas horarias, especialmente la" E. Hora estándar de América del Sur "uno?"
No hay mucho más que agregar, excepto que, además de las increíbles y detalladas contribuciones de Matt a los datos de zona horaria de Windows, hay una gran cantidad de investigaciones con diferentes agencias, ONG y organismos gubernamentales que se describen en otra parte. Como ejemplo, existen desafíos adicionales en lugares como Marruecos que no solo realizan transiciones cuatro veces al año, sino que la información está sujeta a que el gobierno establezca la observancia oficial del horario de verano en la región y, a veces, con poco tiempo de espera, lo que lleva a publicaciones adicionales. y desafíos de despliegue. (Sin mencionar cuando un gobierno revisa una decisión varias veces ).
Por lo tanto, para algunas aplicaciones con dependencias críticas, se puede preferir una API a la fuente de IANA, o llamar a los datos de la zona horaria en Windows.Globalization.
Todo esto es oportuno, si perdonan el juego de palabras, justo antes de caer también en el hemisferio norte.