Recherche…


Remarques

Python fournit à la fois des méthodes intégrées et des bibliothèques externes pour créer, modifier, analyser et manipuler les dates et les heures.

Analyse d'une chaîne en objet datetime sensible au fuseau horaire

Python 3.2+ prend en charge le format %z lors du traitement d'une chaîne dans un objet datetime .

Offset UTC sous la forme +HHMM ou -HHMM (chaîne vide si l'objet est naïf).

Python 3.x 3.2
import datetime
dt = datetime.datetime.strptime("2016-04-15T08:27:18-0500", "%Y-%m-%dT%H:%M:%S%z")

Pour les autres versions de Python, vous pouvez utiliser une bibliothèque externe telle que dateutil , ce qui dateutil analyse syntaxique d'une chaîne avec un fuseau horaire dans un objet datetime .

import dateutil.parser
dt = dateutil.parser.parse("2016-04-15T08:27:18-0500")

La variable dt est maintenant un objet datetime avec la valeur suivante:

datetime.datetime(2016, 4, 15, 8, 27, 18, tzinfo=tzoffset(None, -18000))

Arithmétique de date simple

Les dates n'existent pas isolément. Il est fréquent que vous deviez trouver la durée entre les dates ou déterminer quelle sera la date de demain. Cela peut être accompli en utilisant des objets timedelta

import datetime

today = datetime.date.today()
print('Today:', today)

yesterday = today - datetime.timedelta(days=1)
print('Yesterday:', yesterday)

tomorrow = today + datetime.timedelta(days=1)
print('Tomorrow:', tomorrow)

print('Time between tomorrow and yesterday:', tomorrow - yesterday)

Cela produira des résultats similaires à:

Today: 2016-04-15
Yesterday: 2016-04-14
Tomorrow: 2016-04-16
Difference between tomorrow and yesterday: 2 days, 0:00:00

Utilisation d'objets de base datetime

Le module datetime contient trois principaux types d'objets - date, heure et date-heure.

import datetime

# Date object
today = datetime.date.today()
new_year = datetime.date(2017, 01, 01) #datetime.date(2017, 1, 1)

# Time object
noon = datetime.time(12, 0, 0) #datetime.time(12, 0)

# Current datetime
now = datetime.datetime.now()

# Datetime object
millenium_turn = datetime.datetime(2000, 1, 1, 0, 0, 0) #datetime.datetime(2000, 1, 1, 0, 0)

Les opérations arithmétiques pour ces objets sont uniquement prises en charge dans le même type de données et l'exécution d'une arithmétique simple avec des instances de types différents entraînera une erreur TypeError.

# subtraction of noon from today
noon-today
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'datetime.time' and 'datetime.date'
However, it is straightforward to convert between types.

# Do this instead
print('Time since the millenium at midnight: ',
      datetime.datetime(today.year, today.month, today.day) - millenium_turn)

# Or this
print('Time since the millenium at noon: ',
      datetime.datetime.combine(today, noon) - millenium_turn)

Itérer sur les dates

Parfois, vous souhaitez effectuer une itération sur une plage de dates allant d'une date de début à une date de fin. Vous pouvez le faire en utilisant la bibliothèque datetime et l’objet timedelta :

import datetime

# The size of each step in days
day_delta = datetime.timedelta(days=1)

start_date = datetime.date.today()
end_date = start_date + 7*day_delta

for i in range((end_date - start_date).days):
    print(start_date + i*day_delta)

Qui produit:

2016-07-21
2016-07-22
2016-07-23
2016-07-24
2016-07-25
2016-07-26
2016-07-27

Analyse d'une chaîne avec un nom de fuseau horaire court en un objet datetime sensible au fuseau horaire

En utilisant la bibliothèque dateutil comme dans l' exemple précédent sur l'analyse des horodatages sensibles au fuseau horaire , il est également possible d'analyser les horodatages avec un nom de fuseau horaire spécifié "court".

Pour les dates formatées avec des noms de fuseau horaire courte ou des abréviations, qui sont généralement ambigus (par exemple CST, qui pourrait être Central Standard Time, Heure normale de Chine, Cuba heure normale, etc - plus peuvent être trouvés ici ) ou pas nécessairement disponibles dans une base de données standard , il est nécessaire de spécifier un mappage entre l’abréviation du fuseau horaire et l’objet tzinfo .

from dateutil import tz
from dateutil.parser import parse

ET = tz.gettz('US/Eastern')
CT = tz.gettz('US/Central')
MT = tz.gettz('US/Mountain')
PT = tz.gettz('US/Pacific')

us_tzinfos = {'CST': CT, 'CDT': CT,
              'EST': ET, 'EDT': ET,
              'MST': MT, 'MDT': MT,
              'PST': PT, 'PDT': PT}

dt_est = parse('2014-01-02 04:00:00 EST', tzinfos=us_tzinfos)
dt_pst = parse('2016-03-11 16:00:00 PST', tzinfos=us_tzinfos)

Après avoir exécuté ceci:

dt_est
# datetime.datetime(2014, 1, 2, 4, 0, tzinfo=tzfile('/usr/share/zoneinfo/US/Eastern'))
dt_pst
# datetime.datetime(2016, 3, 11, 16, 0, tzinfo=tzfile('/usr/share/zoneinfo/US/Pacific'))

Il est à noter que si vous utilisez un pytz horaire pytz avec cette méthode, celle-ci ne sera pas correctement localisée:

from dateutil.parser import parse
import pytz

EST = pytz.timezone('America/New_York')
dt = parse('2014-02-03 09:17:00 EST', tzinfos={'EST': EST})

Cela attache simplement le pytz horaire de pytz à la date et heure:

dt.tzinfo # Will be in Local Mean Time!
# <DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>

Si vous utilisez cette méthode, vous devriez probablement re localize la partie naïve du datetime après l' analyse syntaxique:

dt_fixed = dt.tzinfo.localize(dt.replace(tzinfo=None))
dt_fixed.tzinfo # Now it's EST.
# <DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)

Construire des datetimes dans le fuseau horaire

Par défaut, tous les objets datetime sont naïfs. Pour les rendre compatibles avec le fuseau horaire, vous devez joindre un objet tzinfo , qui fournit le décalage UTC et l'abréviation du fuseau horaire en fonction de la date et de l'heure.

Zones de décalage fixe

Pour les fuseaux horaires à décalage fixe par rapport à UTC, dans Python 3.2+, le module datetime fournit la classe timezone , une implémentation concrète de tzinfo , qui prend un timedelta et un paramètre (facultatif) name:

Python 3.x 3.2
from datetime import datetime, timedelta, timezone
JST = timezone(timedelta(hours=+9))

dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00

print(dt.tzname())
# UTC+09:00

dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=timezone(timedelta(hours=9), 'JST'))
print(dt.tzname)
# 'JST'

