Me gustaría entender cuándo debería estar usando
datetime.now(tz=pytz.utc).replace(tzinfo=None)a diferencia de simplemente
datetime.utcnow()¿Esto último no tendrá en cuenta, por ejemplo, el horario de verano?
Mucho de cómo funcionará datetime.datetime depende de la máquina en la que se ejecute. La configuración de la hora local y la zona horaria de la máquina host determinará el resultado que obtendrá.
Si la máquina host está en la zona horaria UTC, no habrá diferencia entre datetime.datetime.now() y datetime.datetime.utcnow() .
De acuerdo con la documentación de pytz :
La forma preferida de tratar con los tiempos es trabajar siempre en UTC, convirtiendo a la hora local solo cuando se genera una salida para ser leída por humanos.
pytz se usa para contabilizar el horario de verano, y datetime.datetime.utcnow() se usa para proporcionar un punto de referencia estandarizado universal sobre el cual puede calcular el horario de verano. datetime.datetime.utcnow() por sí solo no tendrá en cuenta el horario de verano.
Nunca debe usar datetime.utcnow() ya que le brinda una marca de tiempo ingenua con la que puede dispararse en el pie. Si realmente quiere una marca de tiempo ingenua, explíquela usando su primera opción. now() toma el parámetro tz (que siempre debe proporcionar, para evitar usar el host TZ). Pero utcnow() obviamente no proporciona eso. Así que está condenado.
Por ejemplo, supongamos que tiene una marca de tiempo UTC y desea convertirla a la hora local en la Ciudad de México:
my_timestamp.astimezone(pytz.timezone("America/Mexico_City"))Se ve bien, ¿verdad? No, mira esto:
>>> datetime.utcnow() datetime.datetime(2021, 3, 29, 21, 40, 44, 329559) >>> datetime.utcnow().astimezone(pytz.timezone("America/Mexico_City")) datetime.datetime(2021, 3, 29, 21, 40, 44, 329559, tzinfo=<DstTzInfo 'America/Mexico_City' CST-1 day, 18:00:00 STD>) Como puede ver, astimezone simplemente agregará el tz si le da una marca de tiempo ingenua, sin ajustar la hora real como se esperaba. (si no quisiera ajustar, habría usado .replace )
Es súper confuso, y no te encuentras con problemas como este si solo te aseguras de no tener marcas de tiempo ingenuas. Puede tenerlos en sus API externas, si lo desea, pero agregue una zona horaria cuando ingresen al sistema.
Para resumir: siempre use datetime.now(tz=some_tz) .
Para citar el artículo de Paul Ganssle Deja de usar utcnow y utcfromtimestamp
[No] use utcnow() o utcfromtimestamp() simplemente porque es la abstracción incorrecta.
[...]
La razón por la que no podemos simplemente cambiar utcnow() a un alias por ahora (timezone.utc) en la biblioteca estándar es que cambiaría la semántica de cómo los consumidores tratan esas fechas y horas.
IIRC, contribuyó bastante a cpython (el núcleo de Python) alrededor de la fecha y hora.
Por lo tanto: no use datetime.utcnow()