web-dev-qa-db-fra.com

Heure ISO (ISO 8601) en Python

J'ai un fichier. En Python, j'aimerais prendre son heure de création et la convertir en chaîne heure ISO (ISO 8601) tout en préservant le fait qu'elle a été créée dans le fuseau horaire de l'Est (ET) .

Comment utiliser le fichier ctime et le convertir en une chaîne de temps ISO indiquant le fuseau horaire de l'Est (et prenant en compte l'heure d'été, si nécessaire)?

240
Joseph Turian

Local selon ISO 8601:

import datetime
datetime.datetime.now().isoformat()

UTC à ISO 8601:

import datetime
datetime.datetime.utcnow().isoformat()

Local selon ISO 8601 sans microseconde:

import datetime
datetime.datetime.now().replace(microsecond=0).isoformat()

UTC à ISO 8601 avec information de fuseau horaire (Python 3):

import datetime
datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).isoformat()

Local selon ISO 8601 avec les informations de fuseau horaire (Python 3):

import datetime, time

# Calculate the offset taking into account daylight saving time
utc_offset_sec = time.altzone if time.localtime().tm_isdst else time.timezone
utc_offset = datetime.timedelta(seconds=-utc_offset_sec)
datetime.datetime.now().replace(tzinfo=datetime.timezone(offset=utc_offset)).isoformat()

Pour Python 2, voyez et utilisez pytz .

367
estani

Voici ce que j'utilise pour convertir au format datetime XSD:

from datetime import datetime
datetime.now().replace(microsecond=0).isoformat()
# You get your ISO string

Je suis tombé sur cette question lors de la recherche du format de date/heure XSD (xs:dateTime). J'avais besoin de supprimer les microsecondes de isoformat.

51
radtek

J'ai trouvé le datetime.isoformat dans la documentation . Il semble faire ce que tu veux:

datetime.isoformat([sep])

Return a string representing the date and time in ISO 8601 format, YYYY-MM-DDTHH:MM:SS.mmmmmm or, if microsecond is 0, YYYY-MM-DDTHH:MM:SS

If utcoffset() does not return None, a 6-character string is appended, giving the UTC offset in (signed) hours and minutes: YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or, if microsecond is 0 YYYY-MM-DDTHH:MM:SS+HH:MM

The optional argument sep (default 'T') is a one-character separator, placed between the date and time portions of the result. For example,
>>>

>>> from datetime import tzinfo, timedelta, datetime
>>> class TZ(tzinfo):
...     def utcoffset(self, dt): return timedelta(minutes=-399)
...
>>> datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ')
'2002-12-25 00:00:00-06:39'
48
user2120810

Représentation temporelle ISO 8601

La norme internationale ISO 8601 décrit une représentation sous forme de chaîne pour les dates et les heures. Deux exemples simples de ce format sont

2010-12-16 17:22:15
20101216T172215

(qui signifient tous deux le 16 décembre 2010), mais le format permet également des temps de résolution inférieurs à la seconde et de spécifier des fuseaux horaires. Ce format n’est bien sûr pas spécifique à Python, mais il est bon pour stocker les dates et heures dans un format portable. Vous trouverez des détails sur ce format dans entrée de Markus Kuhn .

Je recommande l'utilisation de ce format pour stocker les temps dans des fichiers.

Une façon d'obtenir l'heure actuelle dans cette représentation consiste à utiliser strftime à partir du module time de la bibliothèque standard Python:

>>> from time import strftime
>>> strftime("%Y-%m-%d %H:%M:%S")
'2010-03-03 21:16:45'

Vous pouvez utiliser le constructeur strptime de la classe datetime:

>>> from datetime import datetime
>>> datetime.strptime("2010-06-04 21:08:12", "%Y-%m-%d %H:%M:%S")
datetime.datetime(2010, 6, 4, 21, 8, 12)

Le plus robuste est le module Egenix mxDateTime:

>>> from mx.DateTime.ISO import ParseDateTimeUTC
>>> from datetime import datetime
>>> x = ParseDateTimeUTC("2010-06-04 21:08:12")
>>> datetime.fromtimestamp(x)
datetime.datetime(2010, 3, 6, 21, 8, 12)

Références

47
Voislav Sauca

Le format horaire ISO 8601 ne stocke pas de nom de fuseau horaire, seul le décalage UTC correspondant est conservé.

Pour convertir un fichier ctime en une chaîne temporelle ISO 8601 tout en préservant le décalage UTC dans Python 3:

