Comment puis-je convertir un objet datetime en millisecondes depuis l'époque (temps unix) en Python?

356

J'ai un datetimeobjet Python que je veux convertir en temps Unix ou en secondes / millisecondes depuis l'époque de 1970.

Comment puis-je faire cela?

SuperString
la source
Si vous avez atterri ici juste en voulant des secondes d'époque actuelles avec une précision en millisecondes, essayez $ python -c 'import time; print(time.time())'ce qui a donné:1584487455.698623
MarkHu

Réponses:

474

Il me semble que la façon la plus simple de le faire est

import datetime

epoch = datetime.datetime.utcfromtimestamp(0)

def unix_time_millis(dt):
    return (dt - epoch).total_seconds() * 1000.0
Sophie Alpert
la source
32
Jusqu'à présent, c'est la meilleure solution (si version python> 2.7). Parce que l'implémentation de %sdépend du système d'exploitation! Ainsi, n'importe qui veut que le code fonctionne de manière fiable quel que soit le système d'exploitation, ne doit JAMAIS utiliser %s. Pour 2,3 <py ver <2,7. On peut simplement en construire un total_seconds()comme ça:delta.days*86400+delta.seconds+delta.microseconds/1e6
Wang
14
note: dtdoit être en UTC (pas local). Voir une réponse similaire avec le support Python 2.6 / 3
jfs
7
Il convient de mentionner que si tout ce que vous voulez est un véritable horodatage Unix tel que défini ici en.wikipedia.org/wiki/Unix_time (et que vous n'utiliserez donc que la fonction unix_time de cette réponse), vous devez encapsuler delta.total_seconds () avec int pour éviter de se retrouver avec un flotteur
corford
1
L'époque calculée à l'aide de utcfromtimestamp(0)peut provoquer un décalage de «tz» uniquement si «tz» n'est pas égal à 0. Cela est dû dt au fait que dans dt- epoch«tz» y est calculé alors que epoch est le temps UTC. La meilleure façon de calculer l'époque epoch = datetime.datetime(1970, 1, 1)est de considérer le fuseau horaire.
ahj
35
Pourquoi oh pourquoi datetime.utcfromtimestamp(0)retourne un datetime sans tzinfo? C'est juste là dans le nom de la méthode, utc fromtimestamp. Afin de le rendre non naïf, je dois faire quelque chose comme datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC). Cela est nécessaire si le dtfuseau horaire est au courant, sinon vous obtiendrezTypeError: can't subtract offset-naive and offset-aware datetimes
FGreg
171

En Python 3.3, ajout d'une nouvelle méthode timestamp:

import datetime
seconds_since_epoch = datetime.datetime.now().timestamp()

Votre question indiquait que vous aviez besoin de millisecondes, que vous pouvez obtenir comme ceci:

milliseconds_since_epoch = datetime.datetime.now().timestamp() * 1000

Si vous utilisez timestampun objet datetime naïf, il a supposé qu'il se trouve dans le fuseau horaire local. Utilisez des objets datetime compatibles avec le fuseau horaire si ce n'est pas ce que vous avez l'intention de faire.

eshizhan
la source
28
Remarque: la .timestamp()méthode suppose qu'un datetime d'entrée naïf se trouve dans le fuseau horaire local (et que l'heure locale peut être ambiguë). S'il est en UTC, utilisez-le à la dt.replace(tzinfo=timezone.utc).timestamp()place .
jfs
11
datetime.timestamp () renvoie les secondes de l'époque sous forme de flottant. Pour obtenir des millisecondes: int (datetime.timestamp () * 1000)
Solar.gy
9
Cette réponse n'est pas un exemple copiable et collable, dans l'esprit des documents peu conviviaux sur docs.python.org/3/library/… - c'est: datetime.datetime.timestamp(datetime.datetime.now())
MarkHu
3
Dans 3.6 (au moins), datetime.timestamp () suppose qu'un datetime naïf (tzinfo = None) datetime est en UTC. Il vaut donc toujours mieux que votre fuseau horaire soit défini: datetime.datetime.now(pytz.timezone('Europe/Paris')).timestamp() == datetime.datetime.now(pytz.utc).timestamp() == datetime.datetime.utcnow().timestamp()mais pas (toujours) égal à datetime.datetime.now().timestamp()(ce dernier n'est égal au reste que si le tz local est UTC ...)
Bluu
1
Pour votre intérêt, l'inverse est] fromtimestamp( docs.python.org/3/library/… )
Flimm
98
>>> import datetime
>>> # replace datetime.datetime.now() with your datetime object
>>> int(datetime.datetime.now().strftime("%s")) * 1000 
1312908481000

Ou l'aide du module de temps (et sans formatage de date):

>>> import datetime, time
>>> # replace datetime.datetime.now() with your datetime object
>>> time.mktime(datetime.datetime.now().timetuple()) * 1000
1312908681000.0

Répondu avec l'aide de: http://pleac.sourceforge.net/pleac_python/datesandtimes.html

Documentation:

miku
la source
6
Btw, strftime ("% s") renvoie une chaîne vide pour moi. La deuxième façon fonctionne bien.
Pavel Vlasov
23
N'a
6
'% s' n'est pas pris en charge par Python, par exemple, il peut être absent sous Windows. .timetuple()renvoie tm_isdst=-1il force mktime()à deviner. Il peut deviner à tort pendant l'heure d'été (50% de risque d'erreur +/- heure). '% S' et mktime()peuvent utiliser le mauvais décalage utc pour les dates du passé. Vous avez besoin d'une base de données de fuseau horaire historique telle que fournie par le pytzmodule pour convertir de manière fiable l'heure locale en horodatage POSIX (sauf si le système d'exploitation fournit déjà une telle base de données)
jfs
1
time.mktime(ts.timetuple())où ts est l'objet datetime de python
suhailvs
1
@suhail: lisez mon commentaire ci-dessus à propos de mktime/timetuple. timetuple()Dépouille également des fractions de seconde et le but de la question est d'obtenir l'horodatage avec une précision en millisecondes.
jfs
13

Voici comment je le fais:

from datetime import datetime
from time import mktime

dt = datetime.now()
sec_since_epoch = mktime(dt.timetuple()) + dt.microsecond/1000000.0

millis_since_epoch = sec_since_epoch * 1000
estani
la source
2
@JFSebastian Merci pour l'avertissement! en effet, aucun dst n'est envisagé. Si votre serveur est en heure locale au lieu de UTC, cela fera une différence. Je n'ai pas (encore) trouvé de raison impérieuse de configurer des serveurs dans autre chose que UTC. Ma devise est "écrire UTC, lire l'heure locale" afin que vous sachiez toujours où vous séjournez ...
estani
2
Vous pouvez toujours utiliser calendar.timegm au lieu de mktime pour éviter le problème de mktime essayant de deviner le fuseau horaire.
Decko
13

Recommandations de la documentation Python 2.7 pour le timemodule

Conversion entre les représentations temporelles

Ankur Agarwal
la source
@ChristopherBull Divisez simplement le nombre de millisecondes par 1000 pour arriver en secondes
Jonas
5
Vous avez mal compris et vous vous êtes trompé. Les secondes sont toutes prêtes à être disponibles dans les fonctions ci-dessus. Vous pouvez le convertir en millisecondes, mais ce serait la précision d'une seconde.
Christopher Bull
1
Cette réponse utilise le timemodule, mais l'OP a posé des questions sur le datetimemodule. FWIW, l'époque actuelle la plus simple estint(time.time())
MarkHu
7
from datetime import datetime
from calendar import timegm

# Note: if you pass in a naive dttm object it's assumed to already be in UTC
def unix_time(dttm=None):
    if dttm is None:
       dttm = datetime.utcnow()

    return timegm(dttm.utctimetuple())

print "Unix time now: %d" % unix_time()
print "Unix timestamp from an existing dttm: %d" % unix_time(datetime(2014, 12, 30, 12, 0))
corford
la source
timegm()ne fonctionne qu'avec le temps utc. Il n'utilise pas tm_isdstdonc vous pouvez utiliser à la utcnow.timetuple()place de utcnow.utctimetuple(). Remarque: l'utilisation naive_local_datetime.utctimetuple()serait incorrecte ici. Il ne traduit pas l'heure locale en utc. timetuple()Appelez également les fractions de fractions de seconde du résultat (si cela dépend de l'application). De plus, la question porte sur * milli * secondes, pas sur les secondes
jfs
Je préfère utiliser utcnow () et utctimetuple () pour rendre le code absolument clair que vous traitez avec UTC (et de cette façon, quiconque le lisant n'a pas à se rappeler que timegm est uniquement UTC). utctimetuple () n'implique pas de traduction sur un objet dttm naïf (d'où l'initiation du dttm avec utcnow ()). En outre, la question mentionne des secondes ou des millisecondes.
corford
Remarque: j'aurais dû dire dans le dernier commentaire que j'ai lu la question comme impliquant qu'il voulait des secondes ou des millisecondes (probablement mon erreur). Pour les millis, multipliez simplement par 1000 (comme le suggère la réponse du meilleur score).
corford
utctimetuple()dépouille des fractions de seconde. La multiplication par 1000ne les récupérera pas.
jfs
1
En raison de la façon dont l'OP a posé cette question, on ne sait pas exactement ce qu'il / elle voulait (c'est-à-dire un horodatage Unix vrai ou un horodatage avec une précision en millisecondes). Quoi qu'il en soit, les deux questions ont déjà été posées et répondues ailleurs. Cela dit, je pense que les réponses ici sont les plus rapides et les plus propres à saisir et à illustrer les différentes solutions au problème.
corford
3
>>> import datetime
>>> import time
>>> import calendar

>>> #your datetime object
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2013, 3, 19, 13, 0, 9, 351812)

>>> #use datetime module's timetuple method to get a `time.struct_time` object.[1]
>>> tt = datetime.datetime.timetuple(now)
>>> tt
time.struct_time(tm_year=2013, tm_mon=3, tm_mday=19, tm_hour=13, tm_min=0, tm_sec=9,     tm_wday=1, tm_yday=78, tm_isdst=-1)

>>> #If your datetime object is in utc you do this way. [2](see the first table on docs)
>>> sec_epoch_utc = calendar.timegm(tt) * 1000
>>> sec_epoch_utc
1363698009

>>> #If your datetime object is in local timeformat you do this way
>>> sec_epoch_loc = time.mktime(tt) * 1000
>>> sec_epoch_loc
1363678209.0

[1] http://docs.python.org/2/library/datetime.html#datetime.date.timetuple

[2] http://docs.python.org/2/library/time.html

Jinesh
la source
3

Voici une autre forme de solution avec normalisation de votre objet temps:

def to_unix_time(timestamp):
    epoch = datetime.datetime.utcfromtimestamp(0) # start of epoch time
    my_time = datetime.datetime.strptime(timestamp, "%Y/%m/%d %H:%M:%S.%f") # plugin your time object
    delta = my_time - epoch
    return delta.total_seconds() * 1000.0
arhoskins
la source
2

Un peu de code pandas:

import pandas

def to_millis(dt):
    return int(pandas.to_datetime(dt).value / 1000000)
volhv
la source
1
import time
seconds_since_epoch = time.mktime(your_datetime.timetuple()) * 1000
MattoTodd
la source
9
C'est faux! L'horaire ne comprend pas la milliseconde, donc mktime ne renverra pas l'époque avec une résolution en millisecondes. C'est inutile dans ce cas.
Wang
@Wang - vous avez raison monsieur, cela ne retourne pas millis, seulement quelques secondes
MattoTodd
1
Si vous supprimez * 1000, cependant, vous obtenez seconds_since_epoch. Vote pour cette réponse parce que je ne me soucie pas des millisecondes en ce moment.
Michael Scheper
0

Voici une fonction que j'ai faite sur la base de la réponse ci-dessus

def getDateToEpoch(myDateTime):
    res = (datetime.datetime(myDateTime.year,myDateTime.month,myDateTime.day,myDateTime.hour,myDateTime.minute,myDateTime.second) - datetime.datetime(1970,1,1)).total_seconds()
    return res

Vous pouvez encapsuler la valeur retournée comme ceci: str (int (res)) Pour la retourner sans valeur décimale à utiliser comme chaîne ou juste int (sans la chaîne)

Gil Allen
la source
-14

Cette autre solution pour datetime caché à unixtimestampmillis.

private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public static long GetCurrentUnixTimestampMillis()
    {
        DateTime localDateTime, univDateTime;
        localDateTime = DateTime.Now;          
        univDateTime = localDateTime.ToUniversalTime();
        return (long)(univDateTime - UnixEpoch).TotalMilliseconds;
    } 
samsanthosh2008
la source
2
La question concerne le langage Python
Stéphane