Python Créer un horodatage Unix cinq minutes dans le futur

297

Je dois créer une valeur "Expires" 5 minutes dans le futur, mais je dois la fournir au format UNIX Timestamp. Je l'ai jusqu'à présent, mais cela semble être un hack.

def expires():
    '''return a UNIX style timestamp representing 5 minutes from now'''
    epoch = datetime.datetime(1970, 1, 1)
    seconds_in_a_day = 60 * 60 * 24
    five_minutes = datetime.timedelta(seconds=5*60)
    five_minutes_from_now = datetime.datetime.now() + five_minutes
    since_epoch = five_minutes_from_now - epoch
    return since_epoch.days * seconds_in_a_day + since_epoch.seconds

Existe-t-il un module ou une fonction qui effectue la conversion d'horodatage pour moi?

Daniel Rhoden
la source
7
Je recommande de changer le sujet de cette question. La question est bonne, mais il ne s'agit pas de convertir datetime en horodatage Unix. Il s'agit de savoir comment obtenir un horodatage Unix 5 minutes à l'avenir.
DA
Je ne suis pas d'accord, @DA La question dit essentiellement "Je dois faire X et Y. Voici ce que j'ai maintenant. Quelle est la meilleure façon de faire Y?" Il y a peut-être de meilleures façons de faire X, mais le titre et le corps posent clairement des questions sur Y.
Rob Kennedy
6
Je suis entièrement d'accord avec vous sur la question, et je pense que c'est une bonne question avec une bonne réponse. Le problème est que "Python datetime to Unix timestamp" ne reflète ni la question ni la réponse. J'ai trouvé ce message à la recherche d'un moyen de faire la conversion, et j'ai perdu du temps en raison de la ligne d'objet trompeuse. Je suggère: "Python, 5 minutes dans le futur comme horodatage UNIX"
DA
3
@JimmyKane - Une réponse assez complète sur la façon d'obtenir un horodatage à partir d'une date peut être trouvée ici: stackoverflow.com/questions/8777753/…
Tim Tisdall
@TimTisdall oui puisque le titre a changé, cela n'a aucun sens
Jimmy Kane

Réponses:

349

Une autre façon consiste à utiliser calendar.timegm:

future = datetime.datetime.utcnow() + datetime.timedelta(minutes=5)
return calendar.timegm(future.timetuple())

Il est également plus portable que le %sdrapeau strftime(ce qui ne fonctionne pas sous Windows).

Cat Plus Plus
la source
Merci D.Shawley. help (datetime.timedelta) n'a pas mentionné ce raccourci. Il n'avait que des jours, des secondes et des microsecondes.
Daniel Rhoden
12
Notez que, en combinant les deux précédents commentaires, la bonne solution est: calendar.timegm(future.utctimetuple()). Cela garantit qu'un temps UTC est passé calendar.timegm.
shadowmatter
1
Je ne peux pas voter assez pour le commentaire de @ tumbleweed. Si vous essayez d'obtenir un horodatage UNIX (et donc un en UTC), utilisez calendar.timegm.
Bialecki
@ tumbleweed, à droite. Si vous utilisez mktime plus gmtime (0) entraînera un delta aller-retour différent de zéro pour tout fuseau horaire en plus de l'UTC: par exemple, `time.mktime (datetime.fromtimestamp (time.mktime (time.gmtime (0))). TIMERUPLE ())` donne des 21600.0secondes (6 heures) au lieu de 0,0 pour le TZ de ma machine Unix
plaques de cuisson
Si vous voulez obtenir l' horodatage UTC vous devez utiliser ceci: calendar.timegm(datetime.datetime.utcnow().timetuple()). La méthode utilisant datetime.datetime.now().utctimetuple()ne fonctionne pas pour moi (Python 3.2).
Wookie88
155

Maintenant, en Python> = 3.3, vous pouvez simplement appeler la méthode timestamp () pour obtenir l'horodatage sous forme de flottant.

import datetime
current_time = datetime.datetime.now(datetime.timezone.utc)
unix_timestamp = current_time.timestamp() # works if Python >= 3.3

