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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33415475/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 13:19:57  来源:igfitidea点击:

How to get current date and time from GPS unsegment time in python

pythondatetimegps

提问by Anton Protopopov

I have gps unsegmented time like this:

我有这样的 GPS 未分段时间:

Tgps = 1092121243.0

And I'd like to understand what date and time is that. The begining of GPS time is 6 January 1980. Python function

我想了解那是什么日期和时间。GPS 时间的起始时间为 1980 年 1 月 6 日。 Python 函数

datetime.utcfromtimestamp 

could give seconds from 1 January 1970 year.

可以给出从 1970 年 1 月 1 日开始的秒数。

I found following:

我发现以下内容:

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)

I'm not sure about leapseconds are they included in function datetime or I should calculate them and substract from the result? May be also exists better solution of this problem?

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

采纳答案by jfs

GPS time started in sync with UTC: 1980-01-06 (UTC) == 1980-01-06 (GPS). Both tick in SI seconds. The difference between GPS time and UTC time increases with each (intercalary) leap second.

GPS 时间开始与 UTC 同步:1980-01-06 (UTC) == 1980-01-06 (GPS)。两者都在 SI 秒内打勾。GPS 时间和 UTC 时间之间的差异随着每个(闰秒)闰秒而增加。

To find the correct UTC time, you need to know the number of leap seconds occurred before the given GPS time:

要找到正确的 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)

Output

输出

2014-08-15 07:00:27 # (UTC)

where leap_count(date)is the number of leap seconds introduced before the given date. From TAI-UTC table(note: the site is the authoritative source on leap seconds. It publishes Bulletin C announcing new leap seconds):

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

1980..: 19s 
2012..: 35s

and therefore:

因此:

(leap_count(2014) - leap_count(1980)) == (35 - 19)


If you are on Unix then you could use "right"time zone to get UTC time from TAI time (and it is easy to get TAI time from GPS time: TAI = GPS + 19 seconds (constant offset)):

如果您使用的是 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!

Output

输出

2014-08-15 07:00:27 # (UTC)


You could avoid changing the timezone if you extract the leap seconds list from the corresponding 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 the second method is used:

如果从相应的tzfile(5). 它是前两种方法的组合,其中第一种方法的跳跃计数计算是自动的,而第二种方法的自动更新tzdatatz 数据库的系统包)被使用:

>>> 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)

where leapseconds.pycan extract leap seconds from /usr/share/zoneinfo/right/UTCfile (part of tzdatapackage).

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

All three methods produce the same result.

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

回答by Yury Kirienko

I use the following function that counts leap seconds:

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

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)

Of course, you need to update _LEAP_DATESoccasionally, but these updates are quite rare.

当然,您_LEAP_DATES偶尔需要更新,但这些更新非常罕见。

In general, GPS time consists of two numbers: GPS weekand the number of secondssince the beginning of the current GPS week. Therefore, you can use the following:

一般来说,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))

In your case week = 0, so:

在你的情况下week = 0,所以:

In [1]: gps2utc(0, 1092121243.0)
Out[1]: datetime.datetime(2014, 8, 15, 7, 0, 27)

回答by Ru887321

You can use the astropy.timepackage to do this:

你可以使用astropy.time包来做到这一点:

GPS time to TAI

到 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)

which returns 2014-08-15 07:01:02.000

返回 2014-08-15 07:01:02.000

GPS time to UTC

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)

which outputs 2014-08-15 07:00:27.000

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