如何从python中的GPS unsegment时间获取当前日期和时间

Ant*_*pov 9 python datetime gps

我有像这样的gps未分段时间:

Tgps = 1092121243.0
Run Code Online (Sandbox Code Playgroud)

而且我想了解那个日期和时间.GPS时间的开始时间是1980年1月6日.Python功能

datetime.utcfromtimestamp 
Run Code Online (Sandbox Code Playgroud)

从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)
Run Code Online (Sandbox Code Playgroud)

我不确定leapseconds是否包含在函数datetime中,或者我应该计算它们并从结果中减去?也可能存在更好的解决这个问题的方法?

jfs*_*jfs 16

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)
Run Code Online (Sandbox Code Playgroud)

产量

2014-08-15 07:00:27 # (UTC)
Run Code Online (Sandbox Code Playgroud)

leap_count(date)给定日期之前引入的闰秒数.从TAI-UTC表(注意:该站点是闰秒的权威来源.它发布公告C宣布新的闰秒):

1980..: 19s 
2012..: 35s
Run Code Online (Sandbox Code Playgroud)

因此:

(leap_count(2014) - leap_count(1980)) == (35 - 19)
Run Code Online (Sandbox Code Playgroud)

如果你在Unix上,那么你可以使用"right"时区从TAI时间获得UTC时间(并且很容易从GPS时间获得TAI时间:TAI = GPS + 19秒(恒定偏移)):

#!/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!
Run Code Online (Sandbox Code Playgroud)

产量

2014-08-15 07:00:27 # (UTC)
Run Code Online (Sandbox Code Playgroud)

如果从相应的列表中提取闰秒列表,则可以避免更改时区tzfile(5).它是前两种方法的组合,其中第一种方法的闰计算自动化,并使用第二种方法的自动更新tzdata(tz数据库的系统包):

>>> 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)
Run Code Online (Sandbox Code Playgroud)

哪里leapseconds.py可以从/usr/share/zoneinfo/right/UTC文件中提取闰秒(tzdata包的一部分).

所有三种方法都产生相同的结果.


Ru8*_*321 13

你可以使用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)
Run Code Online (Sandbox Code Playgroud)

返回 2014-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)
Run Code Online (Sandbox Code Playgroud)

哪个输出 2014-08-15 07:00:27.000


Yur*_*nko 6

我使用以下计算leap秒的函数:

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)
Run Code Online (Sandbox Code Playgroud)

当然,您需要_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))
Run Code Online (Sandbox Code Playgroud)

就您而言week = 0,这样:

In [1]: gps2utc(0, 1092121243.0)
Out[1]: datetime.datetime(2014, 8, 15, 7, 0, 27)
Run Code Online (Sandbox Code Playgroud)

  • 为了确保您的代码是最新的,您必须每年两次(理论上为4次)咨询[Bulletin C](ftp://hpiers.obspm.fr/iers/bul/bulc/bulletinc.dat)一年)。您可以[使用基于tzfile的解决方案“ right / UTC”`(http://stackoverflow.com/a/33426779/4279)依赖于自动更新的tzdata系统包。 (2认同)