unix_timestamp_plus_5_min = unix_timestamp + (5 * 60)  # 5 min * 60 seconds
Tim Tisdall
la source
4
+1 pour cela. Il devrait être affiché beaucoup plus haut, car c'est la façon la plus claire de le faire dans Python 3
Viktor Stískala
2
@ scott654 Je pensais que l'avoir bien au début du commentaire le rendait assez clair, mais j'y ai ajouté du gras aussi.
Tim Tisdall
1
Je ferais la note en tant que commentaire dans le bloc de code parce que nous analysons tous le code dans les réponses en premier et ne lisons le reste que si le code semble bon. Bonne réponse cependant.
Matthew Purdon
2
l'heure locale peut être ambiguë . L'exemple ( datetime.now()) est mauvais car il encourage l'utilisation d'objets datetime naïfs qui représentent l'heure locale et il peut échouer pendant les transitions DST (en raison de l'ambiguïté inhérente). Vous pouvez utiliser à la ts = datetime.now(timezone.utc).timestamp()place.
jfs
@JFSebastian - bon point. Je ne voulais pas ajouter aux importations, cependant, je l'ai changé en utcnow(). Je suis habitué à travailler sur des machines où le fuseau horaire est défini sur UTC, mais cela ne devrait pas être supposé dans cet extrait de code.
Tim Tisdall
139

Je viens de trouver cela, et c'est encore plus court.

import time
def expires():
    '''return a UNIX style timestamp representing 5 minutes from now'''
    return int(time.time()+300)
