Phil Ehrens
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
}
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
}