- en
- Language: fr
Fuseaux horaires¶
Aperçu¶
Lorsque la prise en charge des fuseaux horaires est activée, Django stocke les informations de date/heure en UTC dans la base de données, utilise en interne des objets date/heure conscients de leur fuseau horaire et les convertit dans les gabarits et les formulaires en utilisant le fuseau horaire de l’utilisateur.
C’est très pratique si vos utilisateurs sont répartis sur plus d’un fuseau horaire et que vous vouliez afficher les informations temporelles selon l’heure locale de chacun.
Même si votre site Web n’est utilisé que dans un seul fuseau horaire, stocker les données en UTC dans la base de données fait partie des bonnes pratiques. Une des raisons principales étant l’heure d’été (Daylight Saving Time - DST). Dans beaucoup de pays, l’heure d’été fait avancer d’une heure au printemps et reculer d’une heure en automne. Si vous travaillez en temps local, vous risquez d’obtenir des erreurs deux fois par année, au moment de la transition (la documentation de pytz aborde ces questions plus en détails). ce n’est probablement pas un problème pour votre blog, mais c’en est un si vous surfacturez ou sous-facturez vos clients d’une heure, deux fois par année, chaque année. La solution à ce problème est d’utiliser UTC dans le code, et le temps local uniquement lors des interactions avec les utilisateurs du site.
La prise en charge des fuseaux horaires est désactivée par défaut. Pour l’activer, définissez USE_TZ = True dans votre fichier de réglages. L’installation de pytz est fortement recommandée, mais n’est pas toujours obligatoire, en fonction du moteur de base de données, du système d’exploitation et du fuseau horaire. Si vous obtenez une exception à la suite de requêtes de dates ou d’heures, essayez de l’installer avant de créer un ticket. C’est aussi simple que :
$ pip install pytz
Note
Le fichier settings.py créé par défaut par django-admin startproject définit USE_TZ = True par commodité.
Note
Il existe également un réglage différent mais lié nommé USE_L10N qui contrôle l’activation ou non des formats de régionalisation. Voir Régionalisation des formats pour plus de détails.
Si vous êtes empêtré dans un problème particulier, commencez par lire la FAQ des fuseaux horaires.
Concepts¶
Objets datetime naïfs et conscients¶
Les objets datetime.datetime de Python possèdent un attribut tzinfo pouvant être utilisé pour stocker le fuseau horaire, représenté par une instance d’une sous-classe de datetime.tzinfo. Lorsque cet attribut est défini et qu’il décrit un décalage horaire, l’objet datetime est conscient. Dans le cas contraire, il est naïf.
Vous pouvez utiliser is_aware() et is_naive() pour déterminer si les objets datetime sont conscients (aware) ou naïfs.
Lorsque la prise en charge des fuseaux horaires est désactivée, Django utilise des objets datetime naïfs en heure locale. C’est simple et suffisant dans de nombreux cas. Dans ce mode, pour obtenir le temps actuel, vous écririez :
import datetime
now = datetime.datetime.now()
Lorsque la prise en charge des fuseaux horaires est activée (USE_TZ=True), Django utilise des objets datetime conscients de leur fuseau horaire. Si vote code crée des objets datetime, ils devraient également être conscients. Dans ce mode, l’exemple ci-dessus devient :
from django.utils import timezone
now = timezone.now()
Avertissement
La manipulation des objets datetime conscients n’est pas toujours intuitive. Par exemple, le paramètre tzinfo du constructeur standard de datetime ne fonctionne pas de manière fiable pour les fuseaux horaires avec heure d’été. L’utilisation de l’heure UTC est généralement sûre ; si vous utilisez d’autres fuseaux horaires, vous devriez lire attentivement la documentation de pytz.
Note
Les objets datetime.time de Python comportent également un attribut tzinfo, et PostgreSQL possède un type correspondant time with time zone (heure avec fuseau horaire). Cependant, comme l’explique la documentation de PostgreSQL, ce type « prête des propriétés qui font douter de son utilité ».
Django ne prend en charge que des objets time naïfs et génère une exception si vous essayez d’enregistrer un objet time conscient, dans la mesure où un fuseau horaire n’a pas de sens pour un objet time sans date associée.
Interprétation des objets datetime naïfs¶
Lorsque USE_TZ vaut True, Django accepte encore les objets datetime naïfs, afin de préserver la rétrocompatibilité. Lorsque la couche base de données en reçoit un, elle essaie de le rendre conscient en l’interprétant dans le fuseau horaire par défaut et génère un avertissement.
Malheureusement, durant les transitions d’heure d’été, certains objets datetime n’existent pas ou sont ambigus. Dans de telles situations, pytz génère une exception. D’autres implémentations de tzinfo, tel que le fuseau local utilisé comme valeur de repli quand pytz n’est pas installé, peuvent générer une exception ou renvoyer un résultat imprécis. C’est pourquoi vous devriez toujours créer des objets datetime conscients lorsque la prise en charge des fuseaux horaires est activée.
En pratique, c’est rarement un problème. Django produit des objets datetime conscients dans les modèles et les formulaires, et la plupart du temps, les nouveaux objets datetime sont créés à partir d’objets existants par des opérations timedelta. Le seul objet datetime qui est souvent créé dans du code applicatif est l’heure actuelle et timezone.now() fait automatiquement ce qu’il faut.
Fuseau horaire par défaut et fuseau horaire actuel¶
Le fuseau horaire par défaut est le fuseau horaire défini par le réglage TIME_ZONE.
Le fuseau horaire actuel est le fuseau horaire utilisé pour l’affichage.
Vous devriez définir le fuseau horaire actuel au fuseau horaire réel de l’utilisateur avec activate(). Sinon, c’est le fuseau horaire par défaut qui est utilisé.
Note
Comme expliqué dans la documentation de TIME_ZONE, Django définit des variables d’environnement afin que son processus tourne dans le fuseau horaire par défaut. Ce comportement est indépendant de la valeur de USE_TZ et du fuseau horaire actuel.
Lorsque USE_TZ vaut True, ceci est utile pour préserver la rétrocompatibilité avec les applications qui se basent encore sur le temps local. Cepedant, comme expliqué ci-dessus, ce n’est pas totalement fiable et vous devriez toujours travailler avec des objets datetime conscients en UTC dans votre propre code. Par exemple, utilisez utcfromtimestamp() au lieu de fromtimestamp() et n’oubliez pas de définir tzinfo à utc.
Sélection du fuseau horaire actuel¶
Le fuseau horaire actuel est l’équivalent de la langue actuelle pour les traductions. Cependant, il n’y a pas d’équivalent à l’en-tête HTTP Accept-Language que Django pourrait utiliser pour déterminer automatiquement le fuseau horaire de l’utilisateur. Au lieu de cela, Django fournit des fonctions de sélection du fuseau horaire. Utilisez-les pour bâtir une logique de sélection du fuseau horaire qui a du sens dans votre situation.
La plupart des sites Web se préoccupant des fuseaux horaires ne font que demander aux utilisateurs leur fuseau horaire de domicile et stockent cette information dans le profil des utilisateurs. Pour les utilisateurs anonymes, ils utilisent le fuseau horaire de la majorité de leur public ou l’heure UTC. pytz propose des utilitaires, comme une liste de fuseaux horaires par pays, qu’il est possible d’exploiter pour faire une présélection des choix les plus probables.
Voici un exemple qui stocke le fuseau horaire actuel dans la session (la gestion d’erreur est totalement absente par simplicité).
Ajoutez le middleware suivant à MIDDLEWARE_CLASSES:
import pytz
from django.utils import timezone
class TimezoneMiddleware(object):
def process_request(self, request):
tzname = request.session.get('django_timezone')
if tzname:
timezone.activate(pytz.timezone(tzname))
else:
timezone.deactivate()
Créez une vue capable de définir le fuseau horaire actuel :
from django.shortcuts import redirect, render
def set_timezone(request):
if request.method == 'POST':
request.session['django_timezone'] = request.POST['timezone']
return redirect('/')
else:
return render(request, 'template.html', {'timezones': pytz.common_timezones})
Ajoutez un formulaire dans template.html dont la cible POST est cette vue :
{% load tz %}
{% get_current_timezone as TIME_ZONE %}
<form action="{% url 'set_timezone' %}" method="POST">
{% csrf_token %}
<label for="timezone">Time zone:</label>
<select name="timezone">
{% for tz in timezones %}
<option value="{{ tz }}"{% if tz == TIME_ZONE %} selected="selected"{% endif %}>{{ tz }}</option>
{% endfor %}
</select>
<input type="submit" value="Set" />
</form>
Saisie de données avec fuseau horaire dans les formulaires¶
Lorsque vous activez la prise en charge des fuseaux horaires, Django interprète les dates/heures saisies dans les formulaires dans le fuseau horaire actuel et place des objets datetime conscients dans
Si le fuseau horaire actuel génère une exception pour les dates/heures qui n’existent pas ou qui sont ambiguës car elles se trouvent dans une transition d’heure d’été (les fuseaux horaires dans pytz le font), ces dates/heures seront signalées comme non valables.
Affichage de fuseaux horaires conscients dans les gabarits¶
Lorsque vous activez la prise en charge des fuseaux horaires, Django convertit les objets datetime dans le fuseau horaire actuel au moment où ils sont affichés dans un gabarit. Ce comportement est très semblable à la régionalisation des formats.
Avertissement
Django ne convertit pas les objets datetime naïfs car ils peuvent être ambigus et parce que votre code ne doit jamais produire de tels objets naïfs lorsque la prise en charge des fuseaux horaires est activée. Cependant, vous pouvez forcer la conversion avec les filtres de gabarit décrits ci-dessous.
La conversion en temps local n’est pas toujours adéquate, par exemple dans le cas où vous générez du contenu à destination d’autres ordinateurs. Les filtres et balises suivants, mis à disposition par la bibliothèque de balises de gabarit tz, permettent de contrôler les conversions de fuseaux horaires.
Balises de gabarit¶
localtime¶
Active ou désactive la conversion d’objets datetime conscients dans le fuseau horaire actuel à l’intérieur du bloc contenu.
Cette balise a exactement le même effet que le réglage USE_TZ en ce qui concerne le moteur de gabarits. Elle permet un contrôle plus précis des endroits où la conversion se fait.
Pour activer ou désactiver la conversion pour un bloc de gabarit, utilisez :
{% load tz %}
{% localtime on %}
{{ value }}
{% endlocaltime %}
{% localtime off %}
{{ value }}
{% endlocaltime %}
Note
La valeur de USE_TZ n’est pas prise en compte à l’intérieur d’un bloc {% localtime %}.
timezone¶
Définit ou annule le fuseau horaire actuel dans le bloc contenu. Lorsque le fuseau horaire actuel est annulé, c’est le fuseau horaire par défaut qui s’applique.
{% load tz %}
{% timezone "Europe/Paris" %}
Paris time: {{ value }}
{% endtimezone %}
{% timezone None %}
Server time: {{ value }}
{% endtimezone %}
get_current_timezone¶
Vous pouvez obtenir le nom du fuseau horaire actuel en utilisant la balise get_current_timezone:
{% get_current_timezone as TIME_ZONE %}
Si vous activez le processeur de contexte django.template.context_processors.tz, chaque objet RequestContext contient alors une variable TIME_ZONE avec la valeur de get_current_timezone().
Filtres de gabarit¶
Ces filtres acceptent aussi bien des objets datetime conscients que naïfs. À des fins de conversion, ils partent du principe que les objets naïfs sont dans le fuseau horaire par défaut. Ils renvoient toujours des objets datetime conscients.
localtime¶
Force la conversion d’une valeur unique dans le fuseau horaire actuel.
Par exemple :
{% load tz %}
{{ value|localtime }}
timezone¶
Force la conversion d’une seule valeur dans un fuseau horaire arbitraire.
Le paramètre doit être une instance d’une sous-classe de tzinfo ou un nom de fuseau horaire. S’il s’agit d’un nom de fuseau horaire, pytz est obligatoire.
Par exemple :
{% load tz %}
{{ value|timezone:"Europe/Paris" }}
Guide de migration¶
Voici comment effectuer la migration d’un projet démarré avant que Django ne prenne en charge les fuseaux horaires.
Base de données¶
PostgreSQL¶
Le moteur PostgreSQL stocke les dates/heures comme timestamp with time zone. En pratique, cela signifie qu’il convertit les objets datetime en UTC à partir du fuseau horaire de la connexion au moment du stockage, et à partir d’UTC vers le fuseau horaire de la connexion lors de la sélection.
En conséquence, si vous utilisez PostgreSQL, vous pouvez librement passer de USE_TZ = False à USE_TZ = True et inversement. Le fuseau horaire de la connexion de la base de données sera défini respectivement à TIME_ZONE et à UTC, ce qui fait que Django reçoit des dates/heures correctes dans tous les cas. Vous n’avez pas à convertir les données.
Autres bases de données¶
Les autres moteurs stockent les dates/heures sans information de fuseau horaire. Si vous passez de USE_TZ = False à USE_TZ = True, vous devez convertir vos données du temps local en UTC, ce qui n’est pas déterministe si votre temps local est sujet à l’heure d’été.
Code¶
La première étape est d’ajouter USE_TZ = True à votre fichier de réglages et d’installer pytz (si possible). À ce stade, tout devrait fonctionner en principe. Si vous créez des objets datetime naïfs dans votre code, Django les rend conscients en cas de besoin.
Cependant, ces conversions peuvent échouer aux alentours des transitions d’heure d’été, ce qui signifie que vous n’obtenez pas encore tous les bénéfices de la prise en charge des fuseaux horaires. Il est également probable que vous rencontriez quelques problèmes car il est impossible de comparer une date/heure naïve avec une date/heure consciente. Comme Django vous donne maintenant des dates/heures conscientes, vous obtiendrez des exceptions chaque fois que vous comparez une date/heure provenant d’un modèle ou d’un formulaire avec une date/heure naïve que vous avez créée dans votre code.
La seconde étape est donc de réviser votre code pour que chaque endroit où vous créer des objets datetime, ceux-ci soient conscients. Cela peut se faire progressivement. django.utils.timezone définit quelques utilitaires bien pratiques pour du code compatible : now(), is_aware(), is_naive(), make_aware() et make_naive().
Finalement, pour vous aider à trouver le code qui a besoin d’être mis à jour, Django émet un avertissement lorsque vous essayez d’enregistrer une date/heure naïve dans la base de données :
RuntimeWarning: DateTimeField ModelName.field_name received a naive
datetime (2012-01-01 00:00:00) while time zone support is active.
Durant le développement, vous pouvez transformer ces avertissements en exceptions et obtenir une trace d’appel en ajoutant ce qui suit dans votre fichier de réglages :
import warnings
warnings.filterwarnings(
'error', r"DateTimeField .* received a naive datetime",
RuntimeWarning, r'django\.db\.models\.fields')
Instantanés¶
Lors de la sérialisation d’une date/heure consciente, le décalage UTC est pris en compte, comme ceci :
"2011-09-01T13:20:30+03:00"
Pour une date/heure naïve, ce n’est évidemment pas le cas :
"2011-09-01T13:20:30"
Pour les modèles comportant des champs DateTimeField, cette différence rend impossible l’écriture d’un instantané fonctionnant à la fois avec et sans prise en charge des fuseaux horaires.
Les instantanés générés avec USE_TZ = False ou avant Django 1.4 utilisent le format « naïf ». Si votre projet contient de tels instantanés et que vous activez la prise en charge des fuseaux horaires, vous verrez des exceptions RuntimeWarning lorsque vous les chargez. Pour vous débarrasser des ces avertissements, vous devez convertir vos instantanés au format « conscient ».
Vous pouvez régénérer les instantanés avec loaddata, puis dumpdata. Ou s’ils ne sont pas trop gros, vous pouvez simplement les modifier et ajouter le décalage UTC correspondant à votre TIME_ZONE dans chaque objet datetime sérialisé.
FAQ¶
Configuration¶
Je n’ai pas besoin de plusieurs fuseaux horaires. Dois-je activer la prise en charge des fuseaux horaires ?
Oui. Lorsque la prise en charge des fuseaux horaires est activée, Django utilise un modèle plus précis du temps local. Cela vous protège de bogues subtils et non reproductibles lors des transitions d’heure d’été (DST).
À cet égard, les fuseaux horaires sont comparables à l’Unicode dans Python. Au début c’est difficile. Vous obtenez des erreurs de codage et de décodage. Puis vous apprenez comment ça marche. Et certains problèmes disparaissent, vous n’obtenez plus jamais d’affichage corrompu lorsque votre application reçoit du contenu non ASCII.
Lorsque vous activez la prise en charge des fuseaux horaires, vous allez rencontrer certaines erreurs parce que vous utilisez des dates/heures naïves là où Django s’attend à des dates/heures conscientes. De telles erreurs apparaissent lors de l’exécution des tests et elles sont simples à corriger. Vous apprendrez rapidement comment éviter les opérations non valides.
D’un autre côté, les bogues qui proviennent d’une non prise en charge des fuseaux horaires sont beaucoup plus durs à prévenir, à diagnostiquer et à corriger. Tout ce qui touche aux tâches planifiées ou à l’arithmétique des dates/heures est sujet à de subtils bogues qui ne vous affecteront qu’une ou deux fois par année.
C’est pour ces raisons que la prise en charge des fuseaux horaires est activée par défaut dans les nouveaux projets, et vous devriez garder ce réglage pour autant que vous n’ayez pas une bonne raison de ne pas le faire.
J’ai activé la prise en charge des fuseaux horaires. Suis-je tranquille ?
Peut-être. Vous êtes mieux protégé des bogues liés à l’heure d’été, mais il est toujours possible que vous vous trompiez en convertissant sans précaution des objets datetime naïfs en objets datetime conscients et vice-versa.
Si votre application se connecte à d’autres systèmes, par exemple si elle interroge un service Web, prenez soin de bien définir les dates/heures. Pour les transmettre de manière fiable, leur représentation doit inclure le décalage UTC ou leur valeur doit être en UTC (ou les deux !).
Finalement, notre système de calendrier contient des pièges intéressants pour les ordinateurs :
>>> import datetime >>> def one_year_before(value): # DON'T DO THAT! ... return value.replace(year=value.year - 1) >>> one_year_before(datetime.datetime(2012, 3, 1, 10, 0)) datetime.datetime(2011, 3, 1, 10, 0) >>> one_year_before(datetime.datetime(2012, 2, 29, 10, 0)) Traceback (most recent call last): ... ValueError: day is out of range for month
(Pour implémenter cette fonction, vous devez décider si 2012-02-29 moins une année est 2011-02-28 ou 2011-03-01, ce qui dépend de vos exigences métier)
Dois-je installer pytz ?
Oui. La politique de Django est de ne pas exiger de dépendances externes, c’est pour cela que pytz est facultatif. Cependant, il est beaucoup plus sûr de l’installer.
Dès que vous activez la prise en charge des fuseaux horaires, Django a besoin d’une définition du fuseau horaire par défaut. Lorsque pytz est disponible, Django charge cette définition à partir de la base de données tz. C’est la solution la plus précise. Sinon, il calcule les conversions en se basant sur la différence entre le temps local et le temps UTC tel que rapporté par le système d’exploitation. C’est moins fiable, en particulier durant les périodes de transitions d’heure d’été.
De plus, si vous souhaitez gérer des utilisateurs dans plusieurs fuseaux horaires, pytz est la référence en ce qui concerne les définitions de fuseaux horaires.
Dépannage¶
Mon application plante avec TypeError: can't compare offset-naive and offset-aware datetimes , qu’est-ce que je fais faux ?
Reproduisons cette erreur en comparant des objets datetime naïf et conscient :
>>> import datetime >>> from django.utils import timezone >>> naive = datetime.datetime.utcnow() >>> aware = timezone.now() >>> naive == aware Traceback (most recent call last): ... TypeError: can't compare offset-naive and offset-aware datetimes
Si vous rencontrez cette erreur, il est très probable que votre code compare ces deux choses :
un objet datetime fourni par Django, par exemple une valeur lue à partir d’un champ de formulaire ou d’un champ de modèle. Comme vous avez activé la prise en charge des fuseaux horaires, cet objet est conscient.
un objet datetime généré dans votre code de manière naïve (sinon vous ne liriez pas ceci).
Généralement, la solution correcte est de modifier votre code pour qu’il utilise plutôt un objet datetime conscient.
Si vous écrivez une application réutilisable qui doit fonctionner indépendamment de la valeur de USE_TZ, il peut être utile d’appeler django.utils.timezone.now(). Cette fonction renvoie la date et l’heure actuelle sous forme d’objet datetime naïf lorsque USE_TZ = False et sous forme d’objet datetime conscient lorsque USE_TZ = True. Vous pouvez y ajouter ou soustraire une valeur datetime.timedelta selon vos besoins.
Je vois beaucoup de RuntimeWarning: DateTimeField received a naive datetime (YYYY-MM-DD HH:MM:SS) while time zone support is active , est-ce mauvais signe ?
Lorsque la prise en charge des fuseaux horaires est activée, la couche de base de données s’attend à ne recevoir que des objets datetime conscients de votre code. Cet avertissement se produit lorsqu’elle reçoit un objet datetime naïf. Cela indique que vous n’avez pas terminé de transformer votre code pour la prise en charge des fuseaux horaires. Veuillez vous référer au guide de migration pour des indications supplémentaires sur ce processus.
Dans l’intervalle et par rétrocompatibilité, Django considère l’objet datetime comme se trouvant dans le fuseau horaire par défaut, ce qui correspond généralement à la réalité.
now.date() est hier ! (ou demain)
Si vous avez toujours utilisé des objets datetime naïfs, vous pensez probablement pouvoir convertir un objet datetime en objet date en appelant sa méthode date(). Vous considérez également que date est très semblable à datetime, avec moins de précision.
Rien de cela n’est vrai dans un environnement conscient des fuseaux horaires :
>>> import datetime >>> import pytz >>> paris_tz = pytz.timezone("Europe/Paris") >>> new_york_tz = pytz.timezone("America/New_York") >>> paris = paris_tz.localize(datetime.datetime(2012, 3, 3, 1, 30)) # This is the correct way to convert between time zones with pytz. >>> new_york = new_york_tz.normalize(paris.astimezone(new_york_tz)) >>> paris == new_york, paris.date() == new_york.date() (True, False) >>> paris - new_york, paris.date() - new_york.date() (datetime.timedelta(0), datetime.timedelta(1)) >>> paris datetime.datetime(2012, 3, 3, 1, 30, tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>) >>> new_york datetime.datetime(2012, 3, 2, 19, 30, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
Comme le montre cet exemple, le même objet datetime peut représenter une date différente selon le fuseau horaire dans lequel il est représenté. Mais le problème réel est plus fondamental.
Un objet datetime représente un point dans le temps. C’est absolu et cela ne dépend de rien d’autre. Au contraire, une date est un concept calendaire. Il s’agit d’une période de temps dont les limites dépendent du fuseau horaire dans lequel la date est considérée. Comme vous pouvez le voir, ces deux concepts sont fondamentalement différents et la conversion d’un objet datetime en un objet date n’est pas une opération déterministe.
Qu’est-ce que cela signifie en pratique ?
Généralement, vous devriez éviter de convertir un objet datetime en date. Par exemple, vous pouvez utiliser le filtre de gabarit date pour n’afficher que la partie date d’un objet datetime. Ce filtre convertit l’objet datetime dans le fuseau horaire actuel avant de le mettre en forme, s’assurant ainsi que le résultat produit sera correct.
Si vous avez réellement besoin d’effectuer vous-même la conversion, vous devez d’abord prendre soin de convertir l’objet datetime dans le fuseau horaire approprié. Il s’agit généralement du fuseau horaire actuel :
>>> from django.utils import timezone >>> timezone.activate(pytz.timezone("Asia/Singapore")) # For this example, we just set the time zone to Singapore, but here's how # you would obtain the current time zone in the general case. >>> current_tz = timezone.get_current_timezone() # Again, this is the correct way to convert between time zones with pytz. >>> local = current_tz.normalize(paris.astimezone(current_tz)) >>> local datetime.datetime(2012, 3, 3, 8, 30, tzinfo=<DstTzInfo 'Asia/Singapore' SGT+8:00:00 STD>) >>> local.date() datetime.date(2012, 3, 3)
J’obtiens une erreur “Are time zone definitions for your database and pytz installed?” pytz est installée, je suppose donc que le problème vient de ma base de données ?
Si vous utilisez MySQL, consultez la section Définitions de fuseaux horaires des notes MySQL pour plus d’instructions sur le chargement des définitions de fuseaux horaires.
Utilisation¶
J’ai une chaîne "2012-02-21 10:28:45" et je sais qu’elle est dans le fuseau horaire ** ``”Europe/Helsinki”``. Comment puis-je la transformer en un objet ``datetime`` conscient ?
C’est exactement le rôle de pytz.
>>> from django.utils.dateparse import parse_datetime >>> naive = parse_datetime("2012-02-21 10:28:45") >>> import pytz >>> pytz.timezone("Europe/Helsinki").localize(naive, is_dst=None) datetime.datetime(2012, 2, 21, 10, 28, 45, tzinfo=<DstTzInfo 'Europe/Helsinki' EET+2:00:00 STD>)
Notez que localize est une extension de pytz à l’API tzinfo. Il peut être nécessaire d’intercepter les erreurs pytz.InvalidTimeError. La documentation de pytz contient davantage d’exemples. Il est recommandé de la consulter avant d’essayer de manipuler des objets datetime conscients.
Comment puis-je obtenir le temps local dans le fuseau horaire actuel ?
Et bien, la première question à se poser est : est-ce réellement nécessaire ?
Le temps local ne doit être utilisé que lorsque l’on interagit avec des humains, et la couche des gabarits fournit des filtres et des balises pour convertir des objets datetime dans le fuseau horaire de votre choix.
De plus, Python sait comparer des objets datetime conscients, en prenant en compte les décalages UTC si nécessaire. C’est beaucoup plus simple (et potentiellement plus rapide) d’écrire tout le code des modèles et des vues en UTC. Ainsi, dans la plupart des cas, l’objet datetime en UTC renvoyé par django.utils.timezone.now() sera suffisant.
Par souci d’exhaustivité, si vous devez vraiment obtenir le temps local dans le fuseau horaire actuel, voici comment vous pouvez l’obtenir :
>>> from django.utils import timezone >>> timezone.localtime(timezone.now()) datetime.datetime(2012, 3, 3, 20, 10, 53, 873365, tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)
Dans cet exemple, pytz est installé et le fuseau horaire actuel est "Europe/Paris".
Comment puis-je voir tous les fuseaux horaires disponibles ?
pytz fournit des utilitaires, y compris une liste des fuseaux horaires actuels et une liste de tous les fuseaux horaires disponibles, parmi lesquels se trouvent aussi certains qui n’ont qu’un intérêt historique.