如何从 python 中的 GPS 未分段时间获取当前日期和时间
How to get current date and time from GPS unsegment time in python
我有这样的 gps 未分段时间:
Tgps = 1092121243.0
我想知道那是什么日期和时间。 GPS 时间的开始是 1980 年 1 月 6 日。Python 函数
datetime.utcfromtimestamp
可以给出从 1970 年 1 月 1 日开始的秒数。
我发现了以下内容:
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)
我不确定闰秒是否包含在函数 datetime 中,或者我应该计算它们并从结果中减去?
可能还存在解决此问题的更好方法?
GPS 时间开始与 UTC 同步:1980-01-06 (UTC) == 1980-01-06 (GPS)
。两者都以 SI 秒计。 GPS 时间和 UTC 时间之间的差异随着每个(闰秒)闰秒而增加。
要找到正确的 UTC 时间,您需要知道给定 GPS 时间之前的闰秒数:
#!/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)
其中 leap_count(date)
是给定日期之前引入的闰秒数。来自 TAI-UTC table (note: the site is the authoritative source on leap seconds. It publishes Bulletin C announcing new leap seconds):
1980..: 19s
2012..: 35s
因此:
(leap_count(2014) - leap_count(1980)) == (35 - 19)
如果您使用的是 Unix,那么您可以使用 "right"
时区从 TAI 时间获取 UTC 时间
(并且很容易从 GPS 时间获取 TAI 时间:TAI = GPS + 19 seconds (constant offset)):
#!/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)
如果从使用第二种方法的相应 tzfile(5)
. It is a combination of the first two methods where the leap count computation from the first method is automated and the autoupdating tzdata
(system package for the tz database) 中提取闰秒列表,则可以避免更改时区:
>>> 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)
其中 leapseconds.py
可以从 /usr/share/zoneinfo/right/UTC
文件(tzdata
包的一部分)中提取闰秒。
所有三种方法产生相同的结果。
我使用以下计算闰秒的函数:
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)
当然,你需要偶尔更新_LEAP_DATES
,但这些更新很少见。
一般来说,GPS 时间由两个数字组成:GPS 周 和自当前 GPS 周开始以来的秒 .因此,您可以使用以下内容:
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))
在你的情况下 week = 0
,所以:
In [1]: gps2utc(0, 1092121243.0)
Out[1]: datetime.datetime(2014, 8, 15, 7, 0, 27)
您可以使用 astropy.time 包来执行此操作:
到 TAI 的 GPS 时间
from astropy.time import Time
mytime = 1092121243.0
t = Time(mytime, format='gps')
t = Time(t, format='iso') # same as scale='tai'
print(t)
哪个returns2014-08-15 07:01:02.000
GPS 时间为 UTC
from astropy.time import Time
sec = 1092121243.0
t_in = Time(sec, format='gps')
t_out = Time(t_in, format='iso', scale='utc')
print(t_out)
输出2014-08-15 07:00:27.000
and 个答案之间的线性组合。
from astropy.time import Time
def gps2utc(gpsweek, gpsseconds):
""" GPS time to UTC.
Parameters
----------
gpsweek : int
GPS week number, i.e. 1866.
gpsseconds : int
Number of seconds since the beginning of week.
Returns
-------
datetime
datetime instance with UTC time.
"""
secs_in_week = 604800
secs = gpsweek * secs_in_week + gpsseconds
t_gps = Time(secs, format="gps")
t_utc = Time(t_gps, format="iso", scale="utc")
return t_utc.datetime
在你的情况下 week = 0
,所以:
In [1]: gps2utc(0, 1092121243.0)
Out[1]: datetime.datetime(2014, 8, 15, 7, 0, 27)
我有这样的 gps 未分段时间:
Tgps = 1092121243.0
我想知道那是什么日期和时间。 GPS 时间的开始是 1980 年 1 月 6 日。Python 函数
datetime.utcfromtimestamp
可以给出从 1970 年 1 月 1 日开始的秒数。
我发现了以下内容:
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)
我不确定闰秒是否包含在函数 datetime 中,或者我应该计算它们并从结果中减去? 可能还存在解决此问题的更好方法?
GPS 时间开始与 UTC 同步:1980-01-06 (UTC) == 1980-01-06 (GPS)
。两者都以 SI 秒计。 GPS 时间和 UTC 时间之间的差异随着每个(闰秒)闰秒而增加。
要找到正确的 UTC 时间,您需要知道给定 GPS 时间之前的闰秒数:
#!/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)
其中 leap_count(date)
是给定日期之前引入的闰秒数。来自 TAI-UTC table (note: the site is the authoritative source on leap seconds. It publishes Bulletin C announcing new leap seconds):
1980..: 19s
2012..: 35s
因此:
(leap_count(2014) - leap_count(1980)) == (35 - 19)
如果您使用的是 Unix,那么您可以使用 "right"
时区从 TAI 时间获取 UTC 时间
(并且很容易从 GPS 时间获取 TAI 时间:TAI = GPS + 19 seconds (constant offset)):
#!/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)
如果从使用第二种方法的相应 tzfile(5)
. It is a combination of the first two methods where the leap count computation from the first method is automated and the autoupdating tzdata
(system package for the tz database) 中提取闰秒列表,则可以避免更改时区:
>>> 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)
其中 leapseconds.py
可以从 /usr/share/zoneinfo/right/UTC
文件(tzdata
包的一部分)中提取闰秒。
所有三种方法产生相同的结果。
我使用以下计算闰秒的函数:
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)
当然,你需要偶尔更新_LEAP_DATES
,但这些更新很少见。
一般来说,GPS 时间由两个数字组成:GPS 周 和自当前 GPS 周开始以来的秒 .因此,您可以使用以下内容:
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))
在你的情况下 week = 0
,所以:
In [1]: gps2utc(0, 1092121243.0)
Out[1]: datetime.datetime(2014, 8, 15, 7, 0, 27)
您可以使用 astropy.time 包来执行此操作:
到 TAI 的 GPS 时间
from astropy.time import Time
mytime = 1092121243.0
t = Time(mytime, format='gps')
t = Time(t, format='iso') # same as scale='tai'
print(t)
哪个returns2014-08-15 07:01:02.000
GPS 时间为 UTC
from astropy.time import Time
sec = 1092121243.0
t_in = Time(sec, format='gps')
t_out = Time(t_in, format='iso', scale='utc')
print(t_out)
输出2014-08-15 07:00:27.000
from astropy.time import Time
def gps2utc(gpsweek, gpsseconds):
""" GPS time to UTC.
Parameters
----------
gpsweek : int
GPS week number, i.e. 1866.
gpsseconds : int
Number of seconds since the beginning of week.
Returns
-------
datetime
datetime instance with UTC time.
"""
secs_in_week = 604800
secs = gpsweek * secs_in_week + gpsseconds
t_gps = Time(secs, format="gps")
t_utc = Time(t_gps, format="iso", scale="utc")
return t_utc.datetime
在你的情况下 week = 0
,所以:
In [1]: gps2utc(0, 1092121243.0)
Out[1]: datetime.datetime(2014, 8, 15, 7, 0, 27)