J'essaie de générer un horodatage RFC 3339 UTC en Python. Jusqu'à présent, j'ai été capable de faire ce qui suit:
>>> d = datetime.datetime.now()
>>> print d.isoformat('T')
2011-12-18T20:46:00.392227
Mon problème est de régler le décalage UTC.
Selon docs , la méthode de classe datetime.now([tz])
prend un argument optionnel tz
où tz must be an instance of a class tzinfo subclass
et datetime.tzinfo
est an abstract base class for time zone information objects.
C’est là que je me perds. Comment tzinfo est-il une classe abstraite et comment suis-je censé l’appliquer?
(NOTE: Dans PHP c'est aussi simple que timestamp = date(DATE_RFC3339);
, c'est pourquoi je ne comprends pas pourquoi l'approche de Python est si compliquée ...)
Plus bas dans le même document que vous avez lié, il explique comment le mettre en œuvre, en donnant quelques exemples, notamment le code complet d'une classe UTC
(représentant UTC), une classe FixedOffset
(représentant un fuseau horaire avec un décalage fixe UTC, par opposition à un fuseau horaire avec heure d’été et tout le reste) et quelques autres.
Les fuseaux horaires sont pénibles, ce qui explique probablement pourquoi ils ont choisi de ne pas les inclure dans la bibliothèque datetime.
essayez pytz, il a le tzinfo que vous cherchez: http://pytz.sourceforge.net/
Vous devez d'abord créer l'objet datetime
, puis appliquer le fuseau horaire comme ci-dessous, puis votre sortie .isoformat()
inclura le décalage UTC comme vous le souhaitez:
d = datetime.datetime.utcnow()
d_with_timezone = d.replace(tzinfo=pytz.UTC)
d_with_timezone.isoformat()
'2017-04-13T14: 34: 23.111142 + 00: 00'
Ou bien, utilisez simplement UTC et jetez un "Z" (pour le fuseau horaire Zulu) à la fin pour marquer le "fuseau horaire" comme étant UTC.
d = datetime.datetime.utcnow() # <-- get time in UTC
print d.isoformat("T") + "Z"
'2017-04-13T14: 34: 23.111142Z'
En Python 3.3+:
>>> from datetime import datetime, timezone
>>> local_time = datetime.now(timezone.utc).astimezone()
>>> local_time.isoformat()
'2015-01-16T16:52:58.547366+01:00'
Sur les anciennes versions de Python, si tout ce dont vous avez besoin est d’un objet datetime averti représentant l’heure actuelle en UTC, vous pouvez définir une simple sous-classe tzinfo comme indiqué dans la documentation pour représenter le fuseau horaire UTC :
from datetime import datetime
utc_now = datetime.now(utc)
print(utc_now.isoformat('T'))
# -> 2015-05-19T20:32:12.610841+00:00
Vous pouvez également utiliser tzlocal
module pour obtenir le fuseau horaire pytz
représentant votre fuseau horaire local:
#!/usr/bin/env python
from datetime import datetime
from tzlocal import get_localzone # $ pip install tzlocal
now = datetime.now(get_localzone())
print(now.isoformat('T'))
Cela fonctionne à la fois sur Python 2 et 3.
J'ai beaucoup lutté avec le format datetime RFC3339, mais j'ai trouvé une solution appropriée pour convertir date_string <=> datetime_object dans les deux sens.
Vous avez besoin de deux modules externes différents, car l'un d'entre eux n'est capable de faire la conversion que dans un seul sens (malheureusement):
première installation:
Sudo pip install rfc3339
Sudo pip install iso8601
puis inclure:
import datetime # for general datetime object handling
import rfc3339 # for date object -> date string
import iso8601 # for date string -> date object
Pour ne pas avoir besoin de savoir quel module correspond à quelle direction, j’ai écrit deux fonctions d’aide simples:
def get_date_object(date_string):
return iso8601.parse_date(date_string)
def get_date_string(date_object):
return rfc3339.rfc3339(date_object)
que dans votre code, vous pouvez facilement utiliser comme ceci:
input_string = '1989-01-01T00:18:07-05:00'
test_date = get_date_object(input_string)
# >>> datetime.datetime(1989, 1, 1, 0, 18, 7, tzinfo=<FixedOffset '-05:00' datetime.timedelta(-1, 68400)>)
test_string = get_date_string(test_date)
# >>> '1989-01-01T00:18:07-05:00'
test_string is input_string # >>> True
Heureka! Maintenant, vous pouvez facilement ( haha ) utiliser vos chaînes de date et vos chaînes de date dans un format utilisable.
Le paquet pytz est disponible pour Python 2.X et 3.X. Il implémente des sous-classes concrètes de tzinfo
, parmi d'autres services, pour que vous n'ayez pas à le faire.
Pour ajouter un décalage UTC: importer datetime importer pytz
dt = datetime.datetime(2011, 12, 18, 20, 46, 00, 392227)
utc_dt = pytz.UTC.localize(dt)
Et maintenant ceci:
print utc_dt.isoformat()
serait imprimer:
2011-12-18T20:46:00.392227+00:00
Vous pouvez en effet utiliser le module intégré - in datetime . Comme @ruakhmentionne , la page contient des exemples qui montrent comment. Si vous regardez dans la section sur tzinfo vous verrez Voyez un long exemple montrant de nombreux cas d'utilisation différents. Voici le code de celui que vous recherchez, qui consiste à générer un horodatage RFC 3339 UTC.
from datetime import tzinfo, timedelta, datetime
import time as _time
ZERO = timedelta(0)
STDOFFSET = timedelta(seconds=-_time.timezone)
if _time.daylight:
DSTOFFSET = timedelta(seconds=-_time.altzone)
else:
DSTOFFSET = STDOFFSET
DSTDIFF = DSTOFFSET - STDOFFSET
class LocalTimezone(tzinfo):
def utcoffset(self, dt):
if self._isdst(dt):
return DSTOFFSET
else:
return STDOFFSET
def dst(self, dt):
if self._isdst(dt):
return DSTDIFF
else:
return ZERO
def tzname(self, dt):
return _time.tzname[self._isdst(dt)]
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, 0)
stamp = _time.mktime(tt)
tt = _time.localtime(stamp)
return tt.tm_isdst > 0
Local = LocalTimezone()
d = datetime.now(Local)
print d.isoformat('T')
# which returns
# 2014-04-28T15:44:45.758506-07:00