File Coverage

blib/lib/Time/TAI64.pm
Criterion Covered Total %
statement 74 95 77.8
branch 13 40 32.5
condition 3 11 27.2
subroutine 15 18 83.3
pod 9 9 100.0
total 114 173 65.9


line stmt bran cond sub pod time code
1             package Time::TAI64;
2             # vim: et ts=4
3              
4             =head1 NAME
5              
6             Time::TAI64 - Perl extension for converting TAI64 strings into standard unix timestamps.
7              
8             =head1 SYNOPSIS
9              
10             Generate TAI64 timestamps
11              
12             use Time::TAI64 qw/tai64n/;
13             use Time::HiRes qw/time/;
14              
15             $now = time; # High precision
16             printf "%s\n", unixtai64n($now);
17              
18             Print out human readable logs
19              
20             use Time::TAI64 qw/:tai64n/;
21              
22             open FILE, "/var/log/multilog/stats";
23             while(my $line = ) {
24             my($tai,$log) = split(' ',$line,2);
25             printf "%s %s",tai64nlocal($tai),$log;
26             }
27             close FILE;
28            
29             =head1 DESCRIPTION
30              
31             This is a package provides routines to convert TAI64 strings, like timestamps produced
32             by B, into values that can be processed by other perl functions to
33             display the timestamp in human-readable form and/or use in mathematical
34             computations.
35              
36             =cut
37              
38 4     4   142790 use strict;
  4         13  
  4         199  
39              
40 4     4   21 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION $FUZZ $AUTOLOAD);
  4         8  
  4         1062  
41              
42             #require 5.008;
43             require Exporter;
44              
45             @ISA = qw(Exporter);
46              
47             @EXPORT = ();
48             @EXPORT_OK = qw(
49             tai2unix
50             tai2strftime
51             tai64unix
52             tai64nunix
53             tai64naunix
54             tai64nlocal
55             unixtai64
56             unixtai64n
57             unixtai64na
58             );
59              
60             $EXPORT_TAGS{'tai'} = [
61             qw( tai2unix tai2strftime )
62             ];
63              
64             $EXPORT_TAGS{'tai64'} = [
65             @{ $EXPORT_TAGS{'tai'} },
66             qw( tai64unix unixtai64 )
67             ];
68              
69             $EXPORT_TAGS{'tai64n'} = [
70             @{ $EXPORT_TAGS{'tai'} },
71             qw( tai64nunix unixtai64n tai64nlocal )
72             ];
73              
74             $EXPORT_TAGS{'tai64na'} = [
75             @{ $EXPORT_TAGS{'tai'} },
76             qw( tai64naunix unixtai64na )
77             ];
78              
79             $EXPORT_TAGS{'all'} = [
80             @{ $EXPORT_TAGS{'tai'} },
81             @{ $EXPORT_TAGS{'tai64'} },
82             @{ $EXPORT_TAGS{'tai64n'} },
83             @{ $EXPORT_TAGS{'tai64na'} },
84             ];
85              
86 4     4   1015 use POSIX qw(strftime);
  4         7047  
  4         25  
