Version 0 of GPS/UTC Time Conversion Functions

Updated 1999-08-11 00:40:38

Phil Ehrens

  • GMT or UTC to GPS
 Description:
 Given a GMT or UNIX epoch time, return GPS time.
 If no argument is given, return current GPS time.

 Parameters:
 time - UNIX epoch seconds, or a date and time: "01/06/80 01:01:01"

 Usage:
         set gpstime [ gpsTime "04/20/99 01:20:59" ]
     or  set gpstime [ gpsTime 91232121 ]
     or  set gpstime [ gpsTime 01/20/01 ]
     or  set gpstime [ gpsTime 01/20/2001 ]
     (of course, you can't calculate GPS time in the future
     unless you know when the leap seconds are...)
     or  set gpstime [ gpsTime now ]


 Comments:
 This procedure must be manually updated when a new
 leap-second is added.  see:
 ftp://tycho.usno.navy.mil/pub/series/ser14.txt
 The GPS epoch started at 0 at 02/06/80 00:00:00 GMT.
 Should put leap seconds in a separate file and check
 daily for updates.

 proc gpsTime { { time "" } } {
     ;## the difference between the UNIX epoch and GPS epoch.
     set epochdiff 315964819
     ;## 1972-01-01 00:00:00 UTC was 1972-01-01 00:00:10 TAI.
     set offset 10
     ;## assumes 00:00:00.
     set leapdates {
                   06/30/1972
                   12/31/1972
                   12/31/1973
                   12/31/1974
                   12/31/1975
                   12/31/1976
                   12/31/1977
                   12/31/1978
                   12/31/1979
                   06/30/1981
                   06/30/1982
                   06/30/1983
                   06/30/1985
                   12/31/1987
                   12/31/1989
                   12/31/1990
                   06/30/1992
                   06/30/1993
                   06/30/1994
                   12/31/1995
                   06/30/1997
                   01/01/1999
                   }
     ;## quick short-circuit for "now".
     if { [ regexp {^$|now} $time ] } {
        set time [ clock seconds ]
        set fudge [ expr $offset + [ llength $leapdates ] ]
        return [ expr $time - $epochdiff + $fudge ]
        }
     ;## build the lookup table in gmt seconds
     foreach date $leapdates {
          lappend leapsecs [ clock scan $date -gmt 1 ]
          }
     ;## canonicalise input to UNIX epoch seconds
     if { ! [ regexp {^-?[0-9]+$} $time ] } {
        if { [ catch {
           set time [ clock scan $time -gmt 1 ]
           } err ] } {
           return -error code $err
           }
        }
     foreach sec [ lsort -integer $leapsecs ] {
          if { $time <= $sec } {
             set index [ lsearch $leapsecs $sec ]
             break;
             }
          ;## if we fall off the end of the list
          set index [ llength $leapsecs ]
          }
     set offset [ expr $offset + $index ]
     set gpstime [ expr $time - $epochdiff + $offset ]
     return $gpstime
 }
  • GPS to UTC
 Description:
 Converts GPS epoch time to UNIX epoch time

 Parameters:
 time - GPS time in GPS seconds, leap second corrected

 Usage:
        set utctime [ utcTime gpsTime ]

 Comments:
 This is what happens when you adopt GPS time as your
 standard!  grumble grumble...
 Yes, it is right -- try "clock format [ utcTime 0 ] -gmt 1"

 proc utcTime { { time "" } } {
     if { ! [ regexp {^-?[0-9]+$} $time ] } {
        return -code error "utcTime requires integer argument"
        }
     ;## the difference between the UNIX epoch and GPS epoch.
     set epochdiff 315964819
     ;## 1972-01-01 00:00:00 UTC was 1972-01-01 00:00:10 TAI.
     set offset 10
     ;## assumes 00:00:00.
     set leapdates {
                   06/30/1972
                   12/31/1972
                   12/31/1973
                   12/31/1974
                   12/31/1975
                   12/31/1976
                   12/31/1977
                   12/31/1978
                   12/31/1979
                   06/30/1981
                   06/30/1982
                   06/30/1983
                   06/30/1985
                   12/31/1987
                   12/31/1989
                   12/31/1990
                   06/30/1992
                   06/30/1993
                   06/30/1994
                   12/31/1995
                   06/30/1997
                   01/01/1999
                   }
     foreach date $leapdates {
          lappend leapsecs [ gpsTime $date ]
          }
     foreach sec [ lsort -integer $leapsecs ] {
          if { $time <= $sec } {
             set index [ lsearch $leapsecs $sec ]
             break;
             }
          ;## if we fall off the end of the list
          set index [ llength $leapsecs ]
          }
     set offset [ expr $offset + $index ]
     set utctime [ expr $time + $epochdiff - $offset ]
     return $utctime
 }