web-dev-qa-db-fra.com

Générer un horodatage RFC 3339 en Python

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 tztz 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 ...)

47
Yarin

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.

7
ruakh

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'

36
monkut

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.

22
jfs

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.

5
MenschMarcus

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
1
Eli_B

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
0
gene_wood

Je viens de commencer à travailler avec un autre utilitaire utile: dateutil library pour la gestion du fuseau horaire et l’analyse de la date. Recommandé autour de SO, y compris cette answer

0
Yarin