web-dev-qa-db-fra.com

Comment tester si un horodatage donné est en secondes ou millisecondes?

Supposons une variable donnée, elle contient un horodatage UNIX, mais que ce soit au format secondes ou millisecondes est inconnu, je veux l'assigner à une variable au format secondes

Par exemple:

unknown = 1398494489444 # This is millisecond
t = ???

Mise à jour: je comprends qu'il n'est pas possible de le dire sans donner quelques limitations, alors le voici

  • current_ts - 86400 * 365 <inconnu <current_ts

Assume current_ts = current unix timestamp

27
Ryan

Si vous convertissez les valeurs d'horodatage maximales avec x chiffres en millisecondes, vous obtenez quelque chose comme ceci:

  • 9999999999999 (13 chiffres) signifie samedi 20 novembre 2286 17:46:39 UTC
  • 999999999999 (12 chiffres) signifie Sun Sep 09 2001 01:46:39 UTC
  • 99999999999 (11 chiffres) signifie sam 03 mars 1973 09:46:39 UTC

Vos horodatages peuvent-ils être antérieurs à 2001? Sinon, je pense que vous pouvez vérifier si le nombre comporte 13 chiffres ou plus - si oui, vous avez des millisecondes, sinon vous avez des secondes. Bien sûr, cela ne fonctionnera que jusqu'à ce que les horodatages en secondes aient également 13 chiffres, ce qui signifie que les horodatages en millisecondes auront 16 chiffres:

  • 1000000000000000 (16 chiffres) signifie vendredi 27 septembre 33658 01:46:40 mais d'ici là, je vivrai sur une planète du système Alpha Centauri et les normes de temps auront probablement changé un peu :)

P.S. vous pouvez assouplir la condition à 12 chiffres ou plus, si vos horodatages ne peuvent pas remonter plus loin que 1973. La condition ne devrait être correcte que jusqu'à:

  • 100000000000000 (15 chiffres) signifie mercredi 16 novembre 5138 09:46:40 car cela en secondes aura 12 chiffres et chevauchera avec votre condition
41
Sandman

Au risque d'attirer des votes négatifs, je tiens à dire officiellement que ne le faites pas.

Faire des hypothèses sur les unités d'une quantité physique est une idée terrible - cela a conduit à la destruction de Mars Meteorological Orbiter (les unités de poussée calculées étaient en livres, les moteurs attendaient des Newtons. Pas assez de poussée - et l'orbiteur a brûlé dans l'atmosphère).

Si vous avez une assez bonne idée de l'ampleur d'un nombre, vous devriez pouvoir faire une "supposition éclairée" des unités. Par exemple, si je vous dis que mon poids est de 230, vous pourriez me regarder et penser "je parie que ce sont des livres, pas des kilos". De même, si vous convertissez un horodatage de mon anniversaire en une date en supposant qu'elle était en secondes, et que cela se révèle être de 200 ans dans le futur, vous pouvez raisonnablement supposer que "secondes" n'était pas la bonne unité.

Mais c'est une chose DANGEREUSE à faire.

Pourtant - si vous devez le faire, alors en général, je recommanderais l'approche suivante:

  1. Compte tenu de toutes les unités possibles, effectuez la conversion à une échelle "sensible" (par exemple, convertissez votre horodatage en année/mois/jour).
  2. Regardez les valeurs que vous avez obtenues. Lequel de ceux-ci est "le plus probable". Dans le cas des dates, vous pourriez avoir une bonne idée (date de mise en service de cet ordinateur: était-ce 1970 ou 2012? Etc)
  3. Choisissez la valeur la plus probable
  4. Enregistrez quelque part que c'est ce que vous avez fait - de sorte que si les conséquences de cette décision s'avèrent fausses, vous puissiez retracer l'erreur

Cette dernière chose est importante - elle vous permettra d'apprendre de votre erreur. Par exemple, si votre horodatage vous indique quelque chose sur la prochaine apparition de la comète, vous pouvez imprimer

Prochaine apparition attendue de la comète: 29 décembre 2546 (hypothèse: l'horodatage de X a été donné en secondes)

De cette façon, il y a un "retour". En général, " documentez vos hypothèses " n'est pas seulement un bon conseil - il est essentiel dans toute science exacte.

Enfin - la conversion d'un horodatage de ms en s est obtenue en divisant le nombre par 1000. Mais je suis sûr que vous le savez.

21
Floris

Avec vos contraintes, il est trivial de détecter des horodatages en millisecondes. Même les horodatages d'un an dans le passé sont encore plus grands que l'horodatage actuel.

Testez simplement si le nombre est supérieur à l'horodatage actuel; si oui, vous avez un horodatage en millisecondes:

now = time.mktime(time.gmtime())
if t > now:
    # milliseconds, convert to seconds
    t /= 1000.0

En divisant par 1000, vous reconvertissez l'horodatage en un exprimé en secondes et les fonctions par défaut du module time peuvent être appliquées.

En effet, même un horodatage en millisecondes représentant une année dans le passé, interprété accidentellement comme horodatage en secondes, se situerait loin dans le futur:

>>> import time
>>> ts = time.mktime(time.gmtime())
>>> year_ago = ts - (86400 * 365)
>>> time.gmtime(year_ago * 1000) # misinterpret milliseconds as seconds
time.struct_time(tm_year=45395, tm_mon=7, tm_mday=9, tm_hour=14, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=190, tm_isdst=0)

Vous devez avoir un horodatage début 197 avant de pouvoir confondre les deux plages:

>>> now = time.mktime(time.gmtime())
>>> time.gmtime(ts / 1000) # misinterpret seconds as milliseconds
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=17, tm_hour=5, tm_min=25, tm_sec=13, tm_wday=5, tm_yday=17, tm_isdst=0)

Par exemple. les horodatages des 17 premiers jours suivant l'époque UNIX pourraient être confondus avec les horodatages en millisecondes. Tout après cette date sera plus grande qu'un horodatage de "l'heure actuelle".

Avec vos contraintes spécifiques, vous avez la chance de pouvoir séparer les deux unités si facilement. meilleure option est de ne pas entrer dans cette situation en premier lie. Ces données provenaient de quelque part; déterminez le plus tôt possible quel type de données vous avez au lieu de devoir deviner plus tard. Aucun système ne vous donnera au hasard des horodatages en secondes une partie du temps, des horodatages en millisecondes le reste du temps. Vous pouvez sûrement savoir sur la base d'autres informations quel type de données vous recherchez et convertir à ce moment-là ou annoter vos données pour inclure le type?

20
Martijn Pieters

Une alternative à la réponse donnée par Martin:

Nous avons rencontré ce problème lorsque nous avons dû unifier les horodatages des documents provenant de tiers. Alors que la condition précédente était:

if date > time.time():
    use_miliseconds(date)
else:
    use_seconds(date)

, et il semble que cela devrait fonctionner, il existe des cas Edge, surtout si date a été dérivé d'une représentation sous forme de chaîne sans informations de fuseau horaire, ou si les horloges sont modifiées.

Une variante plus sûre serait d'utiliser:

if date > time.time() + HUNDRED_YEARS:
    use_miliseconds(date)
else:
    use_seconds(date)

, où HUNDRED_YEARS = 365 * 24 * 3600. Cette condition est beaucoup plus sujette aux erreurs, en fait, elle fonctionne pour n'importe quelle date sauf janvier et février 1970 (qui sont ambigus dans les deux cas).

0
vlyubin