En Python, comment convertir un objet `datetime` en secondes?

226

Toutes mes excuses pour la simple question ... Je suis nouveau sur Python ... J'ai cherché autour et rien ne semble fonctionner.

J'ai un tas d'objets datetime et je veux calculer le nombre de secondes depuis un temps fixe dans le passé pour chacun (par exemple depuis le 1er janvier 1970).

import datetime
t = datetime.datetime(2009, 10, 21, 0, 0)

Cela semble ne faire que différencier les dates qui ont des jours différents:

t.toordinal()

Toute aide est très appréciée.

Nathan Lippi
la source
2
Je convertirais probablement les deux en S depuis l'époque et j'irais de là: int(t.timestamp())
nerdwaller
pour l'opération inverse, allez ici: convertir-secondes-depuis-époque-en-un-objet-
Trevor Boyd Smith

Réponses:

233

Pour la date spéciale du 1er janvier 1970, il existe plusieurs options.

Pour toute autre date de début, vous devez obtenir la différence entre les deux dates en quelques secondes. La soustraction de deux dates donne un timedeltaobjet qui, à partir de Python 2.7, a une total_seconds()fonction.

>>> (t-datetime.datetime(1970,1,1)).total_seconds()
1256083200.0

La date de début est généralement spécifiée en UTC, donc pour des résultats corrects, datetimevous introduisez cette formule en UTC également. Si votre datetimen'est pas déjà en UTC, vous devrez le convertir avant de l'utiliser, ou attacher une tzinfoclasse qui a le bon décalage.

Comme indiqué dans les commentaires, si vous en avez un tzinfoattaché, datetimevous en aurez également besoin à la date de début ou la soustraction échouera; pour l'exemple ci-dessus, j'ajouterais tzinfo=pytz.utcsi vous utilisez Python 2 ou tzinfo=timezone.utcsi vous utilisez Python 3.

Mark Ransom
la source
1
Python m'avertit maintenant: "TypeError: impossible de soustraire des heures de temps décalées et naïves" Quelle est la meilleure solution pour résoudre ce problème?
Aaron Ash
2
@Charybdis, essayez datetime.datetime(1970,1,1,tzinfo=pytz.utc).
Mark Ransom
9
Pensez à utiliser: datetime.datetime.utcfromtimestamp(0) j'ai utilisé cela pour obtenir facilement «l'époque». Notez que l'époque n'est pas toujours la même sur tous les systèmes.
DA
3
Soyez très prudent avec les fuseaux horaires ici. Je suis à UTC + 2, ce qui signifie que la sortie de time.time()et datetime.now() - datetime(1970, 1, 1)diffère de 7200 secondes. Utilisez plutôt (t - datetime.datetime.fromtimestamp(0)).total_seconds(). Ne pas utiliser utcfromtimestamp(0)si vous souhaitez convertir un datetime dans votre fuseau horaire local.
Carl
2
@DA: Python ne prend pas en charge les époques non POSIX . Tous les systèmes sur lesquels python fonctionne utilisent la même époque: 1970-01-01 00:00:00 UTC
jfs
130

Pour obtenir l'heure Unix (secondes depuis le 1er janvier 1970):

>>> import datetime, time
>>> t = datetime.datetime(2011, 10, 21, 0, 0)
>>> time.mktime(t.timetuple())
1319148000.0
Mark Byers
la source
22
soyez prudent lorsque vous utilisez time.mktime car il exprime l'heure locale et dépend de la plate-forme
Shih-Wen Su
7
Soyez prudent en effet. Ça m'a mordu le cul à fond
Arg
il suppose qu'il ts'agit d'une heure locale. Le décalage UTC pour le fuseau horaire local peut avoir été différent dans le passé et si mktime()(bibliothèque C) n'a pas accès aux données de fuseau horaire historiques sur une plate-forme donnée, il peut échouer ( pytzest un moyen portable d'accéder à la base de données tz). En outre, l'heure locale peut être ambiguë, par exemple, pendant les transitions DST - vous avez besoin d'informations supplémentaires pour
lever l'ambiguïté
1
Soyez prudent lorsque vous l'utilisez avec des temps qui ont des fractions de seconde. time.mktime(datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timetuple())se traduit par une 1564819506.0baisse silencieuse des millisecondes, mais datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timestamp()(réponse d'Andrzej Pronobis) entraîne 1564819506.912le résultat attendu.
Alex
128

À partir de Python 3.3, cela devient super facile avec la datetime.timestamp()méthode. Bien sûr, cela ne sera utile que si vous avez besoin du nombre de secondes à partir du 1970-01-01 UTC.

from datetime import datetime
dt = datetime.today()  # Get timezone naive now
seconds = dt.timestamp()

