【问题标题】:How to get current date and time from GPS unsegment time in python如何从python中的GPS取消分段时间获取当前日期和时间
【发布时间】:2016-01-29 16:02:10
【问题描述】:

我有这样的 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 中,或者我应该计算它们并从结果中减去? 是否也存在更好的解决这个问题的方法?

【问题讨论】:

    标签: python datetime gps


    【解决方案1】:

    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(注意:该网站是闰秒的权威来源。它发布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) 中提取闰秒列表,您可以避免更改时区。它是前两种方法的组合,其中第一种方法的跳跃计数计算是自动的,并且使用第二种方法的自动更新tzdatathe 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 包的一部分)中提取闰秒。

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

    【讨论】:

      【解决方案2】:

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

      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)
      

      【讨论】:

      【解决方案3】:

      您可以使用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)
      

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

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

      【讨论】:

        猜你喜欢
        • 2011-01-01
        • 2012-12-04
        • 1970-01-01
        • 1970-01-01
        • 2012-08-15
        • 1970-01-01
        • 2018-09-26
        • 1970-01-01
        相关资源
        最近更新 更多