Pour les versions Python antérieures à 3.2, il est nécessaire d'utiliser une bibliothèque tierce, telle que dateutil . dateutil fournit une classe équivalente, tzoffset , qui (à partir de la version 2.5.3) prend les arguments de la forme dateutil.tz.tzoffset(tzname, offset) , où le offset est spécifié en secondes:

Python 3.x 3.2
Python 2.x 2.7
from datetime import datetime, timedelta
from dateutil import tz

JST = tz.tzoffset('JST', 9 * 3600) # 3600 seconds per hour
dt = datetime(2015, 1, 1, 12, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00
print(dt.tzname)
# 'JST'

Zones avec heure avancée

Pour les zones avec heure avancée, les bibliothèques standard python ne fournissent pas de classe standard, il est donc nécessaire d'utiliser une bibliothèque tierce. pytz et dateutil sont des bibliothèques populaires fournissant des classes de fuseau horaire.

En plus des fuseaux horaires statiques, dateutil fournit des classes de fuseau horaire qui utilisent l'heure d'été (voir la documentation du module tz ). Vous pouvez utiliser la méthode tz.gettz() pour obtenir un objet de fuseau horaire, qui peut ensuite être transmis directement au constructeur datetime :

from datetime import datetime
from dateutil import tz
local = tz.gettz() # Local time
PT = tz.gettz('US/Pacific') # Pacific time

dt_l = datetime(2015, 1, 1, 12, tzinfo=local) # I am in EST
dt_pst = datetime(2015, 1, 1, 12, tzinfo=PT)
dt_pdt = datetime(2015, 7, 1, 12, tzinfo=PT) # DST is handled automatically
print(dt_l)
# 2015-01-01 12:00:00-05:00
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-07-01 12:00:00-07:00

ATTENTION : à partir de la version 2.5.3, dateutil ne gère pas correctement les dateutil ambiguës et utilisera toujours la date ultérieure par défaut. Il n'y a aucun moyen de construire un objet avec un dateutil fuseau horaire représentant, par exemple 2015-11-01 1:30 EDT-4 , puisque c'est au cours d' une transition heure d'été.

Tous les cas de bord sont traités correctement lors de l'utilisation de pytz , mais les pytz horaires pytz ne doivent pas être directement liés aux fuseaux horaires via le constructeur. Au lieu de cela, un pytz horaire pytz doit être attaché en utilisant la méthode de localize du fuseau horaire:

from datetime import datetime, timedelta
import pytz

PT = pytz.timezone('US/Pacific')
dt_pst = PT.localize(datetime(2015, 1, 1, 12))
dt_pdt = PT.localize(datetime(2015, 11, 1, 0, 30))
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-11-01 00:30:00-07:00

Sachez que si vous effectuez une arithmétique datetime sur un pytz horaire pytz pytz, vous devez soit effectuer les calculs en UTC (si vous voulez un temps écoulé absolu), soit appeler normalize() sur le résultat:

dt_new = dt_pdt + timedelta(hours=3) # This should be 2:30 AM PST
print(dt_new)
# 2015-11-01 03:30:00-07:00
dt_corrected = PT.normalize(dt_new)
print(dt_corrected)
# 2015-11-01 02:30:00-08:00

Analyse floue de datetime (extraction de datetime d'un texte)

Il est possible d'extraire une date d'un texte à l' aide du dateutil analyseur en mode « flou », où les composants de la chaîne non reconnu comme faisant partie d'une date sont ignorées.

from dateutil.parser import parse

dt = parse("Today is January 1, 2047 at 8:21:00AM", fuzzy=True)
print(dt)

dt est maintenant un objet datetime et vous datetime.datetime(2047, 1, 1, 8, 21) imprimé.

Changer de fuseau horaire

Pour basculer entre les fuseaux horaires, vous avez besoin d'objets datetime qui prennent en compte le fuseau horaire.

from datetime import datetime
from dateutil import tz

utc = tz.tzutc()
local = tz.tzlocal()

utc_now = datetime.utcnow()
utc_now # Not timezone-aware.

utc_now = utc_now.replace(tzinfo=utc)
utc_now # Timezone-aware.

local_now = utc_now.astimezone(local)
local_now # Converted to local time.

Analyse d'un horodatage ISO 8601 arbitraire avec des bibliothèques minimales

Python ne prend en charge que l'analyse des horodatages ISO 8601. Pour le strptime vous devez savoir exactement dans quel format il se trouve. Comme complication, la cordification d'un datetime est un horodatage ISO 8601, avec un espace comme séparateur et fraction de 6 chiffres:

str(datetime.datetime(2016, 7, 22, 9, 25, 59, 555555))
# '2016-07-22 09:25:59.555555'

mais si la fraction est 0, aucune partie fractionnaire n'est sortie

str(datetime.datetime(2016, 7, 22, 9, 25, 59, 0))
# '2016-07-22 09:25:59'

Mais ces deux formes nécessitent un format différent pour le strptime . De plus, strptime' does not support at all parsing minute timezones that have a : in it, thus 2016-07-22 09: 25: 59 + 0300 can be parsed, but the standard format 2016-07-22 09:25:59 +03: 00` ne peut pas.

Il existe une bibliothèque de fichiers iso8601 appelée iso8601 qui analyse correctement les horodatages ISO 8601 et uniquement ceux-ci.

Il supporte les fractions et les fuseaux horaires, et le séparateur T avec une seule fonction:

import iso8601
iso8601.parse_date('2016-07-22 09:25:59')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22 09:25:59+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<FixedOffset '+03:00' ...>)
iso8601.parse_date('2016-07-22 09:25:59Z')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22T09:25:59.000111+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, 111, tzinfo=<FixedOffset '+03:00' ...>)

