2017-03-14 2 views
0

J'ai essayé de calculer la date moi-même en utilisant l'entier signé maximum de 64 bits mais toujours finir avec une autre date qui est différente de quelques millions d'années. J'ai essayé d'utiliser les années sidérales et les années bissextiles, mais j'ai toujours des résultats qui durent au moins quelques millions d'années.Comment la date du 4 décembre 292,277,026,596 a-t-elle été calculée pour le débordement de l'horodatage unix signé 64 bits?

Voici ce que j'ai essayé jusqu'ici:

dateA = 1970 + (9223372036854775807/31556926.08)

dateB = 1970 + (9223372036854775807/31536000) + (((9223372036854775807/31536000)/4)/365)

Les deux renvoient la mauvaise réponse. Quelqu'un peut-il me guider dans la bonne direction?

+0

Êtes-vous sûr de la valeur signée est utilisée comme limite? Certaines implémentations utilisent une signature non signée. –

+2

Avez-vous même google comment calculer l'année bissextile? - Il vous manque plusieurs parties qui pourraient affecter les choses aussi longtemps. – stdunbar

+0

Mais même si l'année bissextile était erronée, l'année sidérale ne serait-elle pas correcte? –

Répondre

2

Vous devez tenir compte des années bissextiles. Une année est une année bissextile si:

  • est divisible par 4;
  • sauf si il est également divisible par 100;
  • ou si elle est divisible par 400.

Comme une estimation approximative de l'année, le calcul 1970 + 0x7fffffffffffffff // 86400 // (365 + 1/4 - 1/100 + 1/400) donne une réponse de 292277026596. Je vais laisser la dérivation de la journée exacte comme un exercice pour le lecteur.

J'ai utilisé Python 3 pour ce calcul qui donne des résultats réels pour les divisions entières. Ajustez en conséquence pour Python 2.

+0

Merci! Je n'ai pas importé de division de '__future__', alors ça gâchait tous mes résultats, maintenant c'est correct pour le jour. –

2

Utilisons datetime pour soulever des charges lourdes.

>>> import datetime 

D'abord, le calendrier grégorien se répète exactement tous les 400 ans. Voici le nombre de jours d'un cycle de 400 ans:

>>> 365 * 400 + 100 - 4 + 1 
146097 

Effacer? Chaque année a au moins 365 jours. Il y aurait 100 années bissextiles (+100), sauf les années divisibles par 100 ne sont pas des années bissextiles (-4), sauf les années divisibles par 400 sont les années bissextiles (+1).

Utilisez ensuite que pour savoir combien de blocs de 400 ans correspondent à un certain nombre de secondes égal au plus grand entier 63 bits:

>>> divmod((1 << 63) - 1, 146097 * 24 * 3600) 
(730692561, 7161147007) 

Nous avons donc 730692561 blocs de 400 ans, avec 7161147007 secondes laissé pour compte. datetime peut directement calculer ce nombre de secondes au-delà de l'époque:

>>> datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=7161147007) 
datetime.datetime(2196, 12, 4, 15, 30, 7) 

Ainsi, sauf pour l'année, la dernière seconde représentable est le 4 Décembre à 15:30:07 UTC.

Pour obtenir l'année, il suffit d'ajouter les blocs 730.692.561 400 ans:

>>> 2196 + 730692561 * 400 
292277026596 
+0

En soustrayant des multiples exacts de 400 ans, c'est génial, j'aurais aimé y penser. –

+1

Heh - J'ai écrit le module 'datetime', et il fait quelque chose de très similaire en interne, juste au cas où nous laisserions un jour des nombres illimités ;-) –

+1

J'ai revu cette réponse et il m'est apparu que dans 400 ans tu pourrais finis un autre jour de la semaine, donc j'ai vérifié: 146097% 7 == 0. Ces Grégoriens pensaient à tout! –