J'ai le temps non segmenté gps comme ceci:
Tgps = 1092121243.0
Et j'aimerais comprendre quelle est la date et l'heure. Le début de l'heure GPS est le 6 janvier 1980. Fonction Python
datetime.utcfromtimestamp
pourrait donner secondes à partir du 1er janvier 1970 année.
J'ai trouvé suivant:
from datetime import datetime
GPSfromUTC = (datetime(1980,1,6) - datetime(1970,1,1)).total_seconds()
curDate = datetime.utcfromtimestamp(Tgps + GPSfromUTC)
Out[83]: datetime.datetime(2014, 8, 15, 7, 0, 43)
Je ne suis pas sûr que des secondes soient écoulées, sont-elles incluses dans la fonction datetime ou devrais-je les calculer et soustraire du résultat? Peut-être existe-t-il également une meilleure solution à ce problème?
L'heure GPS a commencé en synchronisation avec l'heure UTC: 1980-01-06 (UTC) == 1980-01-06 (GPS)
. Les deux cochent en secondes SI. La différence entre l'heure GPS et l'heure UTC augmente avec chaque seconde intercalaire (intercalaire).
Pour trouver l'heure UTC correcte, vous devez connaître le nombre de secondes bissextiles écoulées avant l'heure GPS donnée:
#!/usr/bin/env python
from datetime import datetime, timedelta
# utc = 1980-01-06UTC + (gps - (leap_count(2014) - leap_count(1980)))
utc = datetime(1980, 1, 6) + timedelta(seconds=1092121243.0 - (35 - 19))
print(utc)
2014-08-15 07:00:27 # (UTC)
où leap_count(date)
est le nombre de secondes bissextiles introduites avant la date donnée. De table TAI-UTC _ _ (remarque: le site est la source faisant autorité en secondes intercalaires. Il publie le bulletin C annonçant de nouvelles secondes intercalaires ):
1980..: 19s
2012..: 35s
et donc:
(leap_count(2014) - leap_count(1980)) == (35 - 19)
Si vous êtes sous Unix, vous pouvez utiliser le "right"
fuseau horaire pour obtenir l'heure UTC à partir de l'heure TAI (Et il est facile d'obtenir l'heure TAI à partir de l'heure GPS: TAI = GPS + 19 secondes (décalage constant) } _):
#!/usr/bin/env python
import os
import time
os.environ['TZ'] = 'right/UTC' # TAI scale with 1970-01-01 00:00:10 (TAI) Epoch
time.tzset() # Unix
from datetime import datetime, timedelta
gps_timestamp = 1092121243.0 # input
gps_Epoch_as_gps = datetime(1980, 1, 6)
# by definition
gps_time_as_gps = gps_Epoch_as_gps + timedelta(seconds=gps_timestamp)
gps_time_as_tai = gps_time_as_gps + timedelta(seconds=19) # constant offset
tai_Epoch_as_tai = datetime(1970, 1, 1, 0, 0, 10)
# by definition
tai_timestamp = (gps_time_as_tai - tai_Epoch_as_tai).total_seconds()
print(datetime.utcfromtimestamp(tai_timestamp)) # "right" timezone is in effect!
2014-08-15 07:00:27 # (UTC)
Vous pouvez éviter de modifier le fuseau horaire si vous extrayez la liste des secondes intercalaires à partir du tzfile(5)
correspondant. C'est une combinaison des deux premières méthodes où le calcul du nombre de sauts de la première méthode est automatisé et la mise à jour automatique tzdata
(package système pour la base de données tz ) de la deuxième méthode est utilisée:
>>> from datetime import datetime, timedelta
>>> import leapseconds
>>> leapseconds.gps_to_utc(datetime(1980,1,6) + timedelta(seconds=1092121243.0))
datetime.datetime(2014, 8, 15, 7, 0, 27)
où leapseconds.py
peut extraire les secondes intercalaires du fichier /usr/share/zoneinfo/right/UTC
(composant du package tzdata
).
Les trois méthodes produisent le même résultat.
J'utilise la fonction suivante qui compte les secondes intercalaires:
import bisect
from datetime import datetime, timedelta
_LEAP_DATES = ((1981, 6, 30), (1982, 6, 30), (1983, 6, 30),
(1985, 6, 30), (1987, 12, 31), (1989, 12, 31),
(1990, 12, 31), (1992, 6, 30), (1993, 6, 30),
(1994, 6, 30), (1995, 12, 31), (1997, 6, 30),
(1998, 12, 31), (2005, 12, 31), (2008, 12, 31),
(2012, 6, 30), (2015, 6, 30), (2016, 12, 31))
LEAP_DATES = Tuple(datetime(i[0], i[1], i[2], 23, 59, 59) for i in _LEAP_DATES)
def leap(date):
"""
Return the number of leap seconds since 1980-01-01
:param date: datetime instance
:return: leap seconds for the date (int)
"""
# bisect.bisect returns the index `date` would have to be
# inserted to keep `LEAP_DATES` sorted, so is the number of
# values in `LEAP_DATES` that are less than `date`, or the
# number of leap seconds.
return bisect.bisect(LEAP_DATES, date)
Bien sûr, vous devez mettre à jour _LEAP_DATES
de temps en temps, mais ces mises à jour sont assez rares.
En général, l'heure GPS se compose de deux chiffres: Semaine GPS et le nombre de secondes depuis le début de la semaine GPS en cours. Par conséquent, vous pouvez utiliser les éléments suivants:
def gps2utc(week, secs):
"""
:param week: GPS week number, i.e. 1866
:param secs: number of seconds since the beginning of `week`
:return: datetime instance with UTC time
"""
secs_in_week = 604800
gps_Epoch = datetime(1980, 1, 6, 0, 0, 0)
date_before_leaps = gps_Epoch + timedelta(seconds=week * secs_in_week + secs)
return date_before_leaps - timedelta(seconds=leap(date_before_leaps))
Dans votre cas, week = 0
, donc:
In [1]: gps2utc(0, 1092121243.0)
Out[1]: datetime.datetime(2014, 8, 15, 7, 0, 27)
Vous pouvez utiliser le paquet astropy.time pour le faire:
from astropy.time import Time
mytime = 1172361618
t = Time(mytime, format='gps')
t = Time(t, format='iso')
print t
qui retourne:
2017-03-01 00: 00: 37.000
Je pense qu’il ya quelques légères définitions au niveau 1 seconde entre le temps UNIX rapporté par astropy et la définition stricte POSIX, mais c’est proche.