Project

General

Profile

Development #71918

Les soucis de date autour des changements heure d'été/hiver viennent de pytz/django

Added by Benjamin Dauvergne 2 months ago. Updated 2 months ago.

Status:
Nouveau
Priority:
Normal
Assignee:
-
Category:
-
Target version:
-
Start date:
01 December 2022
Due date:
% Done:

0%

Estimated time:
Patch proposed:
No
Planning:
No

Description

En voulant m'essayer à implémenter les dates de début de réservation variables, j'ai essayé d'utiliser dateutil.tz au lieu de pytz et je me suis aperçu qu'on avait rien à faire quand on fait des date + timedelta(days=x) pour que l'heure reste la même, ça marche tout seul (pareil avec tzlocal) en cherchant un peu j'ai vu que pytz était totalement déprécié et plus utilisé en Django 4 (en fait django est tout buggé parce qu'il utilise pytz et python 3.6 a introduit un changement non supporté par pytz si j'ai bien compris).

Un code qui essaie de faire un peu pareil que ce qui est fait dans Agenda.max_booking_datetime.

$ cat test_date.py
import datetime

import dateutil.tz

from django.conf import settings
from django.utils.timezone import localtime, now

import django

print(django.VERSION)

class Settings:
    TIME_ZONE = 'Europe/Paris'
    USE_TZ = True

settings.configure(Settings)

base_dj = localtime(now()).replace(hour=0, minute=0, second=0, microsecond=0)

europe_france_dtutil = dateutil.tz.gettz('Europe/Paris')

base_dateutil = localtime(now(), europe_france_dtutil).replace(hour=0, minute=0, second=0, microsecond=0)

for i in range(366):
    dt_dj = localtime(base_dj + datetime.timedelta(days=i))
    dt_dateutil = localtime(base_dateutil + datetime.timedelta(days=i))
    # check dst offset is equal
    assert dt_dj.dst() == dt_dateutil.dst(), (dt_dj.dst(), dt_dateutil.dst())
    if not dt_dj.hour == base_dj.hour:
        print('iteration', i)
        print('django')
        print(base_dj, ' ---> ', dt_dj)
        print('dateutil')
        print(base_dateutil, ' ---> ', dt_dateutil)
        break
 python3 test_date.py 
(3, 2, 15, 'final', 0)
iteration 116
django
2022-12-01 00:00:00+01:00  --->  2023-03-27 01:00:00+02:00
dateutil
2022-12-01 00:00:00+01:00  --->  2023-03-27 00:00:00+02:00

C'est le deuxième appel à localtime() qui foire la date coté django/pytz, avant ça l'offset dst est mauvais (il n'a pas été ajusté par le + timedelta() après il est bon mais l'heure est faussée). dateutil.tz n'a pas ce comportement, zoneinfo qui est utilisé par django 4 non plus.

History

#1

Updated by Emmanuel Cazenave 2 months ago

C'est bon à savoir.

Pour le plan d'action, je dirais de ne rien faire maintenant, qu'il faudra juste se souvenir de virer le code superflu quand on bossera sur la compat django 4.2 (LTS).

#2

Updated by Benjamin Dauvergne 2 months ago

Le comportement est vraiment parfait, jamais une date qui n'existe pas et autant que possible la bonne heure :
(2ème colonne django, 3ème dateutil)

113 2023-03-24 02:00:00+01:00 2023-03-24 02:00:00+01:00
114 2023-03-25 02:00:00+01:00 2023-03-25 02:00:00+01:00
115 2023-03-26 03:00:00+02:00 2023-03-26 03:00:00+02:00
116 2023-03-27 03:00:00+02:00 2023-03-27 02:00:00+02:00
117 2023-03-28 03:00:00+02:00 2023-03-28 02:00:00+02:00

330 2023-10-27 03:00:00+02:00 2023-10-27 02:00:00+02:00
331 2023-10-28 03:00:00+02:00 2023-10-28 02:00:00+02:00
332 2023-10-29 02:00:00+01:00 2023-10-29 02:00:00+02:00
333 2023-10-30 02:00:00+01:00 2023-10-30 02:00:00+01:00
334 2023-10-31 02:00:00+01:00 2023-10-31 02:00:00+01:00
330 2023-10-27 04:01:00+02:00 2023-10-27 03:01:00+02:00
331 2023-10-28 04:01:00+02:00 2023-10-28 03:01:00+02:00
332 2023-10-29 03:01:00+01:00 2023-10-29 03:01:00+01:00
333 2023-10-30 03:01:00+01:00 2023-10-30 03:01:00+01:00
334 2023-10-31 03:01:00+01:00 2023-10-31 03:01:00+01:00

Also available in: Atom PDF