]> err.no Git - moreutils/blob - ts
Update name one more place
[moreutils] / ts
1 #!/usr/bin/perl
2
3 =head1 NAME
4
5 ts - timestamp input
6
7 =head1 SYNOPSIS
8
9 ts [-r] [-i] [format]
10
11 =head1 DESCRIPTION
12
13 ts adds a timestamp to the beginning of each line of input.
14
15 The optional format parameter controls how the timestamp is formatted,
16 as used by L<strftime(3)>. The default format is "%b %d %H:%M:%S". In
17 addition to the regular strftime conversion specifications, "%.S" and "%.s"
18 are like "%S" and "%s", but provide subsecond resolution
19 (ie, "30.00001" and "1301682593.00001").
20
21 If the -r switch is passed, it instead converts existing timestamps in
22 the input to relative times, such as "15m5s ago". Many common timestamp
23 formats are supported. Note that the Time::Duration and Date::Parse perl
24 modules are required for this mode to work. Currently, converting localized
25 dates is not supported.
26
27 If both -r and a format is passed, the existing timestamps are
28 converted to the specified format.
29
30 If the -i switch is passed, ts timestamps incrementally instead.  Every
31 timestamp will be the time elapsed since the last timestamp.
32 The default format changes to "%H:%M:%S", and "%.S" and "%.s" can be used
33 as well.
34
35 =head1 ENVIRONMENT
36
37 The standard TZ environment variable controls what time zone dates
38 are assumed to be in, if a timezone is not specified as part of the date.
39
40 =head1 AUTHOR
41
42 Copyright 2006 by Joey Hess <joey@kitenet.net>
43
44 Licensed under the GNU GPL.
45
46 =cut
47
48 use warnings;
49 use strict;
50 use POSIX q{strftime};
51
52 $|=1;
53
54 my $rel=0;
55 my $inc=0;
56 use Getopt::Long;
57 GetOptions("r" => \$rel, "i" => \$inc) || die "usage: ts [-r] [-i] [format]\n";
58
59 if ($rel) {
60         eval q{
61                 use Date::Parse;
62                 use Time::Duration;
63         };
64         die $@ if $@;
65 }
66
67 my $use_format=@ARGV;
68 my $format="%b %d %H:%M:%S";
69 if ($inc) {
70         $format="%H:%M:%S";
71 }
72 $format=shift if @ARGV;
73
74 # For subsecond resolution, Time::HiRes is needed.
75 my $hires=0;
76 if ($format=~/\%\.[Ss]/) {
77         require Time::HiRes;
78         $hires=1;
79 }
80
81 my $lastseconds = 0;
82 my $lastmicroseconds = 0;
83
84 if ($hires) {
85         ($lastseconds, $lastmicroseconds) = Time::HiRes::gettimeofday();
86 } else {
87         $lastseconds = time;
88 }
89
90
91 while (<>) {
92         if (! $rel) {
93                 if ($hires) {
94                         my $f=$format;
95                         my ($seconds, $microseconds) = Time::HiRes::gettimeofday();
96                         if ($inc) {
97                                 my $deltaseconds = $seconds - $lastseconds;
98                                 my $deltamicroseconds = $microseconds - $lastmicroseconds;
99                                 if ($deltamicroseconds < 0) {
100                                         $deltaseconds -= 1;
101                                         $deltamicroseconds += 1000000;
102                                 }
103                                 $lastseconds = $seconds;
104                                 $lastmicroseconds = $microseconds;
105                                 $seconds = $deltaseconds;
106                                 $microseconds = $deltamicroseconds;
107                         }
108                         my $s=sprintf("%06i", $microseconds);
109                         $f=~s/\%\.([Ss])/%$1.$s/g;
110                         if (!$inc) {
111                                 print strftime($f, localtime($seconds));
112                         } else {
113                                 print strftime($f, gmtime($seconds));
114                         }
115                 }
116                 else {
117                         if ($inc) {
118                                 my $seconds = time;
119                                 my $deltaseconds = $seconds - $lastseconds;
120                                 $lastseconds = $seconds;
121                                 print strftime($format, gmtime($deltaseconds));
122                         } else {
123                                 print strftime($format, localtime);
124                         }
125                 }
126                 print " ".$_;
127         }
128         else {
129                 s{\b(
130                         \d\d[-\s\/]\w\w\w       # 21 dec 17:05
131                                 (?:\/\d\d+)?    # 21 dec/93 17:05
132                                 [\s:]\d\d:\d\d  #       (time part of above)
133                                 (?::\d\d)?      #       (optional seconds)
134                                 (?:\s+[+-]\d\d\d\d)? #  (optional timezone)
135                         |
136                         \w{3}\s+\d\d\s+\d\d:\d\d:\d\d # syslog form
137                         |
138                         \d\d\d[-:]\d\d[-:]\d\dT\d\d:\d\d:\d\d.\d+ # ISO-8601
139                         |
140                         (?:\w\w\w,?\s+)?        #       (optional Day)
141                         \d+\s+\w\w\w\s+\d\d+\s+\d\d:\d\d:\d\d
142                                                 # 16 Jun 94 07:29:35
143                                 (?:\s+\w\w\w|\s[+-]\d\d\d\d)?
144                                                 #       (optional timezone)
145                         |
146                         \w\w\w\s+\w\w\w\s+\d\d\s+\d\d:\d\d
147                                                 # lastlog format
148                   )\b
149                 }{
150                         $use_format
151                                 ? strftime($format, localtime(str2time($1)))
152                                 : concise(ago(time - str2time($1), 2))
153                 }exg;
154
155                 print $_;
156         }
157 }