87             $VERSION = '2.11';
88              
89             #-----------
90             #
91             ## Extra second difference... leap-seconds...
92             ##
93             #-----------
94             $FUZZ = 10;
95              
96             #-----------
97             #
98             ## Internal Routines
99             ##
100             #-----------
101              
102             #-----------
103             #
104             ## decode_tai64:
105             ## returns the number of seconds;
106             ##
107             #-----------
108             sub _decode_tai64 ($) {
109 3     3   6 my $tok = shift;
110 3         53 my $secs = 0;
111 3 50       13 if (substr($tok,0,9) eq '@40000000') {
112 3         9 $secs = hex(substr($tok,9,8)) - $FUZZ;
113             }
114 3         7 return $secs;
115             }
116              
117             #-----------
118             #
119             ## decode_tai64n:
120             ## returns a two element array containing the number
121             ## of seconds and nanoseconds respectively.
122             #-----------
123             sub _decode_tai64n ($) {
124 6     6   6 my $tok = shift;
125 6         8 my $secs = 0;
126 6         5 my $nano = 0;
127 6 50       17 if (substr($tok, 0, 9) eq '@40000000') {
128 6         14 $secs = hex(substr($tok,9,8)) - $FUZZ;
129 6         8 $nano = hex(substr($tok,17,8));
130             }
131 6         11 return ($secs,$nano);
132             }
133              
134             #-----------
135             #
136             ## decode_tai64na:
137             ## returns a three element array containing the number
138             ## of seconds, nanoseconds, and attoseconds respectively.
139             #-----------
140             sub _decode_tai64na ($) {
141 2     2   4 my $tok = shift;
142 2         3 my $secs = 0;
143 2         4 my $nano = 0;
144 2         3 my $atto = 0;
145 2 50       11 if (substr($tok, 0, 9) eq '@40000000') {
146 2         6 $secs = hex(substr($tok,9,8)) - $FUZZ;
147 2         5 $nano = hex(substr($tok,17,8));
148 2         5 $atto = hex(substr($tok,25,8));
149             }
150 2         27 return ($secs,$nano,$atto);
151             }
152              
153             #-----------
154             #
155             ## encode_tai64:
156             ## returns a 16 character string tai64 encoded
157             ## using the timestamp supplied, preceded by '@'.
158             #-----------
159             sub _encode_tai64 ($) {
160 16     16   21 my $s = shift; $s += $FUZZ;
  16         23  
161 16         68 my $t = '@40000000'. sprintf("%08x",$s);
162 16         51 return $t;
163             }
164              
165             #-----------
166             #
167             ## encode_tai64n:
168             ## returns a 24 character string tai64n encoded
169             ## using the timestamp supplied, preceded by '@'.
170             #-----------
171             sub _encode_tai64n ($$) {
172 12     12   17 my($s,$n) = @_;
173 12         25 my $t = _encode_tai64($s) . sprintf("%08x",$n);
174 12         48 return $t;
175             }
176              
177             #-----------
178             #
179             ## encode_tai64na:
180             ## returns a 32 character string tai64na encoded
181             ## using the timestamp supplied, preceded by '@'.
182             #-----------
183             sub _encode_tai64na ($$$) {
184 4     4   7 my($s,$n,$a) = @_;
185 4         10 my $t = _encode_tai64n($s,$n) . sprintf("%08x",$a);
186 4         17 return $t;
187             }
188              
189             =head1 EXPORTS
190              
191             In order to use any of these functions, they must be properly imported
192             by using any of the following tags to use related functions:
193              
194              
195             =over 4
196              
197             =item :tai
198              
199             Generic Functions
200              
201             =item tai2unix ( $tai_string )
202              
203             This method converts a tai64, tai64n, or tai64na string into a unix
204             timestamp. If successfull, this function returns an integer value
205             containing the number of seconds since Jan 1, 1970 as would perl's
206             C
207              
208             =cut
209              
210             sub tai2unix ($) {
211 0     0 1 0 my $tok = shift;
212 0 0       0 return int(tai64unix($tok)) if length($tok) == 17;
213 0 0       0 return int(tai64nunix($tok)) if length($tok) == 25;
214 0 0       0 return int(tai64naunix($tok)) if length($tok) == 33;
215 0         0 return 0;
216             }
217              
218             =item tai2strftime ( $tai64_string, $format_string )
219              
220             This method converts the tai64, tai64n, or tai64na string given as its
221             first parameter and, returns a formatted string of the converted I
222             as formatted by its second parameter using strftime conventions.
223              
224             If this second parameter is ommited, it defaults to "%a %b %d %H:%M:%S %Y"
225             which should print the timestamp as:
226             Mon Nov 1 12:00:00 2004
227              
228             =cut
229              
230             sub tai2strftime ($;$) {
231 0     0 1 0 my $tok = shift;
232 0   0     0 my $fmt = shift || "%a %b %d %H:%M:%S %Y";
233 0         0 my $secs = tai2unix($tok);
234 0 0       0 return ($secs == 0) ? '' : strftime($fmt,localtime($secs));
235             }
236              
237             =item :tai64
238              
239             TAI64 Functions as well as Generic Functions
240              
241             =item tai64unix ( $tai64_string )
242              
243             This method converts the tai64 string given as its only parameter and
244             if successfull, returns a value for I that is compatible
245             with the value returned from C
246              
247             =cut
248              
249             sub tai64unix ($) {
250 3     3 1 32 my $tok = shift;
251 3 50       12 return 0 unless (length($tok) == 17);
252 3         11 my $s = _decode_tai64($tok);
253 3         7 return $s;
254             }
255              
256             =item unixtai64 ( I )
257              
258             This method converts a unix timestamp into a TAI64 string.
259              
260             =cut
261              
262             sub unixtai64 ($) {
263 4     4 1 5982 my $secs = shift;
264 4 50       18 return '' if ($secs == 0);
265 4         17 return _encode_tai64(int($secs));
266             }
267              
268             =item :ta64n
269              
270             TAI64N Functions as well as Generic Functions
271              
272             =item tai64nunix ( $tai64n_string )
273              
274             This method converts the tai64n string given as its only parameter
275             and if successfull, returns a value for I that is compatible
276             with the value returned from C.
277              
278             =cut
279              
280             sub tai64nunix ($) {
281 6     6 1 14 my $tok = shift;
282 6 50       18 return 0 unless (length($tok) == 25);
283 6         15 my($s,$n) = _decode_tai64n($tok);
284 6         12 $s += ($n/1e9);
285 6         44 return $s;
286             }
287              
288             =item unixtai64n ( I )
289              
290             =item unixtai64n ( I , I )
291              
292             This methods returns a tai64n string using the parameters supplied by the user
293             making the following assumptions:
294              
295             =over 6
296              
297             =item *
298              
299             If I and I are given, these values are used to compute
300             the tai64n string. If I evaluates to more than 1 second, the value
301             of both I and I are reevaluated. Both I and I
302             are assumed to be integers, any fractional part is truncated.
303              
304             =item *
305              
306             If I is an integer, I is assumed to be 0.
307              
308             =item *
309              
310             If I is a C number, the integer part is used for the I
311             and the fractional part is converted to I.
312              
313             =back
314              
315             =cut
316              
317             sub unixtai64n ($;$) {
318 8     8 1 1606 my($secs,$nano) = @_;
319              
320 8 100       22 if (defined($nano)) {
321 1 50       5 if ($nano >= 1e9) {
322 0         0 $secs += int($nano / 1e9);
323 0         0 $nano = ($nano % 1e9);
324             }
325             } else {
326 7         16 $nano = ($secs - int($secs));
327 7         15 $nano *= 1e9;
328             }
329              
330 8 50 33     27 return '' if ($secs == 0 && $nano == 0);
331 8         23 return _encode_tai64n(int($secs),int($nano));
332             }
333              
334             =item tai64nlocal ( $tai64n_string )
335              
336             This utility returns a string representing the tai64n timestamp
337             converted to local time in ISO format: YYYY-MM-DD HH:MM:SS.SSSSSSSSS.
338              
339             The reason to include this funtion is to provide compatibility with the
340             command-line version included in B.
341              
342             =cut
343              
344             sub tai64nlocal ($) {
345 0     0 1 0 my $tok = shift;
346 0         0 my ($secs,$nano) = _decode_tai64n($tok);
347 0 0       0 my $x = ($secs ==0) ? '' :
348             strftime("%Y-%m-%d %H:%M:%S",localtime($secs)) .
349             sprintf(".%09d",$nano);
350 0         0 return($x);
351             }
352              
353             =item :tai64na
354              
355             TAI64NA Functions as well as Generic Functions
356              
357             =item tai64naunix ( $tai64na_string )
358              
359             This method converts the tai64na string given as its only parameter
360             and if successfull, returns a value for I that is compatible
361             with the value returned from C.
362              
363             =cut
364              
365             sub tai64naunix ($) {
366 2     2 1 11 my $tok = shift;
367 2 50       12 return 0 unless (length($tok) == 33);
368 2         8 my ($s,$n,$a) = _decode_tai64na($tok);
369 2         8 $n += ($a/1e9);
370 2         6 $s += ($n/1e9);
371 2         12 return $s;
372             }
373              
374             =item unixtai64na ( I )
375              
376             =item unixtai64na ( I , I , I )
377              
378             This method returns a tai64na string unsing the parameters supplied by the
379             user making the following assumptions:
380              
381             =over 6
382              
383             =item *
384              
385             If I, I and I are given, these values are
386             used to compute the tai64na string. If either I evaluates to
387             more than 1 second, or I evaluates to more than 1 nanosecond,
388             then I, I, and I are reevaluated. These
389             values are assumed to be integers, any fractional part is truncated.
390              
391             =item *
392              
393             If I is an integer, both I and I are
394             assumed to be 0.
395              
396             =item *
397              
398             If I is a C number, the integer part is used for the I
399             and the fractional part is converted to I amd I.
400              
401             =back
402              
403             =cut
404              
405             sub unixtai64na ($;$$) {
406 4     4 1 1151 my($secs,$nano,$atto) = @_;
407              
408 4 50       15 if (defined($nano)) {
409 0 0       0 if ($nano >= 1e9) {
410 0         0 $secs += int($nano / 1e9);
411 0         0 $nano = ($nano % 1e9);
412             }
413             } else {
414 4         14 $nano = ($secs - int($secs));
415 4         10 $nano *= 1e9;
416             }
417              
418 4 50       11 if (defined($atto)) {
419 0 0       0 if ($atto >= 1e9) {
420 0         0 $nano += int($atto / 1e9);
421 0         0 $atto = ($atto % 1e9);
422             }
423             } else {
424 4         6 $atto = ($nano - int($nano));
425 4         1388 $atto *= 1e9;
426             }
427              
428 4 0 33     18 return '' if ($secs == 0 and $nano == 0 and $atto == 0);
      33        
429 4         17 return _encode_tai64na(int($secs),int($nano),int($atto));
430             }
431              
432             #-----
433             # Make PERL Happy!!
434              
435             1;
436              
437             __END__