Daniel Rhoden
la source
12
Cela ne répond pas à la question.
Jesse Dhillon du
22
@JesseDhillon, il répond à la question (faire un horodatage UNIX 5 minutes à l'avenir), mais pas le titre.
dbr
3
time.time()peut être reculé. Pour créer une valeur "Expires" 5 minutes dans le futur, vous pourriez avoir besoin d' time.monotonic()analogue selon votre cas d'utilisation.
jfs
@ jf-sebastian time.monotonic () ne renvoie pas d'horodatage UNIX, il renvoie un horodatage avec un point de référence non défini.
rspeer
@rspeer: oui, comme le disent les docs , seule la différence entre les appels consécutifs est valable. La monotonicpossibilité de l'utiliser dépend de votre cas d'utilisation, par exemple, le subprocessmodule l'utilise pour implémenter l' timeoutoption.
jfs
57

Voici ce dont vous avez besoin:

import time
import datetime
n = datetime.datetime.now()
unix_time = time.mktime(n.timetuple())
Ali
la source
En quoi est-ce différent ou s'ajoute à celui fourni par «Cat Plus Plus»?
David
3
EG c'est la réponse à la question "Python datetime to Unix timestamp" tandis que Cat Plus Plus a répondu à la question "Python datetime that will be in 5 minutes to Unix timestamp". Donc celui-ci est propre et évident.
running.t
@ running.t: cela me rappelle: "chaque problème a une solution simple, évidente et erronée ". Voir les problèmes possibles avecmktime(dt.timetuple()) . datetime.now(timezone.utc).timestamp()fourni par @Tim Tisdall est la solution en Python 3.3+. Sinon, (dt - epoch).total_seconds()pourrait être utilisé .
jfs
@JFSebastian et si je veux vraiment que tous les calculs aient lieu en heure locale? Est-ce le cas, par exemple. analyser une chaîne naïve dont on sait qu'elle est l'heure locale et décider s'il y avait de l'heure d'été en vigueur à ce moment précis?
n611x007
1
@naxa: oui, certaines heures locales sont ambiguës ou inexistantes. Le décalage du fuseau horaire peut également être différent pour des raisons autres que l'heure d'été (vous avez besoin d'une base de données tz telle que pytz, pour trouver le décalage correct). L'heure locale signifie que tout politicien local pense que c'est une bonne idée de mesurer le temps, c'est-à-dire qu'il peut être très irrégulier.
jfs
48

Vous pouvez utiliser datetime.strftimepour obtenir l'heure sous forme Epoch, en utilisant la %schaîne de format:

def expires():
    future = datetime.datetime.now() + datetime.timedelta(seconds=5*60)
    return int(future.strftime("%s"))

Remarque: cela ne fonctionne que sous Linux et cette méthode ne fonctionne pas avec les fuseaux horaires.

mipadi
la source
32
Il s'agit d'un comportement quelque peu non documenté ( python.org/doc/current/library/datetime.html ). Semble fonctionner sous linux et ne fonctionne pas sous win32 (génération ValueError: Invalid format string).
Antony Hatchkins
3
Cette méthode ne fonctionne pas avec les fuseaux horaires. La modification du fuseau horaire donnera le même résultat datetime (2013,12,7, tzinfo = timezone ("America / Chicago")). Strftime ("% s") 1386385200 datetime (2013,12,7, tzinfo = timezone ("Europe / Riga ")). Strftime ("% s ") 1386385200
Martins Balodis
11

Voici une datetimesolution moins cassée pour convertir un objet datetime en horodatage posix:

future = datetime.datetime.utcnow() + datetime.timedelta(minutes=5)
return (future - datetime.datetime(1970, 1, 1)).total_seconds()

Voir plus de détails sur Conversion de datetime.date en horodatage UTC en Python .

jfs
la source
6
def in_unix(input):
  start = datetime.datetime(year=1970,month=1,day=1)
  diff = input - start
  return diff.total_seconds()
Sravan
la source
4

La clé est de vous assurer que toutes les dates que vous utilisez sont dans le fuseau horaire utc avant de commencer la conversion. Voir http://pytz.sourceforge.net/ pour savoir comment procéder correctement. En normalisant à utc, vous éliminez l'ambiguïté des transitions d'heure d'été. Ensuite, vous pouvez utiliser timedelta en toute sécurité pour calculer la distance de l'époque unix, puis convertir en secondes ou millisecondes.

Notez que l'horodatage Unix résultant est lui-même dans le fuseau horaire UTC. Si vous souhaitez voir l'horodatage dans un fuseau horaire localisé, vous devrez effectuer une autre conversion.

Notez également que cela ne fonctionnera que pour les dates après 1970.

   import datetime
   import pytz

   UNIX_EPOCH = datetime.datetime(1970, 1, 1, 0, 0, tzinfo = pytz.utc)
   def EPOCH(utc_datetime):
      delta = utc_datetime - UNIX_EPOCH
      seconds = delta.total_seconds()
      ms = seconds * 1000
      return ms
fawce
la source
3
note: je ne comprends pas "l'horodatage [unix] dans un fuseau horaire localisé". L'horodatage est le même (secondes écoulées depuis 1970-01-01 00:00:00+00:00). Pour obtenir un objet datetime naïf dans le fuseau horaire local:datetime.fromtimestamp(ts)
jfs
4

Ce qui suit est basé sur les réponses ci-dessus (plus une correction pour les millisecondes) et émule datetime.timestamp()pour Python 3 avant 3.3 lorsque les fuseaux horaires sont utilisés.

def datetime_timestamp(datetime):
    '''
    Equivalent to datetime.timestamp() for pre-3.3
    '''
    try:
        return datetime.timestamp()
    except AttributeError:
        utc_datetime = datetime.astimezone(utc)
        return timegm(utc_datetime.timetuple()) + utc_datetime.microsecond / 1e6

Pour répondre strictement à la question posée, vous souhaitez:

datetime_timestamp(my_datetime) + 5 * 60

datetime_timestampfait partie de simple-date . Mais si vous utilisiez ce package, vous taperiez probablement:

SimpleDate(my_datetime).timestamp + 5 * 60

qui gère de nombreux autres formats / types pour my_datetime.

Andrew Cooke
la source
ne devriez-vous pas ajouter (5 * 60) pour ajouter 5 minutes? Je pense que l'ajout de 5 ajoute seulement 5 secondes à l'horodatage.
Tim Tisdall
1
def expiration_time():
    import datetime,calendar
    timestamp = calendar.timegm(datetime.datetime.now().timetuple())
    returnValue = datetime.timedelta(minutes=5).total_seconds() + timestamp
    return returnValue
hd1
la source
1

Notez que les solutions timedelta.total_seconds()fonctionnent avec python-2.7 +. À utiliser calendar.timegm(future.utctimetuple())pour les versions inférieures de Python.

mighq
la source