Si aucun fuseau horaire n'est défini, iso8601.parse_date est défini iso8601.parse_date défaut sur UTC. La zone par défaut peut être modifiée avec l'argument mot-clé default_zone . Notamment, s'il s'agit de None au lieu de la valeur par défaut, les horodatages qui n'ont pas de fuseau horaire explicite sont renvoyés en tant que dat date naïves à la place:

iso8601.parse_date('2016-07-22T09:25:59', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59)
iso8601.parse_date('2016-07-22T09:25:59Z', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)

Conversion de l'horodatage en datetime

Le module datetime peut convertir un timestamp POSIX en objet datetime ITC.

L'époque est le 1er janvier 1970 à minuit.

import time
from datetime import datetime
seconds_since_epoch=time.time()  #1469182681.709

utc_date=datetime.utcfromtimestamp(seconds_since_epoch) #datetime.datetime(2016, 7, 22, 10, 18, 1, 709000)

Soustraire les mois d'une date avec précision

Utiliser le module calendar

import calendar
from datetime import date

def monthdelta(date, delta):
    m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12
    if not m: m = 12
    d = min(date.day, calendar.monthrange(y, m)[1])
    return date.replace(day=d,month=m, year=y)

next_month = monthdelta(date.today(), 1) #datetime.date(2016, 10, 23)