>>> import os
>>> from datetime import datetime, timezone
>>> ts = os.path.getctime(some_file)
>>> dt = datetime.fromtimestamp(ts, timezone.utc)
>>> dt.astimezone().isoformat()
'2015-11-27T00:29:06.839600-05:00'

Le code suppose que votre fuseau horaire local est fuseau horaire de l'Est (ET) et que votre système fournit un décalage UTC correct pour l'horodatage POSIX donné (ts), c'est-à-dire Python a accès à une base de données de fuseaux horaires historiques sur votre système ou le fuseau horaire contenait les mêmes règles à une date donnée.

Si vous avez besoin d'une solution portable. tilisez le module pytz) qui donne accès à la base de données tz :

>>> import os
>>> from datetime import datetime
>>> import pytz  # pip install pytz
>>> ts = os.path.getctime(some_file)
>>> dt = datetime.fromtimestamp(ts, pytz.timezone('America/New_York'))
>>> dt.isoformat()
'2015-11-27T00:29:06.839600-05:00'

Le résultat est le même dans ce cas.

Si vous avez besoin du nom/de l'abréviation/de l'identifiant de la zone horaire, enregistrez-le séparément.

>>> dt.astimezone().strftime('%Y-%m-%d %H:%M:%S%z (%Z)')
'2015-11-27 00:29:06-0500 (EST)'

Remarque: non, : dans le décalage UTC et EST l'abréviation du fuseau horaire ne font pas partie du format d'heure ISO 8601. Ce n'est pas unique.

Différentes bibliothèques/différentes versions de la même bibliothèque peuvent utiliser différentes règles de fuseau horaire pour la même date/fuseau horaire. S'il s'agit d'une date future, les règles pourraient être inconnues pour le moment. En d’autres termes, la même heure UTC peut correspondre à une heure locale différente selon les règles que vous utilisez - enregistrer une heure au format ISO 8601 préserve l’heure UTC et l’heure locale qui correspond à règles de fuseau horaire en vigueur en vigueur sur votre plate-forme. Vous devrez peut-être recalculer l'heure locale sur une plate-forme différente si celle-ci a des règles différentes.

17
jfs

Vous devez utiliser os.stat pour obtenir l'heure de création du fichier et une combinaison de time.strftime et de time.timezone pour la mise en forme:

>>> import time
>>> import os
>>> t = os.stat('C:/Path/To/File.txt').st_ctime
>>> t = time.localtime(t)
>>> formatted = time.strftime('%Y-%m-%d %H:%M:%S', t)
>>> tz = str.format('{0:+06.2f}', float(time.timezone) / 3600)
>>> final = formatted + tz
>>> 
>>> final
'2008-11-24 14:46:08-02.00'
14
Max Shawabkeh

ISO 8601 autorise une représentation compacte sans séparateur, à l'exception du T, aussi j'aime bien utiliser cette ligne unique pour obtenir une chaîne d'horodatage rapide:

>>> datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%S.%fZ")
'20180905T140903.591680Z'

Si vous n'avez pas besoin des microsecondes, laissez simplement de côté la partie .%f:

>>> datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")
'20180905T140903Z'

Pour l'heure locale:

>>> datetime.datetime.now().strftime("%Y%m%dT%H%M%S")
'20180905T140903'
12
Jim Hunziker

Corrigez-moi si je me trompe (mais ce n'est pas le cas), mais le décalage par rapport à l'heure UTC change en fonction de l'heure d'été. Donc vous devriez utiliser

tz = str.format('{0:+06.2f}', float(time.altzone) / 3600)

Je crois aussi que le signe devrait être différent:

tz = str.format('{0:+06.2f}', -float(time.altzone) / 3600)

Je peux me tromper, mais je ne le pense pas.

4

Je suis d'accord avec Jarek et je note en outre que le caractère séparateur ISO est un signe deux-points. Je pense donc que la réponse finale devrait être:

isodate.datetime_isoformat(datetime.datetime.now()) + str.format('{0:+06.2f}', -float(time.timezone) / 3600).replace('.', ':')
2
mattbornski

J'ai développé cette fonction:

def iso_8601_format(dt):
    """YYYY-MM-DDThh:mm:ssTZD (1997-07-16T19:20:30-03:00)"""

    if dt is None:
        return ""

    fmt_datetime = dt.strftime('%Y-%m-%dT%H:%M:%S')
    tz = dt.utcoffset()
    if tz is None:
        fmt_timezone = "+00:00"
    else:
        fmt_timezone = str.format('{0:+06.2f}', float(tz.total_seconds() / 3600))

    return fmt_datetime + fmt_timezone
0
Andre Avilla