Python: strftime () La compensación UTC no funciona como se espera en Windows

Cada vez que uso:

time.strftime("%z") 

Yo obtengo:

 Eastern Daylight Time 

Sin embargo, me gustaría el desplazamiento UTC en la forma + HHMM o -HHMM. Incluso he intentado:

 time.strftime("%Z") 

Lo que aún rinde:

 Eastern Daylight Time 

He leído varias otras publicaciones relacionadas con strftime () y% z siempre parece devolver el desplazamiento UTC en el formato correcto + HHMM o -HHMM. ¿Cómo obtengo strftime () para generar en el formato + HHMM o -HHMM para python 3.3?

Edición: estoy ejecutando Windows 7

Para una solución adecuada, vea la respuesta de abarnert a continuación .


Puede usar time.altzone que devuelve un desplazamiento negativo en segundos. Por ejemplo, estoy en CEST en este momento (UTC + 2), así que obtengo esto:

 >>> time.altzone -7200 

Y para ponerlo en el formato deseado:

 >>> '{}{:0>2}{:0>2}'.format('-' if time.altzone > 0 else '+', abs(time.altzone) // 3600, abs(time.altzone // 60) % 60) '+0200' 

Como mencionó abarnert en los comentarios, time.altzone proporciona el desplazamiento cuando DST está activo, mientras que time.timezone hace cuando DST no está activo. Para averiguar cuál usar, puede hacer lo que JF Sebastian sugirió en su respuesta a una pregunta diferente . Para que pueda obtener la compensación correcta de esta manera:

 time.altzone if time.daylight and time.localtime().tm_isdst > 0 else time.timezone 

Como también lo sugirió, puede usar lo siguiente en Python 3 para obtener el formato deseado usando datetime.timezone :

 >>> datetime.now(timezone.utc).astimezone().strftime('%z') '+0200' 

En 2.x, si miras los documentos por time.strftime , ni siquiera mencionan %z . No se garantiza que exista en absoluto, y mucho menos que sea consistente en todas las plataformas. De hecho, como implica la nota a pie de página 1 , se deja a la función C strftime . En 3.x , por otro lado, sí mencionan %z , y la nota al pie que explica que no funciona de la manera que usted espera no es fácil de ver; eso es un error abierto

Sin embargo, en 2.6+ (incluidas todas las versiones 3.x), se garantiza que datetime.strftime sea compatible con %z como “Desfase UTC en la forma + HHMM o -HHMM (cadena vacía si el objeto es ingenuo)”. Por lo tanto, esto lo convierte en una solución bastante sencilla: usar datetime lugar de time . Exactamente cómo cambiar las cosas depende de lo que está intentando hacer exactamente: usar Python-dateutil tz luego datetime.now(tz.tzlocal()).strftime('%z') es la forma de obtener el formato de la zona horaria local como un desplazamiento GMT, pero si está intentando formatear una hora completa, los detalles serán un poco diferentes.

Si observa la fuente, time.strftime básicamente solo verifica la cadena de formato en busca de especificadores válidos para la plataforma y llama a la función nativa de strftime , mientras que datetime.strftime tiene un montón de manejo especial para diferentes especificadores, incluido %z ; en particular, reemplazará %z con una versión formateada de utcoffset antes de pasar cosas a strftime . El código ha cambiado varias veces desde la versión 2.7, e incluso se ha reorganizado radicalmente una vez, pero básicamente existe la misma diferencia incluso en el troncal anterior a 3.5.

Use time.timezone para obtener la time.timezone de tiempo en segundos.

Formatearlo usando:

 ("-" if time.timezone > 0 else "+") + time.strftime("%H:%M", time.gmtime(abs(time.timezone))) 

para convertir el mismo al formato +/- HH: MM.

Por cierto, ¿no se supone que esto es un error? Según los documentos de strftime .

También pensé que esta respuesta SO podría ayudarlo a convertir la cadena de desplazamiento de Zona al formato HH: MM. Pero como "%z" no funciona como se esperaba, siento que es discutible.

NOTA: la zona time.timezone es inmune al horario de verano.

No sorprenderá que persista este error, cuál es la última versión de Windows disponible actualmente, Win 10, versión 1703 (Creadores). Sin embargo, el tiempo avanza y hay una hermosa biblioteca de fecha y hora llamada péndulo que hace lo que la pregunta pide. Sébastien Eustace (autor principal del producto?) Me ha mostrado esto.

 >>> pendulum.now().strftime('%z') '-0400' 

péndulo asume UTC / GMT a menos que se indique lo contrario, y mantiene la zona horaria con el objeto de fecha y hora. Hay muchas otras posibilidades, entre ellas estas:

 >>> pendulum.now(tz='Europe/Paris').strftime('%z') '+0200' >>> pendulum.create(year=2016, month=11, day=5, hour=16, minute=23, tz='America/Winnipeg').strftime('%z') '-0500' >>> pendulum.now(tz='America/Winnipeg').strftime('%z') '-0500'