Utilisation du module dateutils

import datetime
import dateutil.relativedelta

d = datetime.datetime.strptime("2013-03-31", "%Y-%m-%d")
d2 = d - dateutil.relativedelta.relativedelta(months=1)  #datetime.datetime(2013, 2, 28, 0, 0)

Différences de temps de calcul

timedelta module timedelta est pratique pour calculer les différences entre les temps:

from datetime import datetime, timedelta
now = datetime.now()
then = datetime(2016, 5, 23)     # datetime.datetime(2016, 05, 23, 0, 0, 0)

La spécification de l'heure est facultative lors de la création d'un nouvel objet datetime

delta = now-then

delta est de type timedelta

print(delta.days)
# 60
print(delta.seconds)
# 40826

Pour obtenir un n et un jour d'avance, nous pouvons utiliser:

n jour après jour:

def get_n_days_after_date(date_format="%d %B %Y", add_days=120):

    date_n_days_after = datetime.datetime.now() + timedelta(days=add_days)
    return date_n_days_after.strftime(date_format)

n jour avant la date:

 def get_n_days_before_date(self, date_format="%d %B %Y", days_before=120):

        date_n_days_ago = datetime.datetime.now() - timedelta(days=days_before)
        return date_n_days_ago.strftime(date_format)

Obtenir un horodatage ISO 8601

Sans fuseau horaire, avec microsecondes

from datetime import datetime

datetime.now().isoformat()
# Out: '2016-07-31T23:08:20.886783'

Avec fuseau horaire, avec microsecondes

from datetime import datetime
from dateutil.tz import tzlocal

datetime.now(tzlocal()).isoformat()
# Out: '2016-07-31T23:09:43.535074-07:00'

Avec fuseau horaire, sans microsecondes

from datetime import datetime
from dateutil.tz import tzlocal

datetime.now(tzlocal()).replace(microsecond=0).isoformat()
# Out: '2016-07-31T23:10:30-07:00'

Voir ISO 8601 pour plus d'informations sur le format ISO 8601.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow