Python Language
Date et l'heure
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).
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:
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:
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.