La valeur de retour sera un flottant représentant même des fractions de seconde. Si le datetime est naïf de fuseau horaire (comme dans l'exemple ci-dessus), il sera supposé que l'objet datetime représente l'heure locale, c'est-à-dire que ce sera le nombre de secondes de l'heure actuelle à votre emplacement jusqu'au 1970-01-01 UTC.

Andrzej Pronobis
la source
3
Qui a voté contre, pourriez-vous expliquer pourquoi?
Andrzej Pronobis
5
Je suppose que le downvote est dû à la balise python-2.7 sur la question (c'est juste une supposition).
jfs
3
Il doit s'agir de la réponse acceptée / la réponse acceptée doit être mise à jour en conséquence.
DreamFlasher
11
Il est temps de mettre à niveau je suppose;)
DreamFlasher
est-il possible de calculer cette distance à partir d'une autre date de départ? (je veux changer la date du 01/01/1970)
pellerossa pelles
29

Peut-être hors sujet: pour obtenir l'heure UNIX / POSIX à partir de datetime et la reconvertir:

>>> import datetime, time
>>> dt = datetime.datetime(2011, 10, 21, 0, 0)
>>> s = time.mktime(dt.timetuple())
>>> s
1319148000.0

# and back
>>> datetime.datetime.fromtimestamp(s)
datetime.datetime(2011, 10, 21, 0, 0)

Notez que différents fuseaux horaires ont un impact sur les résultats, par exemple mes retours TZ / DST actuels:

>>>  time.mktime(datetime.datetime(1970, 1, 1, 0, 0).timetuple())
-3600 # -1h

par conséquent, il convient d'envisager la normalisation UTC en utilisant des versions UTC des fonctions.

Notez que le résultat précédent peut être utilisé pour calculer le décalage UTC de votre fuseau horaire actuel. Dans cet exemple, c'est + 1h, c'est-à-dire UTC + 0100.

Références:

Robert Lujo
la source
mktime()peut échouer . En général, vous devez pytzconvertir l'heure locale en utc pour obtenir l'horodatage POSIX.
jfs
calendar.timegm () semble être la version utc de time.mktime ()
frankster
27

int (t.strftime("%s")) fonctionne aussi

dan3
la source
1
Fonctionne pour moi en Python 2.7, avec import datetime; t = datetime.datetime(2011, 10, 21, 0, 0)(comme spécifié par OP). Mais vraiment, je doute que% s soit un format d'heure récemment ajouté.
dan3
1
@ dan3: faux. %sn'est pas pris en charge (il peut fonctionner sur certaines plates-formes si siff test un objet datetime naïf représentant l'heure locale et si la bibliothèque C locale a accès à la base de données tz sinon le résultat peut être faux). Ne l'utilisez pas.
jfs
%sn'est documenté nulle part. Je l'ai semé dans du vrai code et je me demandais ce que c'est et je regarde dans la documentation et il n'y a rien de tel %s. Il n'y a de gros S que pour les secondes.
VStoykov
13

à partir des documents python:

timedelta.total_seconds()

Renvoie le nombre total de secondes contenues dans la durée. Équivalent à

(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6

calculé avec la vraie division activée.

Notez que pour des intervalles de temps très longs (supérieurs à 270 ans sur la plupart des plateformes), cette méthode perdra sa précision en microsecondes.

Cette fonctionnalité est nouvelle dans la version 2.7.

Michael
la source
1
il y a un petit problème avec le calcul il doit être 10 6 au lieu de 10 * 6 ... td.microsecondes + (td.seconds + td.days * 24 * 3600) * 10 6) / 10 ** 6
sdu
@sdu great catch - le double astérisque est dans ma réponse mais stackoverflow le consomme, tente de rectifier seulement enhardir le texte.
Michael
2

Pour convertir un objet datetime qui représente l'heure en UTC en horodatage POSIX :

from datetime import timezone

seconds_since_epoch = utc_time.replace(tzinfo=timezone.utc).timestamp()

Pour convertir un objet datetime qui représente l'heure dans le fuseau horaire local en horodatage POSIX:

import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
seconds_since_epoch = local_timezone.localize(local_time, is_dst=None).timestamp()

Voir Comment convertir l'heure locale en UTC en Python? Si la base de données tz est disponible sur une plateforme donnée; une solution uniquement stdlib peut fonctionner .

Suivez les liens si vous avez besoin de solutions pour les <3.3versions Python.

jfs
la source
1

J'ai essayé le calendar.timegm de la bibliothèque standard et cela fonctionne assez bien:

# convert a datetime to milliseconds since Epoch
def datetime_to_utc_milliseconds(aDateTime):
    return int(calendar.timegm(aDateTime.timetuple())*1000)

Réf: https://docs.python.org/2/library/calendar.html#calendar.timegm

Shaohong Li
la source
il dépouille des fractions de seconde. Il suppose que aDateTimec'est une heure UTC
jfs