-
-
27 Nov 2018 00:46:13 UTC
- Distribution: Time-TAI-Simple
- Module version: 1.15
- Source (raw)
- Browse (raw)
- Changes
- How to Contribute
- Issues
- Testers (532 / 0 / 3)
- Kwalitee
Bus factor: 1- 67.14% Coverage
- License: perl_5
- Perl: v5.10.0
- Activity
24 month- Tools
- Download (26.38KB)
- MetaCPAN Explorer
- Permissions
- Subscribe to distribution
- Permalinks
- This version
- Latest version
- NAME
- VERSION
- SYNOPSIS
- DESCRIPTION
- ABOUT TAI, TAI10, TAI35
- FURTHER READING
- MODULE-SCOPE VARIABLES
- PROCEDURAL INTERFACE
- OBJECT ORIENTED INTERFACE
- EXAMPLES
- TODO
- THREADS
- BUGS
- SEE ALSO
- AUTHOR
- COPYRIGHT AND LICENSE
NAME
Time::TAI::Simple - High resolution UNIX epoch time without leapseconds
VERSION
1.13
SYNOPSIS
use Time::TAI::Simple; # imports tai, tai10, and tai35 # simple and fast procedural interface: $seconds_since_epoch = tai(); $since_epoch_minus_ten = tai10(); # Probably what you want! $close_to_utc_time_for_now = tai35(); # You can likely skip the rest of this synopsis. # object-oriented interface: $tai = Time::TAI::Simple->new(); $since_epoch_minus_ten = $tai->time(); # download a more up-to-date leapsecond list, and recalculate time base: $tai->download_leapseconds() or die("cannot download leapseconds file"); $tai->load_leapseconds(); $tai->calculate_base(); $since_epoch_minus_ten = $tai->time(); # .. or simply download the leapsecond list as part of instantiation. # There is also an option for specifying where to put/find the list: $tai = Time::TAI::Simple->new( download_leapseconds => 1, leapseconds_pathname => '/etc/leap-seconds.list' ); $since_epoch_minus_ten = $tai->time(); # use mode parameter for TAI-00 time or TAI-35 time: $tai00 = Time::TAI::Simple->new(mode => 'tai'); $seconds_since_epoch = $tai00->time(); $tai35 = Time::TAI::Simple->new(mode => 'tai35'); $close_to_utc_time_for_now = $tai35->time(); # reduce processing overhead of instantiation, at the expense of # some precision, by turning off fine-tuning step: $tai = Time::TAI::Simple->new(fine_tune => 0); $nowish = $tai->time(); # accurate to a few milliseconds, not microseconds.
DESCRIPTION
The
Time::TAI::Simple
module provides a very simple way to obtain the number of seconds elapsed since the beginning of the UNIX epoch (January 1st, 1970).It differs from
Time::HiRes
in that it returns the actual number of elapsed seconds, unmodified by the leap seconds introduced by the IETF to make UTC time. These leap seconds can be problematic for automation software, as they effectively make the system clock stand still for one second every few years.D. J. Bernstein describes other problems with leapseconds-adjusted time in this short and sweet article: http://cr.yp.to/proto/utctai.html
Time::TAI::Simple
provides a monotonically increasing count of seconds, which means it will never stand still or leap forward or backward due to system clock adjustments (such as from NTP), and avoids leapseconds-related problems in general.This module differs from Time::TAI and Time::TAI::Now in a few ways:
* it is much simpler to use,
* it uses the same epoch as perl's
time
builtin andTime::HiRes
, not the IETF's 1900-based epoch,* it is a "best effort" implementation, accurate to a few microseconds,
* it depends on the local POSIX monotonic clock, not an external atomic clock.
ABOUT TAI, TAI10, TAI35
This module provides three modes of TAI time:
tai is, very simply, the actual number of elapsed seconds since the epoch.
tai10 provides TAI-10 seconds, which is how TAI time has traditionally been most commonly used, because when leapseconds were introduced in 1972, UTC was TAI minus 10 seconds.
It is the type of time provided by Arthur David Olson's popular time library, and by the TAI patch currently proposed to the standard zoneinfo implementation. When most people use TAI time, it is usually TAI-10.
tai35 provides TAI-35 seconds, which makes it exactly equal to the system clock time returned by
Time::HiRes::time()
before July 1 2015. As the IETF introduces more leapseconds, tai35 will be one second ahead of the system clock time with each introduction.This mode is provided for use-cases where compatability with other TAI time implementations is not required, and keeping the monotonically increasing time relatively close to the system clock time is desirable.
It was decided to provide three types of TAI time instead of allowing an arbitrary seconds offset parameter to make it easier for different systems with different users and different initialization times to pick compatible time modes.
FURTHER READING
The following reading is recommended:
http://cr.yp.to/proto/utctai.html
http://tycho.usno.navy.mil/leapsec.html
http://leapsecond.com/java/gpsclock.htm
MODULE-SCOPE VARIABLES
Time::TAI::Simple
defines a few externally-accessible variables so that users may customize their values to fit their needs, or to use them in other programming projects.@Time::TAI::Simple::LEAPSECOND_UNIX_PATHNAME_LIST
This list enumerates the pathnames where methods will look for the file listing IETF-defined leapseconds on UNIX systems. The list is traversed in order, and the first readable file will be used.
@Time::TAI::Simple::LEAPSECOND_WINDOWS_PATHNAME_LIST
This list enumerates the pathnames where methods will look for the file listing IETF-defined leapseconds on Windows systems. Like its UNIX counterpart, the list is traversed in order, and the first readable file will be used.
@Time::TAI::Simple::FALLBACK_LEAPSECONDS_LIST
If no leapseconds list file can be found,
Time::TAI::Simple
falls back on using this hard-coded list of IETF-defined leapseconds.This is dangerous because if the module is too old to include recently introduced leapseconds, TAI clock objects instantiated after the new leapsecond will be one second ahead of the desired TAI time.
This problem can be avoided by downloading the most recent leapsecond list file, either by invoking the
download_leapseconds
method or by manually downloading it from https://www.ietf.org/timezones/data/leap-seconds.list and putting it somewhereTime::TAI::Simple
will find it, such as/etc/leap-seconds.list
orC:\WINDOWS\leap-seconds.list
.@Time::TAI::Simple::FALLBACK_LEAPSECONDS_LIST
is a list of arrayrefs, each referenced array consisting of two elements, an IETF timestamp and a time delta.$Time::TAI::Simple::LEAPSECOND_IETF_DELTA
The IETF represents TAI time as the number of seconds elapsed since 1900-01-01, which is 2208960000 seconds greater than the number of seconds elapsed since 1971-01-01 (the UNIX epoch).
Time::TAI::Simple
keeps this value in$Time::TAI::Simple::LEAPSECOND_IETF_DELTA
and uses it internally to convert IETF times to UNIX epoch times.$Time::TAI::Simple::TAI_OR
$Time::TAI::Simple::TAI10_OR
$Time::TAI::Simple::TAI35_OR
When using
Time::TAI::Simple
's procedural interface, the first time thetai
,tai10
, andtai35
functions are invoked, they instantiateTime::TAI::Simple
with the appropriatemode
and assign it to these module-scope variables. Subsequent invocations re-use these instants.Before the first invocation, these variables are
undef
.PROCEDURAL INTERFACE
$seconds = tai()
$seconds = tai10()
$seconds = tai35()
These functions return a floating-point number of seconds elapsed since the epoch. They are equivalent to instantiating a
$tai
object with the corresponding mode and invoking itstime
method.EXAMPLE:
use Time::TAI::Simple; my $start_time = tai(); do_something(); my $time_delta = tai() - $start_time; print "doing something took $time_delta seconds\n";
OBJECT ORIENTED INTERFACE
INSTANTIATION
$tai = Time::TAI::Simple->new(%options)
Instantiates and returns a new
Time::TAI::Simple
object, hereafter referred to as$tai
. Returnsundef
on irrecoverable error.Without options, instantiation will:
* find and load the local copy of the leapseconds file into
$tai->{ls_ar}
(or load from@Time::TAI::Simple::FALLBACK_LEAPSECONDS_LIST
if no local file is found),* instantiate a
POSIX::RT::Clock
object referencing the POSIX monotonic clock and store it in$tai->{tm_or}
,* calculate a value for
$tai->{tm_base}
, which is the number of seconds to add to the POSIX monotonic clock time to derive the TAI-10 time, and* perform a "fine tuning" of this
tm_base
, based on repeatedly sampling the system clock and estimating the time difference between loading the value of the system clock and loading the value of the monotonic clock.This behavior can be changed by passing optional parameters:
mode => 'tai'
mode => 'tai10'
(default)mode => 'tai35'
-
Adjusts
$tai->{tm_base}
so that$tai->time()
returns the TAI, TAI-10, or TAI-35 time. download_leapseconds => 0
(default)download_leapseconds => 1
-
When set, causes
new
to try to http-download a new leapseconds list file before loading the leapseconds file.Time::TAI::Simple
maintains an internal list of URLs from which to download this file, and it goes down this list sequentially, stopping when the file has been successfully downloaded. This list may be amended via thedownload_urls
option.By default, no attempt is made to download a leapseconds file. This avoids the potential for very long http timeouts and clobbering any existing administrator-provided leapseconds file.
download_urls => [$url1, $url2, ...]
-
Prepends the provided list of URLs to the list of remove locations from which the leapseconds file is downloaded when the
download_leapseconds
option is set. Use this if your administrator maintains a leapseconds file for organizational use. leapseconds_pathname => '/home/tai/leap-seconds.list'
-
Sets the pathname of the leapseconds list file. This is the pathname to which the file will be stored when downloaded via the
download_leapseconds
option ordownload_leapseconds
method, and it is the pathname from which the file will be loaded by theload_leapseconds
method.By default,
Time::TAI::Simple
will look for this file in several locations, specified in@Time::TAI::Simple::LEAPSECOND_UNIX_PATHNAME_LIST
and@Time::TAI::Simple::LEAPSECOND_WINDOWS_PATHNAME_LIST
. The user may opt to replace the contents of these list variables as an alternative to using theleapseconds_pathname
option (for instance, before invoking thetai
,tai10
,tai35
functions). do_not_load_leapseconds => 0
(default)do_not_load_leapseconds => 1
-
When set, prevents loading the timestamp list from the timestamp list file or
@Time::TAI::Simple::FALLBACK_LEAPSECONDS_LIST
into$tai->{ls_ar}
.This only makes sense when setting the
base_time
option or when populating$tai->{ls_ar}
manually after instantiation and subsequently re-running thecalculate_base
method. base_time => $seconds
-
When set, circumvents the normal process of calculating
$tai->{tm_base}
and uses the provided value instead. This should be the number of seconds added to the time obtained from the POSIX monotonic clock to get the TAI time returned by thetime
method. fine_tune => 0
fine_tune => 1
(default)-
When set (the default), adjusts
tm_base
, based on repeatedly sampling the system clock and estimating the time difference between loading the value of the system clock and loading the value of the monotonic clock. This can add measurable overhead to thecalculate_base
method -- about 35 microseconds on 2013-era hardware, accounting for about 3/4 of instantiation time.When false, skips this fine-tuning, diminishing the precision of the
time
method from a few microseconds to a few milliseconds.
OBJECT ATTRIBUTES
The following attributes of a
Time::TAI::Simple
instance are public. Changes to some attributes will do nothing until theload_leapseconds
and/orcalculate_base
methods are re-run.opt_hr
(hash reference)Refers to the parameters passed to
new
.tm_or
(POSIX::RT::Clock
object reference)Refers to the POSIX standard monotonic clock interface used by
time
to calculate the current TAI time (along withtm_base
).ls_ar
(array reference)Refers to the IETF leapseconds list. Its elements are arrayrefs to
[UTC epoch, seconds]
tuples, and they are ordered byUTC epoch
.ls_tm
(integer)Value is the file modification time of the IETF leapseconds list file, if
ls_ar
was loaded from a file, or the timels_ar
was loaded from@Time::TAI::Simple::FALLBACK_LEAPSECONDS_LIST
, or0
if never loaded.dl_tm
(floating point)Value is the system clock time the
download_leapseconds
method last attempted to download the IETF leapseconds list file, or0.0
if never attempted.tm_base
(floating point)Value is the difference, in seconds, between the POSIX monotonic clock time and the beginning of the epoch. It is used by
time
to calculate the current TAI time. It is initialized by thecalculate_base
method, and is0.0
if never initialized.mode
(string)Exactly one of "tai", "tai10", "tai35", indicating the
mode
with which the object was instantiated, and thus the type of TAI time returned bytime
. Its default value is "tai10".OBJECT METHODS
$tai->time()
Returns a floating-point number of seconds elapsed since the epoch.
$tai->calculate_base(%options)
calculate_base
uses the POSIX monotonic clock, the leapsecond list, and the system clock to calculate$tai->{tm_base}
, which is the difference between the POSIX monotonic clock and the TAI time. This difference is used bytime
to calculate the TAI time from the POSIX monotonic clock time.This method is normally only called by
new
, but can be called explicitly to recalculate$tai->{tm_base}
if one of its dependencies is changed.It takes some of the same options as
new
, and they have the same effect:It has no return value.
$tai->load_leapseconds(%options)
load_leapseconds
finds the local copy of the IETF leapseconds list file, reads it, and populates the object'sls_ar
attribute. If it cannot find any file it uses the values in@Time::TAI::Simple::FALLBACK_LEAPSECONDS_LIST
instead.This method, too, is normally only called by
new
, but can be called explicitly as needed to re-initialize$tai->{ls_ar}
.For now it takes only one option, which has the same effect as passing it to <new>:
It returns 1 on success, 0 on failure.
$tai->download_leapseconds(%options)
download_leapseconds
tries to download the IETF leapseconds file so it can be loaded by theload_leapseconds
method. It iterates through a list of URLs (any provided via theleapseconds_pathname
parameter first, and an internal list after) and saves the first file it is able to download to either the pathname specified by theleapseconds_pathname
parameter or a sensible location appropriate to the operating system type.This method can be called by
new
, but only when thedownload_leapseconds
parameter is passed tonew
with a value which resolves totrue
.It takes two options, which have the same effects as passing them to
new
:It returns 1 on success, 0 on failure.
EXAMPLES
Some simple scripts wrapping this module can be found in
bin
:tai-download-leapseconds
-
Attempts to download the IETF leapseconds file. Will write the pathname of the downloaded file to STDOUT and exit
0
, or write an error to STDERR and exit1
. Pass it the-h
option to see its options.On UNIX hosts, it is recommended that a symlink be made in
/etc/cron.monthly
to/usr/local/bin/tai-download-leapseconds
so that it updates the system's leapseconds file as updates become available. tai
-
Prints the current time. Shows TAI-10 by default. Pass it the
-h
option to see its options.
TODO
Needs more unit tests.
Does
new
need changes to be made thread-safe?Test
_fine_tune
under other versions of perl, find out if the constant factor needs to be version-specific.Do something smart with
ls_tm
anddl_tm
, like an optional feature which tries to refresh the leapsecond list periodically when stale.THREADS
Not tested, but its dependencies are purportedly thread-safe, and I think the
time
method, and thetai
,tai10
, andtai35
functions should be thread-safe. Not so sure aboutnew
.BUGS
Probably. In particular, the Windows compatability code is not tested, nor do I have access to a Windows environment in which to test it. I doubt that the paths in
@Time::TAI::Simple::LEAPSECOND_WINDOWS_PATHNAME_LIST
are sufficient for all environments.Also, some corners were cut in
bin/tai
, particularly in the--iso
code, which means its output will not be precisely correct for locales with timezones whose time offsets are not whole hours.Please report relevant bugs to <ttk[at]ciar[dot]org>.
Bugfix patches are also welcome.
SEE ALSO
DateTime has a
subtract_datetime_absolute
method which will give the actual difference between two times, just like taking the difference between two TAI times.If you are a scientist, you might want Time::TAI or Time::TAI::Now.
An alternative approach to solving the problem of leapsecond-induced bugs is Time::UTC_SLS, "UTC with Smoothed Leap Seconds".
AUTHOR
TTK Ciar, <ttk[at]ciar[dot]org>
COPYRIGHT AND LICENSE
Copyright 2014-2017 by TTK Ciar
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Module Install Instructions
To install Time::TAI::Simple, copy and paste the appropriate command in to your terminal.
cpanm Time::TAI::Simple
perl -MCPAN -e shell install Time::TAI::Simple
For more information on module installation, please visit the detailed CPAN module installation guide.