line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=for gpg |
2
|
|
|
|
|
|
|
-----BEGIN PGP SIGNED MESSAGE----- |
3
|
|
|
|
|
|
|
Hash: SHA1 |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=encoding utf8 |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 NAME |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Time::Format - Easy-to-use date/time formatting. |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=head1 VERSION |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
This is version 1.16 of Time::Format, February 19, 2020. |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=cut |
16
|
|
|
|
|
|
|
|
17
|
25
|
|
|
25
|
|
3584791
|
use strict; |
|
25
|
|
|
|
|
195
|
|
|
25
|
|
|
|
|
16761
|
|
18
|
|
|
|
|
|
|
package Time::Format; |
19
|
|
|
|
|
|
|
$Time::Format::VERSION = '1.16'; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
# This module claims to be compatible with the following versions |
22
|
|
|
|
|
|
|
# of Time::Format_XS. |
23
|
|
|
|
|
|
|
%Time::Format::XSCOMPAT = map {$_ => 1} qw(1.01 1.02 1.03); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub _croak |
26
|
|
|
|
|
|
|
{ |
27
|
2
|
|
|
2
|
|
12
|
require Carp; |
28
|
2
|
|
|
|
|
250
|
goto &Carp::croak; |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Store the file offset of the __DATA__ region. |
32
|
|
|
|
|
|
|
my $data_pos = tell DATA; |
33
|
|
|
|
|
|
|
close DATA; # so we don't hold a lock on this file. |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Here we go through a bunch of tests to decide whether we can use the |
36
|
|
|
|
|
|
|
# XS module, or if we need to load and compile the perl-only |
37
|
|
|
|
|
|
|
# subroutines (which are stored in __DATA__). |
38
|
|
|
|
|
|
|
my $load_perlonly = 0; |
39
|
|
|
|
|
|
|
$load_perlonly = 1 if defined $Time::Format::NOXS && $Time::Format::NOXS; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
if (!$load_perlonly) |
42
|
|
|
|
|
|
|
{ |
43
|
|
|
|
|
|
|
# Check whether the optional XS module is installed. |
44
|
|
|
|
|
|
|
eval { require Time::Format_XS }; |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
if ($@ || !defined $Time::Format_XS::VERSION) |
47
|
|
|
|
|
|
|
{ |
48
|
|
|
|
|
|
|
$load_perlonly = 1; |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
else |
51
|
|
|
|
|
|
|
{ |
52
|
|
|
|
|
|
|
# Check that we're compatible with them (backwards compatibility) |
53
|
|
|
|
|
|
|
# or they're compatible with us (forwards compatibility). |
54
|
|
|
|
|
|
|
unless ($Time::Format::XSCOMPAT{$Time::Format_XS::VERSION} |
55
|
|
|
|
|
|
|
|| $Time::Format_XS::PLCOMPAT{$Time::Format::VERSION}) |
56
|
|
|
|
|
|
|
{ |
57
|
|
|
|
|
|
|
warn "Your Time::Format_XS version ($Time::Format_XS::VERSION) " |
58
|
|
|
|
|
|
|
. "is not compatible with Time::Format version ($Time::Format::VERSION).\n" |
59
|
|
|
|
|
|
|
. "Using Perl-only functions.\n"; |
60
|
|
|
|
|
|
|
$load_perlonly = 1; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# Okay to use the XS version? Great. Wrap it. |
65
|
|
|
|
|
|
|
if (!$load_perlonly) |
66
|
|
|
|
|
|
|
{ |
67
|
|
|
|
|
|
|
*time_format = sub { |
68
|
|
|
|
|
|
|
my ($fmt, $t) = @_; |
69
|
|
|
|
|
|
|
$t = 'time' if not defined $t; |
70
|
|
|
|
|
|
|
@_ = ($fmt, $t); |
71
|
|
|
|
|
|
|
goto &Time::Format_XS::time_format; |
72
|
|
|
|
|
|
|
}; |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
if ($load_perlonly) |
77
|
|
|
|
|
|
|
{ |
78
|
|
|
|
|
|
|
# Time::Format_XS not installed, or version mismatch, or NOXS was set. |
79
|
|
|
|
|
|
|
# The perl routines will need to be loaded. |
80
|
|
|
|
|
|
|
# But let's defer this until someone actually calls time_format(). |
81
|
|
|
|
|
|
|
*time_format = sub |
82
|
|
|
|
|
|
|
{ |
83
|
309
|
100
|
|
309
|
|
610433
|
if (not defined &time_format_perlonly) |
84
|
|
|
|
|
|
|
{ |
85
|
12
|
50
|
|
|
|
560
|
open DATA, '<', __FILE__ |
86
|
|
|
|
|
|
|
or die "Can't access code in " . __FILE__ . ": $!\n";; |
87
|
|
|
|
|
|
|
|
88
|
12
|
|
|
|
|
148
|
flock DATA, 1; # LOCK_SH |
89
|
12
|
|
|
|
|
112
|
seek DATA, $data_pos, 0; |
90
|
12
|
|
|
|
|
96
|
local $^W = 0; # disable warning about subroutines redefined |
91
|
12
|
|
|
|
|
60
|
local $/ = undef; # slurp |
92
|
12
|
|
|
|
|
1179
|
my $code = <DATA>; |
93
|
12
|
|
|
|
|
111
|
flock DATA, 8; # LOCK_UN |
94
|
12
|
|
|
|
|
129
|
close DATA; |
95
|
|
|
|
|
|
|
|
96
|
12
|
|
|
|
|
3398
|
eval $code; |
97
|
12
|
50
|
|
|
|
51643
|
die if $@; |
98
|
|
|
|
|
|
|
} |
99
|
309
|
|
|
|
|
850
|
*time_format = \&time_format_perlonly; |
100
|
309
|
|
|
|
|
1174
|
goto &time_format_perlonly; |
101
|
|
|
|
|
|
|
}; |
102
|
|
|
|
|
|
|
undef $Time::Format_XS::VERSION; # Indicate that XS version is not available. |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
my @EXPORT = qw(%time time_format); |
107
|
|
|
|
|
|
|
my @EXPORT_OK = qw(%time %strftime %manip time_format time_strftime time_manip); |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# We don't need any of Exporter's fancy features, so it's quicker to |
110
|
|
|
|
|
|
|
# do the import ourselves. |
111
|
|
|
|
|
|
|
sub import |
112
|
|
|
|
|
|
|
{ |
113
|
25
|
|
|
25
|
|
195
|
my $pkg = shift; |
114
|
25
|
|
|
|
|
97
|
my ($cpkg,$file,$line) = caller; |
115
|
25
|
|
|
|
|
57
|
my @symbols; |
116
|
25
|
100
|
|
|
|
86
|
if (@_) |
117
|
|
|
|
|
|
|
{ |
118
|
19
|
100
|
|
|
|
81
|
if (grep $_ eq ':all', @_) |
119
|
|
|
|
|
|
|
{ |
120
|
5
|
|
|
|
|
19
|
@symbols = (@EXPORT, @EXPORT_OK, grep $_ ne ':all', @_); |
121
|
|
|
|
|
|
|
} else { |
122
|
14
|
|
|
|
|
40
|
@symbols = @_; |
123
|
|
|
|
|
|
|
} |
124
|
19
|
|
|
|
|
31
|
my %seen; |
125
|
19
|
|
|
|
|
123
|
@symbols = grep !$seen{$_}++, @symbols; |
126
|
|
|
|
|
|
|
} else { |
127
|
6
|
|
|
|
|
17
|
@symbols = @EXPORT; |
128
|
|
|
|
|
|
|
} |
129
|
25
|
|
|
|
|
48
|
my %ok; |
130
|
25
|
|
|
|
|
115
|
@ok{@EXPORT_OK,@EXPORT} = (); |
131
|
25
|
|
|
|
|
78
|
my @badsym = grep !exists $ok{$_}, @symbols; |
132
|
25
|
50
|
|
|
|
76
|
if (@badsym) |
133
|
|
|
|
|
|
|
{ |
134
|
0
|
0
|
|
|
|
0
|
my $s = @badsym>1? 's' : ''; |
135
|
0
|
0
|
|
|
|
0
|
my $v = @badsym>1? 'are' : 'is'; |
136
|
0
|
|
|
|
|
0
|
_croak ("The symbol$s ", join(', ', @badsym), " $v not exported by Time::Format at $file line $line.\n"); |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
25
|
|
|
25
|
|
196
|
no strict 'refs'; |
|
25
|
|
|
|
|
52
|
|
|
25
|
|
|
|
|
5555
|
|
140
|
25
|
|
|
|
|
60
|
foreach my $sym (@symbols) |
141
|
|
|
|
|
|
|
{ |
142
|
66
|
|
|
|
|
304
|
$sym =~ s/^([\$\&\@\%])?//; |
143
|
66
|
|
100
|
|
|
329
|
my $pfx = $1 || '&'; |
144
|
66
|
|
|
|
|
178
|
my $calsym = $cpkg . '::' . $sym; |
145
|
66
|
|
|
|
|
133
|
my $mysym = $pkg . '::' . $sym; |
146
|
66
|
100
|
|
|
|
198
|
if ($pfx eq '%') |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
147
|
|
|
|
|
|
|
{ |
148
|
35
|
|
|
|
|
354
|
*$calsym = \%$mysym; |
149
|
|
|
|
|
|
|
} elsif ($pfx eq '@') { |
150
|
0
|
|
|
|
|
0
|
*$calsym = \@$mysym; |
151
|
|
|
|
|
|
|
} elsif ($pfx eq '$') { |
152
|
0
|
|
|
|
|
0
|
*$calsym = \$$mysym; |
153
|
|
|
|
|
|
|
} else { |
154
|
31
|
|
|
|
|
3756
|
*$calsym = \&$mysym; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# Simple tied-hash implementation. |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# Each hash is simply tied to a subroutine reference. "Fetching" a |
162
|
|
|
|
|
|
|
# value from the hash invokes the subroutine. If a hash (tied or |
163
|
|
|
|
|
|
|
# otherwise) has multiple comma-separated values but the leading |
164
|
|
|
|
|
|
|
# character is a $, then Perl joins the values with $;. This makes it |
165
|
|
|
|
|
|
|
# easy to simulate function calls with tied hashes -- we just split on |
166
|
|
|
|
|
|
|
# $; to recreate the argument list. |
167
|
|
|
|
|
|
|
# |
168
|
|
|
|
|
|
|
# 2005/12/01: We must ensure that time_format gets two arguments, since |
169
|
|
|
|
|
|
|
# the XS version cannot handle variable argument lists. |
170
|
|
|
|
|
|
|
|
171
|
25
|
|
|
25
|
|
199
|
use vars qw(%time %strftime %manip); |
|
25
|
|
|
|
|
52
|
|
|
25
|
|
|
|
|
6283
|
|
172
|
|
|
|
|
|
|
tie %time, 'Time::Format', \&time_format; |
173
|
|
|
|
|
|
|
tie %strftime, 'Time::Format', \&time_strftime; |
174
|
|
|
|
|
|
|
tie %manip, 'Time::Format', \&time_manip; |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub TIEHASH |
177
|
|
|
|
|
|
|
{ |
178
|
75
|
|
|
75
|
|
134
|
my $class = shift; |
179
|
75
|
|
50
|
|
|
170
|
my $func = shift || die "Bad call to $class\::TIEHASH"; |
180
|
75
|
|
|
|
|
184
|
bless $func, $class; |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
sub FETCH |
184
|
|
|
|
|
|
|
{ |
185
|
272
|
|
|
272
|
|
4081310
|
my $self = shift; |
186
|
272
|
|
|
|
|
522
|
my $key = shift; |
187
|
272
|
|
|
|
|
4162
|
my @args = split $;, $key, -1; |
188
|
272
|
|
|
|
|
1083
|
$self->(@args); |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
25
|
|
|
|
|
130
|
use subs qw( |
192
|
25
|
|
|
25
|
|
13775
|
STORE EXISTS CLEAR FIRSTKEY NEXTKEY ); |
|
25
|
|
|
|
|
723
|
|
193
|
|
|
|
|
|
|
*STORE = *EXISTS = *CLEAR = *FIRSTKEY = *NEXTKEY = sub |
194
|
|
|
|
|
|
|
{ |
195
|
2
|
|
|
2
|
|
1000
|
my ($pkg,$file,$line) = caller; |
196
|
2
|
|
|
|
|
10
|
_croak "Invalid call to Time::Format internal function at $file line $line."; |
197
|
|
|
|
|
|
|
}; |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# Module finder -- do we have the specified module available? |
201
|
|
|
|
|
|
|
{ |
202
|
|
|
|
|
|
|
my %have; |
203
|
|
|
|
|
|
|
sub _have |
204
|
|
|
|
|
|
|
{ |
205
|
473
|
|
50
|
473
|
|
22946
|
my $module = shift || return; |
206
|
473
|
100
|
|
|
|
1619
|
return $have{$module} if exists $have{$module}; |
207
|
|
|
|
|
|
|
|
208
|
20
|
|
|
|
|
66
|
my $incmod = $module; |
209
|
20
|
|
|
|
|
139
|
$incmod =~ s!::!/!g; |
210
|
20
|
100
|
|
|
|
171
|
return $have{$module} = 1 if exists $INC{"$incmod.pm"}; |
211
|
|
|
|
|
|
|
|
212
|
6
|
|
|
|
|
25
|
$@ = ''; |
213
|
6
|
|
|
|
|
488
|
eval "require $module"; |
214
|
6
|
50
|
|
|
|
475226
|
return $have{$module} = $@? 0 : 1; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# POSIX strftime, for people who like those weird % formats. |
220
|
|
|
|
|
|
|
sub time_strftime |
221
|
|
|
|
|
|
|
{ |
222
|
|
|
|
|
|
|
# Check if POSIX is available (why wouldn't it be?) |
223
|
15
|
50
|
|
15
|
1
|
705
|
return 'NO_POSIX' unless _have('POSIX'); |
224
|
|
|
|
|
|
|
|
225
|
15
|
|
|
|
|
33
|
my $fmt = shift; |
226
|
15
|
|
|
|
|
38
|
my @time; |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# If more than one arg, assume they're doing the whole arg list |
229
|
15
|
100
|
|
|
|
50
|
if (@_ > 1) |
230
|
|
|
|
|
|
|
{ |
231
|
1
|
|
|
|
|
4
|
@time = @_; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
else # use unix time (current or passed) |
234
|
|
|
|
|
|
|
{ |
235
|
14
|
100
|
|
|
|
51
|
my $time = @_? shift : time; |
236
|
14
|
|
|
|
|
366
|
@time = localtime $time; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
15
|
|
|
|
|
551
|
return POSIX::strftime($fmt, @time); |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
# Date::Manip interface |
244
|
|
|
|
|
|
|
sub time_manip |
245
|
|
|
|
|
|
|
{ |
246
|
14
|
50
|
|
14
|
1
|
59556
|
return "NO_DATEMANIP" unless _have('Date::Manip'); |
247
|
|
|
|
|
|
|
|
248
|
14
|
|
|
|
|
34
|
my $fmt = shift; |
249
|
14
|
100
|
|
|
|
39
|
my $time = @_? shift : 'now'; |
250
|
|
|
|
|
|
|
|
251
|
14
|
100
|
|
|
|
66
|
$time = $1 if $time =~ /^\s* (epoch \s+ \d+)/x; |
252
|
|
|
|
|
|
|
|
253
|
14
|
|
|
|
|
57
|
return Date::Manip::UnixDate($time, $fmt); |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
1; |
258
|
|
|
|
|
|
|
__DATA__ |
259
|
|
|
|
|
|
|
# The following is only compiled if Time::Format_XS is not available. |
260
|
|
|
|
|
|
|
#line 248 "Time/Format.pm" |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
use Time::Local; |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# Default names for months, days |
265
|
|
|
|
|
|
|
my %english_names = |
266
|
|
|
|
|
|
|
( |
267
|
|
|
|
|
|
|
Month => [qw[January February March April May June July August September October November December]], |
268
|
|
|
|
|
|
|
Weekday => [qw[Sunday Monday Tuesday Wednesday Thursday Friday Saturday]], |
269
|
|
|
|
|
|
|
th => [qw[/th st nd rd th th th th th th th th th th th th th th th th th st nd rd th th th th th th th st]], |
270
|
|
|
|
|
|
|
); |
271
|
|
|
|
|
|
|
my %names; |
272
|
|
|
|
|
|
|
my $locale; |
273
|
|
|
|
|
|
|
my %loc_cache; # Cache for remembering times that have already been parsed out. |
274
|
|
|
|
|
|
|
my $cache_size=0; # Number of keys in %loc_cache |
275
|
|
|
|
|
|
|
my $cache_size_limit = 1024; # Max number of times to cache |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# Internal function to initialize locale info. |
278
|
|
|
|
|
|
|
# Returns true if the locale changed. |
279
|
|
|
|
|
|
|
sub setup_locale |
280
|
|
|
|
|
|
|
{ |
281
|
|
|
|
|
|
|
# Do nothing if locale has not changed since %names was set up. |
282
|
|
|
|
|
|
|
my $locale_in_use; |
283
|
|
|
|
|
|
|
$locale_in_use = POSIX::setlocale(POSIX::LC_TIME()) if _have('POSIX'); |
284
|
|
|
|
|
|
|
$locale_in_use = '' if !defined $locale_in_use; |
285
|
|
|
|
|
|
|
return if defined $locale && $locale eq $locale_in_use; |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
my (@Month, @Mon, @Weekday, @Day); |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
unless (eval { |
290
|
|
|
|
|
|
|
require I18N::Langinfo; |
291
|
|
|
|
|
|
|
I18N::Langinfo->import(qw(langinfo)); |
292
|
|
|
|
|
|
|
@Month = map langinfo($_), I18N::Langinfo::MON_1(), I18N::Langinfo::MON_2(), I18N::Langinfo::MON_3(), |
293
|
|
|
|
|
|
|
I18N::Langinfo::MON_4(), I18N::Langinfo::MON_5(), I18N::Langinfo::MON_6(), |
294
|
|
|
|
|
|
|
I18N::Langinfo::MON_7(), I18N::Langinfo::MON_8(), I18N::Langinfo::MON_9(), |
295
|
|
|
|
|
|
|
I18N::Langinfo::MON_10(), I18N::Langinfo::MON_11(), I18N::Langinfo::MON_12(); |
296
|
|
|
|
|
|
|
@Mon = map langinfo($_), I18N::Langinfo::ABMON_1(), I18N::Langinfo::ABMON_2(), I18N::Langinfo::ABMON_3(), |
297
|
|
|
|
|
|
|
I18N::Langinfo::ABMON_4(), I18N::Langinfo::ABMON_5(), I18N::Langinfo::ABMON_6(), |
298
|
|
|
|
|
|
|
I18N::Langinfo::ABMON_7(), I18N::Langinfo::ABMON_8(), I18N::Langinfo::ABMON_9(), |
299
|
|
|
|
|
|
|
I18N::Langinfo::ABMON_10(), I18N::Langinfo::ABMON_11(), I18N::Langinfo::ABMON_12(); |
300
|
|
|
|
|
|
|
@Weekday = map langinfo($_), I18N::Langinfo::DAY_1(), I18N::Langinfo::DAY_2(), I18N::Langinfo::DAY_3(), |
301
|
|
|
|
|
|
|
I18N::Langinfo::DAY_4(), I18N::Langinfo::DAY_5(), I18N::Langinfo::DAY_6(), I18N::Langinfo::DAY_7(); |
302
|
|
|
|
|
|
|
@Day = map langinfo($_), I18N::Langinfo::ABDAY_1(), I18N::Langinfo::ABDAY_2(), I18N::Langinfo::ABDAY_3(), |
303
|
|
|
|
|
|
|
I18N::Langinfo::ABDAY_4(), I18N::Langinfo::ABDAY_5(), I18N::Langinfo::ABDAY_6(), I18N::Langinfo::ABDAY_7(); |
304
|
|
|
|
|
|
|
1; |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
) |
307
|
|
|
|
|
|
|
{ # Internationalization didn't work for some reason; go with English. |
308
|
|
|
|
|
|
|
@Month = @{ $english_names{Month} }; |
309
|
|
|
|
|
|
|
@Weekday = @{ $english_names{Weekday} }; |
310
|
|
|
|
|
|
|
@Mon = map substr($_,0,3), @Month; |
311
|
|
|
|
|
|
|
@Day = map substr($_,0,3), @Weekday; |
312
|
|
|
|
|
|
|
$@ = ''; |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# Store in %names, setting proper case |
316
|
|
|
|
|
|
|
$names{Month} = \@Month; |
317
|
|
|
|
|
|
|
$names{Weekday} = \@Weekday; |
318
|
|
|
|
|
|
|
$names{Mon} = \@Mon; |
319
|
|
|
|
|
|
|
$names{Day} = \@Day; |
320
|
|
|
|
|
|
|
$names{th} = $english_names{th}; |
321
|
|
|
|
|
|
|
$names{TH} = [map uc, @{$names{th}}]; |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
foreach my $name (keys %names) |
324
|
|
|
|
|
|
|
{ |
325
|
|
|
|
|
|
|
my $aref = $names{$name}; # locale-native case |
326
|
|
|
|
|
|
|
$names{uc $name} = [map uc, @$aref]; # upper=case |
327
|
|
|
|
|
|
|
$names{lc $name} = [map lc, @$aref]; # lower-case |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
%loc_cache = (); # locale changes are rare. Clear out cache. |
331
|
|
|
|
|
|
|
$cache_size = 0; |
332
|
|
|
|
|
|
|
$locale = $locale_in_use; |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
return 1; |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
# Types of time values we can handle: |
338
|
|
|
|
|
|
|
my $NUMERIC_TIME = \&decode_epoch; |
339
|
|
|
|
|
|
|
my $DATETIME_OBJECT = \&decode_DateTime_object; |
340
|
|
|
|
|
|
|
my $DATETIME_STRING = \&decode_DateTime_string; |
341
|
|
|
|
|
|
|
# my $DATEMANIP_STRING = \&decode_DateManip_string; |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
# What kind of argument was passed to time_format? |
344
|
|
|
|
|
|
|
# Returns (type, time, cache_time_key, milliseconds, microseconds) |
345
|
|
|
|
|
|
|
sub _classify_time |
346
|
|
|
|
|
|
|
{ |
347
|
|
|
|
|
|
|
my $timeval = shift; |
348
|
|
|
|
|
|
|
$timeval = 'time' if !defined $timeval; |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
my $frac; # Fractional seconds, if any |
351
|
|
|
|
|
|
|
my $cache_value; # 1/20 of 1 cent |
352
|
|
|
|
|
|
|
my $time_type; |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
# DateTime object? |
355
|
|
|
|
|
|
|
if (UNIVERSAL::isa($timeval, 'DateTime')) |
356
|
|
|
|
|
|
|
{ |
357
|
|
|
|
|
|
|
$cache_value = "$timeval"; # stringify |
358
|
|
|
|
|
|
|
$frac = $timeval->nanosecond() / 1e9; |
359
|
|
|
|
|
|
|
$time_type = $DATETIME_OBJECT; |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
# Numeric time? |
362
|
|
|
|
|
|
|
# 1 to 11 digits-- Epoch time should be <= 10 digits, and 12 digits might be YYYYMMDDHHMM. |
363
|
|
|
|
|
|
|
elsif ($timeval =~ /^\s* ( (\d{1,11}) (?:[.,](\d+))? ) $/x) |
364
|
|
|
|
|
|
|
{ |
365
|
|
|
|
|
|
|
$timeval = $1; |
366
|
|
|
|
|
|
|
$cache_value = $2; |
367
|
|
|
|
|
|
|
$frac = $3? '0.' . $3 : 0; |
368
|
|
|
|
|
|
|
$time_type = $NUMERIC_TIME; |
369
|
|
|
|
|
|
|
} |
370
|
|
|
|
|
|
|
# Stringified DateTime object? |
371
|
|
|
|
|
|
|
# Except we make it more flexible by allowing the date OR the time to be specfied |
372
|
|
|
|
|
|
|
# This will also match Date::Manip strings, and many ISO-8601 strings. |
373
|
|
|
|
|
|
|
elsif ($timeval =~ m{\A( (?!\d{6,8}\z) # string must not consist of only 6 or 8 digits. |
374
|
|
|
|
|
|
|
(?: # year-month-day |
375
|
|
|
|
|
|
|
\d{4} # year |
376
|
|
|
|
|
|
|
[-/.]? (?:0[1-9]|1[0-2]) # month |
377
|
|
|
|
|
|
|
[-/.]? (?:0[1-9]|[12]\d|3[01]) # day |
378
|
|
|
|
|
|
|
)? # ymd is optional |
379
|
|
|
|
|
|
|
(?: (?<=\d) [T_ ] (?=\d) )? # separator: T or _ or space, but only if ymd and hms both present |
380
|
|
|
|
|
|
|
) # End of $1: YMD and separator |
381
|
|
|
|
|
|
|
(?: # hms is optional |
382
|
|
|
|
|
|
|
( |
383
|
|
|
|
|
|
|
(?:[01]\d|2[0-4]) # hour |
384
|
|
|
|
|
|
|
[:.]? (?:[0-5]\d) # minute |
385
|
|
|
|
|
|
|
[:.]? (?:[0-5]\d|6[0-1])? # second |
386
|
|
|
|
|
|
|
) # End of $2: HMS |
387
|
|
|
|
|
|
|
(?: [,.] (\d+))? # optional fraction |
388
|
|
|
|
|
|
|
(Z?) # optional "zulu" (UTC) designator |
389
|
|
|
|
|
|
|
)? # end of optional (HMS.fraction) |
390
|
|
|
|
|
|
|
\z |
391
|
|
|
|
|
|
|
}x) |
392
|
|
|
|
|
|
|
{ |
393
|
|
|
|
|
|
|
$cache_value = ($1 || q{}) . ($2 || q{}) . ($4 || q{}); |
394
|
|
|
|
|
|
|
$frac = $3? '0.' . $3 : 0; |
395
|
|
|
|
|
|
|
$time_type = $DATETIME_STRING; |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
# Not set, or set to 'time' string? |
398
|
|
|
|
|
|
|
elsif ($timeval eq 'time' || $timeval eq q{}) |
399
|
|
|
|
|
|
|
{ |
400
|
|
|
|
|
|
|
# Get numeric time |
401
|
|
|
|
|
|
|
$timeval = _have('Time::HiRes')? Time::HiRes::time() : time; |
402
|
|
|
|
|
|
|
$cache_value = int $timeval; |
403
|
|
|
|
|
|
|
$frac = $timeval - $cache_value; |
404
|
|
|
|
|
|
|
$time_type = $NUMERIC_TIME; |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
# *Tiny* numeric time (very close to zero; exponential notation)? |
407
|
|
|
|
|
|
|
# (See bug 87484, https://rt.cpan.org/Ticket/Display.html?id=87484) |
408
|
|
|
|
|
|
|
elsif ($timeval =~ /^\s* -? \d\.\d+ e-\d+ \s*$/x) |
409
|
|
|
|
|
|
|
{ |
410
|
|
|
|
|
|
|
$timeval = sprintf '%8.6f', abs($timeval); |
411
|
|
|
|
|
|
|
$cache_value = int $timeval; |
412
|
|
|
|
|
|
|
$frac = $timeval - $cache_value; |
413
|
|
|
|
|
|
|
$time_type = $NUMERIC_TIME; |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
else |
416
|
|
|
|
|
|
|
{ |
417
|
|
|
|
|
|
|
# User passed us something we don't know how to handle. |
418
|
|
|
|
|
|
|
_croak qq{Unrecognized time value: "$timeval"}; |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
# We messed up. |
421
|
|
|
|
|
|
|
die qq{Illegal time type "$time_type"; programming error in Time::Format. Contact author.} |
422
|
|
|
|
|
|
|
if !defined &$time_type; |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
# Calculate millisecond, microsecond from fraction |
425
|
|
|
|
|
|
|
# msec and usec are TRUNCATED, not ROUNDED, because rounding up |
426
|
|
|
|
|
|
|
# to the next higher second would be a nightmare. |
427
|
|
|
|
|
|
|
my $msec = sprintf '%03d', int ( 1_000 * $frac); |
428
|
|
|
|
|
|
|
my $usec = sprintf '%06d', int (1_000_000 * $frac); |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
return ($time_type, $timeval, $cache_value, $msec, $usec); |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
# Helper function -- returns localtime() hashref |
434
|
|
|
|
|
|
|
sub _loctime |
435
|
|
|
|
|
|
|
{ |
436
|
|
|
|
|
|
|
my ($decode, $time, $cachekey, $msec, $usec) = _classify_time(@_); |
437
|
|
|
|
|
|
|
my $locale_changed = setup_locale; |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
# Cached, because I expect this'll be called on the same time values frequently. |
440
|
|
|
|
|
|
|
die "Programming error: undefined cache value. Contact Time::Format author." |
441
|
|
|
|
|
|
|
if !defined $cachekey; |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# If locale has changed, can't use the cached value. |
444
|
|
|
|
|
|
|
if (!$locale_changed && exists $loc_cache{$cachekey}) |
445
|
|
|
|
|
|
|
{ |
446
|
|
|
|
|
|
|
my $h = $loc_cache{$cachekey}; |
447
|
|
|
|
|
|
|
($h->{mmm}, $h->{uuuuuu}) = ($msec, $usec); |
448
|
|
|
|
|
|
|
return $h; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
# Hour-12, time zone, localtime parts, decoded from input |
452
|
|
|
|
|
|
|
my ($h12, $tz, @time_parts) = $decode->($time); |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
# Populate a whole mess o' data elements |
455
|
|
|
|
|
|
|
my %th; |
456
|
|
|
|
|
|
|
my $m0 = $time_parts[4] - 1; # zero-based month |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
# NOTE: When adding new codes, be wary of adding any that interfere |
459
|
|
|
|
|
|
|
# with the user's ability to use the words "at", "on", or "of" literally. |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
# year, hour(12), month, day, hour, minute, second, millisecond, microsecond, time zone |
462
|
|
|
|
|
|
|
@th{qw[yyyy H m{on} d h m{in} s mmm uuuuuu tz]} = ( $time_parts[5], $h12, @time_parts[4,3,2,1,0], $msec, $usec, $tz); |
463
|
|
|
|
|
|
|
@th{qw[yy HH mm{on} dd hh mm{in} ss]} = map $_<10?"0$_":$_, $time_parts[5]%100, $h12, @time_parts[4,3,2,1,0]; |
464
|
|
|
|
|
|
|
@th{qw[ ?H ?m{on} ?d ?h ?m{in} ?s]} = map $_<10?" $_":$_, $h12, @time_parts[4,3,2,1,0]; |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
# AM/PM |
467
|
|
|
|
|
|
|
my ($h,$d,$wx) = @time_parts[2,3,6]; # Day, weekday index |
468
|
|
|
|
|
|
|
my $a = $h<12? 'a' : 'p'; |
469
|
|
|
|
|
|
|
$th{am} = $th{pm} = $a . 'm'; |
470
|
|
|
|
|
|
|
$th{'a.m.'} = $th{'p.m.'} = $a . '.m.'; |
471
|
|
|
|
|
|
|
@th{qw/AM PM A.M. P.M./} = map uc, @th{qw/am pm a.m. p.m./}; |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
$th{$_} = $names{$_}[$wx] for qw/Weekday WEEKDAY weekday Day DAY day/; |
474
|
|
|
|
|
|
|
$th{$_} = $names{$_}[$m0] for qw/Month MONTH month Mon MON mon/; |
475
|
|
|
|
|
|
|
$th{$_} = $names{$_}[$d] for qw/th TH/; |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
# Don't let the time cache grow boundlessly. |
478
|
|
|
|
|
|
|
if (++$cache_size == $cache_size_limit) |
479
|
|
|
|
|
|
|
{ |
480
|
|
|
|
|
|
|
$cache_size = 0; |
481
|
|
|
|
|
|
|
%loc_cache = (); |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
return $loc_cache{$cachekey} = \%th; |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
sub decode_DateTime_object |
487
|
|
|
|
|
|
|
{ |
488
|
|
|
|
|
|
|
my $dt = shift; |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
my @t = ($dt->hour_12, $dt->time_zone_short_name, |
491
|
|
|
|
|
|
|
$dt->second, $dt->minute, $dt->hour, |
492
|
|
|
|
|
|
|
$dt->day, $dt->month, $dt->year, |
493
|
|
|
|
|
|
|
$dt->dow, $dt->doy, $dt->is_dst); |
494
|
|
|
|
|
|
|
$t[-3] = 0 if $t[-3] == 7; # Convert 1-7 (Mon-Sun) to 0-6 (Sun-Sat). |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
return @t; |
497
|
|
|
|
|
|
|
} |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
# 2005-10-31T15:14:39 |
500
|
|
|
|
|
|
|
sub decode_DateTime_string |
501
|
|
|
|
|
|
|
{ |
502
|
|
|
|
|
|
|
my $dts = shift; |
503
|
|
|
|
|
|
|
unless ($dts =~ m{\A (?!>\d{6,8}\z) # string must not consist of only 6 or 8 digits. |
504
|
|
|
|
|
|
|
(?: |
505
|
|
|
|
|
|
|
(\d{4}) [-/.]? (\d{2}) [-/.]? (\d{2}) # year-month-day |
506
|
|
|
|
|
|
|
)? # ymd is optional, but next must not be digit |
507
|
|
|
|
|
|
|
(?: (?<=\d) [T_ ] (?=\d) )? # separator: T or _ or space, but only if ymd and hms both present |
508
|
|
|
|
|
|
|
(?: # hms is optional |
509
|
|
|
|
|
|
|
(\d{2}) [:.]? (\d{2}) [:.]? (\d{2}) # hour:minute:second |
510
|
|
|
|
|
|
|
(?: [,.] \d+)? # optional fraction (ignored in this sub) |
511
|
|
|
|
|
|
|
(Z?) # optional "zulu" (UTC) indicator |
512
|
|
|
|
|
|
|
)? \z |
513
|
|
|
|
|
|
|
}x) |
514
|
|
|
|
|
|
|
{ |
515
|
|
|
|
|
|
|
# This "should" never happen, since we checked the format of |
516
|
|
|
|
|
|
|
# the string already. |
517
|
|
|
|
|
|
|
die qq{Unrecognized DateTime string "$dts": probable Time::Format bug}; |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
my ($y,$mon,$d,$h,$min,$s,$tz) = ($1,$2,$3,$4,$5,$6,$7); |
521
|
|
|
|
|
|
|
my ($d_only, $t_only); |
522
|
|
|
|
|
|
|
my ($h12, $is_dst, $dow); |
523
|
|
|
|
|
|
|
if (!defined $y) |
524
|
|
|
|
|
|
|
{ |
525
|
|
|
|
|
|
|
# Time only. Set date to 1969-12-31. |
526
|
|
|
|
|
|
|
$y = 1969; |
527
|
|
|
|
|
|
|
$mon = 12; |
528
|
|
|
|
|
|
|
$d = 31; |
529
|
|
|
|
|
|
|
$h12 = $h == 0? 12 |
530
|
|
|
|
|
|
|
: $h > 12? $h - 12 |
531
|
|
|
|
|
|
|
: $h; |
532
|
|
|
|
|
|
|
$is_dst = 0; # (it's the dead of winter!) |
533
|
|
|
|
|
|
|
$dow = 3; # 12/31/1969 is Wednesday. |
534
|
|
|
|
|
|
|
$t_only = 1; |
535
|
|
|
|
|
|
|
} |
536
|
|
|
|
|
|
|
if (!defined $h) |
537
|
|
|
|
|
|
|
{ |
538
|
|
|
|
|
|
|
$h = 0; |
539
|
|
|
|
|
|
|
$min = 0; |
540
|
|
|
|
|
|
|
$s = 0; |
541
|
|
|
|
|
|
|
$d_only = 1; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
if (!$t_only) |
545
|
|
|
|
|
|
|
{ |
546
|
|
|
|
|
|
|
$h12 = $h == 0? 12 |
547
|
|
|
|
|
|
|
: $h > 12? $h - 12 |
548
|
|
|
|
|
|
|
: $h; |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
# DST? |
551
|
|
|
|
|
|
|
# If year is before 1970, use current year. |
552
|
|
|
|
|
|
|
my $tmp_year = $y > 1969? $y : (localtime)[5]+1900; |
553
|
|
|
|
|
|
|
my $ttime = timelocal(0, 0, 0, $d, $mon-1, $tmp_year); |
554
|
|
|
|
|
|
|
my @t = localtime $ttime; |
555
|
|
|
|
|
|
|
$is_dst = $t[8]; |
556
|
|
|
|
|
|
|
$dow = _dow($y, $mon, $d); |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
# +0 is to force numeric (remove leading zeroes) |
560
|
|
|
|
|
|
|
my @t = map {$_+0} ($s,$min,$h,$d,$mon,$y); |
561
|
|
|
|
|
|
|
$h12 += 0; |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
if ($tz && $tz eq 'Z') |
564
|
|
|
|
|
|
|
{ |
565
|
|
|
|
|
|
|
$tz = 'UTC'; |
566
|
|
|
|
|
|
|
} |
567
|
|
|
|
|
|
|
elsif (_have('POSIX')) |
568
|
|
|
|
|
|
|
{ |
569
|
|
|
|
|
|
|
$tz = POSIX::strftime('%Z', @t, $dow, -1, $is_dst); |
570
|
|
|
|
|
|
|
} |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
return ($h12, $tz, @t, $dow, -1, $is_dst); |
573
|
|
|
|
|
|
|
} |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
sub decode_epoch |
576
|
|
|
|
|
|
|
{ |
577
|
|
|
|
|
|
|
my $time = shift; # Assumed to be an epoch time integer |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
my @t = localtime $time; |
580
|
|
|
|
|
|
|
my $tz = _have('POSIX')? POSIX::strftime('%Z', @t) : ''; |
581
|
|
|
|
|
|
|
my $h = $t[2]; # Hour (24), Month index |
582
|
|
|
|
|
|
|
$t[4]++; |
583
|
|
|
|
|
|
|
$t[5] += 1900; |
584
|
|
|
|
|
|
|
my $h12 = $h>12? $h-12 : ($h || 12); |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
return ($h12, $tz, @t); |
587
|
|
|
|
|
|
|
} |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
# $int = dow ($year, $month, $day); |
590
|
|
|
|
|
|
|
# |
591
|
|
|
|
|
|
|
# Returns the day of the week (0=Sunday .. 6=Saturday). Uses Zeller's |
592
|
|
|
|
|
|
|
# congruence, so it isn't subject to the unix 2038 limitation. |
593
|
|
|
|
|
|
|
# |
594
|
|
|
|
|
|
|
#---> $int = dow ($year, $month, $day); |
595
|
|
|
|
|
|
|
sub _dow |
596
|
|
|
|
|
|
|
{ |
597
|
|
|
|
|
|
|
my ($Y, $M, $D) = @_; |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
$M -= 2; |
600
|
|
|
|
|
|
|
if ($M < 1) |
601
|
|
|
|
|
|
|
{ |
602
|
|
|
|
|
|
|
$M += 12; |
603
|
|
|
|
|
|
|
$Y--; |
604
|
|
|
|
|
|
|
} |
605
|
|
|
|
|
|
|
my $C = int($Y/100); |
606
|
|
|
|
|
|
|
$Y %= 100; |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
return (int((26*$M - 2)/10) + $D + $Y + int($Y/4) + int($C/4) - 2*$C) % 7; |
609
|
|
|
|
|
|
|
} |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
# The heart of the module. |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
my %disam; # Disambiguator for 'm' format. |
615
|
|
|
|
|
|
|
$disam{$_} = "{on}" foreach qw/yy d dd ?d/; # If year or day is nearby, it's 'month' |
616
|
|
|
|
|
|
|
$disam{$_} = "{in}" foreach qw/h hh ?h H HH ?H s ss ?s/; # If hour or second is nearby, it's 'minute' |
617
|
|
|
|
|
|
|
sub time_format_perlonly |
618
|
|
|
|
|
|
|
{ |
619
|
|
|
|
|
|
|
my $fmt = shift; |
620
|
|
|
|
|
|
|
my $time = _loctime(@_); |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
# Remove \Q...\E sequences |
623
|
|
|
|
|
|
|
my $rc; |
624
|
|
|
|
|
|
|
if (index($fmt, '\Q') >= 0) |
625
|
|
|
|
|
|
|
{ |
626
|
|
|
|
|
|
|
$rc = init_store($fmt); |
627
|
|
|
|
|
|
|
$fmt =~ s/\\Q(.*?)(?:\\E|$)/remember($1)/seg; |
628
|
|
|
|
|
|
|
} |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
# "Guess" how to interpret ambiguous 'm' |
631
|
|
|
|
|
|
|
$fmt =~ s/ |
632
|
|
|
|
|
|
|
(?<!\\) # Must not follow a backslash |
633
|
|
|
|
|
|
|
(?=[ydhH]) # Must start with one of these |
634
|
|
|
|
|
|
|
( # $1 begins |
635
|
|
|
|
|
|
|
( # $2 begins. Capture: |
636
|
|
|
|
|
|
|
yy # a year |
637
|
|
|
|
|
|
|
| [dhH] # a day or hour |
638
|
|
|
|
|
|
|
) |
639
|
|
|
|
|
|
|
[^?m\\]? # Followed by something that's not part of a month |
640
|
|
|
|
|
|
|
) |
641
|
|
|
|
|
|
|
(?![?m]?m\{[io]n\}) # make sure it's not already unambiguous |
642
|
|
|
|
|
|
|
(?!mon) # don't confuse "mon" with "m" "on" |
643
|
|
|
|
|
|
|
([?m]?m) # $3 is a month code |
644
|
|
|
|
|
|
|
/$1$3$disam{$2}/gx; |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
# Ambiguous 'm', part 2. |
647
|
|
|
|
|
|
|
$fmt =~ s/(?<!\\) # ignore things that begin with backslash |
648
|
|
|
|
|
|
|
([?m]?m) # $1 is a month code |
649
|
|
|
|
|
|
|
( # $2 begins. |
650
|
|
|
|
|
|
|
[^\\]? # 0 or 1 characters |
651
|
|
|
|
|
|
|
(?=[?dsy]) # Next char must be one of these |
652
|
|
|
|
|
|
|
( # $3 begins. Capture: |
653
|
|
|
|
|
|
|
\??[ds] # a day or a second |
654
|
|
|
|
|
|
|
| yy # or a year |
655
|
|
|
|
|
|
|
) |
656
|
|
|
|
|
|
|
)/$1$disam{$3}$2/gx; |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
# The Big Date/Time Pattern of Doom |
659
|
|
|
|
|
|
|
$fmt =~ s/ |
660
|
|
|
|
|
|
|
(?<!\\) # Don't expand something preceded by backslash |
661
|
|
|
|
|
|
|
(?=[dDy?hHsaApPMmWwutT]) # Jump to one of these characters |
662
|
|
|
|
|
|
|
( |
663
|
|
|
|
|
|
|
[Dd]ay|DAY # Weekday abbreviation |
664
|
|
|
|
|
|
|
| yy(?:yy)? # Year |
665
|
|
|
|
|
|
|
| [?m]?m\{[oi]n\} # Unambiguous month-minute codes |
666
|
|
|
|
|
|
|
| th | TH # day suffix |
667
|
|
|
|
|
|
|
| [?d]?d # Day |
668
|
|
|
|
|
|
|
| [?h]?h # Hour (24) |
669
|
|
|
|
|
|
|
| [?H]?H # Hour (12) |
670
|
|
|
|
|
|
|
| [?s]?s # Second |
671
|
|
|
|
|
|
|
| [apAP]\.?[mM]\.? # am and pm strings |
672
|
|
|
|
|
|
|
| [Mm]on(?:th)?|MON(?:TH)? # Month names and abbrev |
673
|
|
|
|
|
|
|
| [Ww]eekday|WEEKDAY # Weekday names |
674
|
|
|
|
|
|
|
| mmm|uuuuuu # millisecond and microsecond |
675
|
|
|
|
|
|
|
| tz # time zone |
676
|
|
|
|
|
|
|
)/$time->{$1}/gx; |
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
# Simulate \U \L \u \l |
679
|
|
|
|
|
|
|
$fmt =~ s/((?:\\[UL])+)((?:\\[ul])+)/$2$1/g; |
680
|
|
|
|
|
|
|
$fmt =~ s/\\U(.*?)(?=\\[EULul]|$)/\U$1/gs; |
681
|
|
|
|
|
|
|
$fmt =~ s/\\L(.*?)(?=\\[EULul]|$)/\L$1/gs; |
682
|
|
|
|
|
|
|
$fmt =~ s/\\l(.)/\l$1/gs; |
683
|
|
|
|
|
|
|
$fmt =~ s/\\u(.)/\u$1/gs; |
684
|
|
|
|
|
|
|
$fmt =~ s/\\E//g; |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
$fmt =~ tr/\\//d; # Remove extraneous backslashes. |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
if (defined $rc) # Fixup \Q \E regions. |
689
|
|
|
|
|
|
|
{ |
690
|
|
|
|
|
|
|
$fmt =~ s/$rc(..)/recall($1)/seg; |
691
|
|
|
|
|
|
|
} |
692
|
|
|
|
|
|
|
return $fmt; |
693
|
|
|
|
|
|
|
} |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
# Code for remembering/restoring \Q...\E regions. |
696
|
|
|
|
|
|
|
# init_store finds a sigil character that's not used within the format string. |
697
|
|
|
|
|
|
|
# remember stores a string in the next slot in @store, and returns a coded replacement. |
698
|
|
|
|
|
|
|
# recall looks up and returns a string from @store. |
699
|
|
|
|
|
|
|
{ |
700
|
|
|
|
|
|
|
my $rcode; |
701
|
|
|
|
|
|
|
my @store; |
702
|
|
|
|
|
|
|
my $stx; |
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
sub init_store |
705
|
|
|
|
|
|
|
{ |
706
|
|
|
|
|
|
|
my $str = shift; |
707
|
|
|
|
|
|
|
$stx = 0; |
708
|
|
|
|
|
|
|
return $rcode = "\x01" unless index($str,"\x01") >= 0; |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
for ($rcode="\x02"; $rcode<"\xFF"; $rcode=chr(1+ord $rcode)) |
711
|
|
|
|
|
|
|
{ |
712
|
|
|
|
|
|
|
return $rcode unless index($str, $rcode) >= 0; |
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
_croak "Time::Format cannot process string: no unique characters left."; |
715
|
|
|
|
|
|
|
} |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
sub remember |
718
|
|
|
|
|
|
|
{ |
719
|
|
|
|
|
|
|
my $enc; |
720
|
|
|
|
|
|
|
do # Must not return a code that contains a backslash |
721
|
|
|
|
|
|
|
{ |
722
|
|
|
|
|
|
|
$enc = pack 'S', $stx++; |
723
|
|
|
|
|
|
|
} while index($enc, '\\') >= 0; |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
$store[$stx-1] = shift; |
726
|
|
|
|
|
|
|
return join '', map "\\$_", split //, "$rcode$enc"; # backslash-escape it! |
727
|
|
|
|
|
|
|
} |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
sub recall |
730
|
|
|
|
|
|
|
{ |
731
|
|
|
|
|
|
|
return $store[unpack 'S', shift]; |
732
|
|
|
|
|
|
|
} |
733
|
|
|
|
|
|
|
} |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
__END__ |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
=head1 SYNOPSIS |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
use Time::Format qw(%time %strftime %manip); |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
$time{$format} |
742
|
|
|
|
|
|
|
$time{$format, $unixtime} |
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
print "Today is $time{'yyyy/mm/dd'}\n"; |
745
|
|
|
|
|
|
|
print "Yesterday was $time{'yyyy/mm/dd', time-24*60*60}\n"; |
746
|
|
|
|
|
|
|
print "The time is $time{'hh:mm:ss'}\n"; |
747
|
|
|
|
|
|
|
print "Another time is $time{'H:mm am tz', $another_time}\n"; |
748
|
|
|
|
|
|
|
print "Timestamp: $time{'yyyymmdd.hhmmss.mmm'}\n"; |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
C<%time> also accepts Date::Manip strings and DateTime objects: |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
$dm = Date::Manip::ParseDate('last monday'); |
753
|
|
|
|
|
|
|
print "Last monday was $time{'Month d, yyyy', $dm}"; |
754
|
|
|
|
|
|
|
$dt = DateTime->new (....); |
755
|
|
|
|
|
|
|
print "Here's another date: $time{'m/d/yy', $dt}"; |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
It also accepts most ISO-8601 date/time strings: |
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
$t = '2005/10/31T17:11:09'; # date separator: / or - or . |
760
|
|
|
|
|
|
|
$t = '2005-10-31 17.11.09'; # in-between separator: T or _ or space |
761
|
|
|
|
|
|
|
$t = '20051031_171109'; # time separator: : or . |
762
|
|
|
|
|
|
|
$t = '20051031171109'; # separators may be omitted |
763
|
|
|
|
|
|
|
$t = '2005/10/31'; # date-only is okay |
764
|
|
|
|
|
|
|
$t = '17:11:09'; # time-only is okay |
765
|
|
|
|
|
|
|
# But not: |
766
|
|
|
|
|
|
|
$t = '20051031'; # date-only without separators |
767
|
|
|
|
|
|
|
$t = '171109'; # time-only without separators |
768
|
|
|
|
|
|
|
# ...because those look like epoch time numbers. |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
C<%strftime> works like POSIX's C<strftime>, if you like those C<%>-formats. |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
$strftime{$format} |
773
|
|
|
|
|
|
|
$strftime{$format, $unixtime} |
774
|
|
|
|
|
|
|
$strftime{$format, $sec,$min,$hour, $mday,$mon,$year, $wday,$yday,$isdst} |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
print "POSIXish: $strftime{'%A, %B %d, %Y', 0,0,0,12,11,95,2}\n"; |
777
|
|
|
|
|
|
|
print "POSIXish: $strftime{'%A, %B %d, %Y', 1054866251}\n"; |
778
|
|
|
|
|
|
|
print "POSIXish: $strftime{'%A, %B %d, %Y'}\n"; # current time |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
C<%manip> works like Date::Manip's C<UnixDate> function. |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
$manip{$format}; |
783
|
|
|
|
|
|
|
$manip{$format, $when}; |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
print "Date::Manip: $manip{'%m/%d/%Y'}\n"; # current time |
786
|
|
|
|
|
|
|
print "Date::Manip: $manip{'%m/%d/%Y','last Tuesday'}\n"; |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
These can also be used as standalone functions: |
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
use Time::Format qw(time_format time_strftime time_manip); |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
print "Today is ", time_format('yyyy/mm/dd', $some_time), "\n"; |
793
|
|
|
|
|
|
|
print "POSIXish: ", time_strftime('%A %B %d, %Y',$some_time), "\n"; |
794
|
|
|
|
|
|
|
print "Date::Manip: ", time_manip('%m/%d/%Y',$some_time), "\n"; |
795
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
=head1 DESCRIPTION |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
This module creates global pseudovariables which format dates and |
799
|
|
|
|
|
|
|
times, according to formatting codes you pass to them in strings. |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
The C<%time> formatting codes are designed to be easy to remember and |
802
|
|
|
|
|
|
|
use, and to take up just as many characters as the output time value |
803
|
|
|
|
|
|
|
whenever possible. For example, the four-digit year code is |
804
|
|
|
|
|
|
|
"C<yyyy>", the three-letter month abbreviation is "C<Mon>". |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
The nice thing about having a variable-like interface instead |
807
|
|
|
|
|
|
|
of function calls is that the values can be used inside of strings (as |
808
|
|
|
|
|
|
|
well as outside of strings in ordinary expressions). Dates are |
809
|
|
|
|
|
|
|
frequently used within strings (log messages, output, data records, |
810
|
|
|
|
|
|
|
etc.), so having the ability to interpolate them directly is handy. |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
Perl allows arbitrary expressions within curly braces of a hash, even |
813
|
|
|
|
|
|
|
when that hash is being interpolated into a string. This allows you |
814
|
|
|
|
|
|
|
to do computations on the fly while formatting times and inserting |
815
|
|
|
|
|
|
|
them into strings. See the "yesterday" example above. |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
The format strings are designed with programmers in mind. What do you |
818
|
|
|
|
|
|
|
need most frequently? 4-digit year, month, day, 24-based hour, |
819
|
|
|
|
|
|
|
minute, second -- usually with leading zeroes. These six are the |
820
|
|
|
|
|
|
|
easiest formats to use and remember in Time::Format: C<yyyy>, C<mm>, |
821
|
|
|
|
|
|
|
C<dd>, C<hh>, C<mm>, C<ss>. Variants on these formats follow a simple |
822
|
|
|
|
|
|
|
and consistent formula. This module is for everyone who is weary of |
823
|
|
|
|
|
|
|
trying to remember I<strftime(3)>'s arcane codes, or of endlessly |
824
|
|
|
|
|
|
|
writing C<$t[4]++; $t[5]+=1900> as you manually format times or dates. |
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
Note that C<mm> (and related codes) are used both for months and |
827
|
|
|
|
|
|
|
minutes. This is a feature. C<%time> resolves the ambiguity by |
828
|
|
|
|
|
|
|
examining other nearby formatting codes. If it's in the context of a |
829
|
|
|
|
|
|
|
year or a day, "month" is assumed. If in the context of an hour or a |
830
|
|
|
|
|
|
|
second, "minute" is assumed. |
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
The format strings are not meant to encompass every date/time need |
833
|
|
|
|
|
|
|
ever conceived. But how often do you need the day of the year |
834
|
|
|
|
|
|
|
(strftime's C<%j>) or the week number (strftime's C<%W>)? |
835
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
For capabilities that C<%time> does not provide, C<%strftime> provides |
837
|
|
|
|
|
|
|
an interface to POSIX's C<strftime>, and C<%manip> provides an |
838
|
|
|
|
|
|
|
interface to the Date::Manip module's C<UnixDate> function. |
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
If the companion module L<Time::Format_XS> is also installed, |
841
|
|
|
|
|
|
|
Time::Format will detect and use it. This will result in a |
842
|
|
|
|
|
|
|
significant speed increase for C<%time> and C<time_format>. |
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
=head1 VARIABLES |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
=over 4 |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
=item time |
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
$time{$format} |
851
|
|
|
|
|
|
|
$time{$format,$time_value}; |
852
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
Formats a unix time number (seconds since the epoch), DateTime object, |
854
|
|
|
|
|
|
|
stringified DateTime, Date::Manip string, or ISO-8601 string, |
855
|
|
|
|
|
|
|
according to the specified format. If the time expression is omitted, |
856
|
|
|
|
|
|
|
the current time is used. The format string may contain any of the |
857
|
|
|
|
|
|
|
following: |
858
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
yyyy 4-digit year |
860
|
|
|
|
|
|
|
yy 2-digit year |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
m 1- or 2-digit month, 1-12 |
863
|
|
|
|
|
|
|
mm 2-digit month, 01-12 |
864
|
|
|
|
|
|
|
?m month with leading space if < 10 |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
Month full month name, mixed-case |
867
|
|
|
|
|
|
|
MONTH full month name, uppercase |
868
|
|
|
|
|
|
|
month full month name, lowercase |
869
|
|
|
|
|
|
|
Mon 3-letter month abbreviation, mixed-case |
870
|
|
|
|
|
|
|
MON mon ditto, uppercase and lowercase versions |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
d day number, 1-31 |
873
|
|
|
|
|
|
|
dd day number, 01-31 |
874
|
|
|
|
|
|
|
?d day with leading space if < 10 |
875
|
|
|
|
|
|
|
th day suffix (st, nd, rd, or th) |
876
|
|
|
|
|
|
|
TH uppercase suffix |
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
Weekday weekday name, mixed-case |
879
|
|
|
|
|
|
|
WEEKDAY weekday name, uppercase |
880
|
|
|
|
|
|
|
weekday weekday name, lowercase |
881
|
|
|
|
|
|
|
Day 3-letter weekday name, mixed-case |
882
|
|
|
|
|
|
|
DAY day ditto, uppercase and lowercase versions |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
h hour, 0-23 |
885
|
|
|
|
|
|
|
hh hour, 00-23 |
886
|
|
|
|
|
|
|
?h hour, 0-23 with leading space if < 10 |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
H hour, 1-12 |
889
|
|
|
|
|
|
|
HH hour, 01-12 |
890
|
|
|
|
|
|
|
?H hour, 1-12 with leading space if < 10 |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
m minute, 0-59 |
893
|
|
|
|
|
|
|
mm minute, 00-59 |
894
|
|
|
|
|
|
|
?m minute, 0-59 with leading space if < 10 |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
s second, 0-59 |
897
|
|
|
|
|
|
|
ss second, 00-59 |
898
|
|
|
|
|
|
|
?s second, 0-59 with leading space if < 10 |
899
|
|
|
|
|
|
|
mmm millisecond, 000-999 |
900
|
|
|
|
|
|
|
uuuuuu microsecond, 000000-999999 |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
am a.m. The string "am" or "pm" (second form with periods) |
903
|
|
|
|
|
|
|
pm p.m. same as "am" or "a.m." |
904
|
|
|
|
|
|
|
AM A.M. same as "am" or "a.m." but uppercase |
905
|
|
|
|
|
|
|
PM P.M. same as "AM" or "A.M." |
906
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
tz time zone abbreviation |
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
Millisecond and microsecond require Time::HiRes, otherwise they'll |
910
|
|
|
|
|
|
|
always be zero. Timezone requires POSIX, otherwise it'll be the empty |
911
|
|
|
|
|
|
|
string. The second codes (C<s>, C<ss>, C<?s>) can be 60 or 61 in rare |
912
|
|
|
|
|
|
|
circumstances (leap seconds, if your system supports such). |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
Anything in the format string other than the above patterns is left |
915
|
|
|
|
|
|
|
intact. Any character preceded by a backslash is left alone and |
916
|
|
|
|
|
|
|
not used for any part of a format code. See the L</QUOTING> section |
917
|
|
|
|
|
|
|
for more details. |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
For the most part, each of the above formatting codes takes up as much |
920
|
|
|
|
|
|
|
space as the output string it generates. The exceptions are the codes |
921
|
|
|
|
|
|
|
whose output is variable length: C<Weekday>, C<Month>, time zone, and |
922
|
|
|
|
|
|
|
the single-character codes. |
923
|
|
|
|
|
|
|
|
924
|
|
|
|
|
|
|
The mixed-case "Month", "Mon", "Weekday", and "Day" codes return the |
925
|
|
|
|
|
|
|
name of the month or weekday in the preferred case representation for |
926
|
|
|
|
|
|
|
the locale currently in effect. Thus in an English-speaking locale, |
927
|
|
|
|
|
|
|
the seventh month would be "July" (uppercase first letter, lowercase |
928
|
|
|
|
|
|
|
rest); while in a French-speaking locale, it would be "juillet" (all |
929
|
|
|
|
|
|
|
lowercase). See the L</QUOTING> section for ways to control the case |
930
|
|
|
|
|
|
|
of month/weekday names. |
931
|
|
|
|
|
|
|
|
932
|
|
|
|
|
|
|
Note that the "C<mm>", "C<m>", and "C<?m>" formats are ambiguous. |
933
|
|
|
|
|
|
|
C<%time> tries to guess whether you meant "month" or "minute" based on |
934
|
|
|
|
|
|
|
nearby characters in the format string. Thus, a format of |
935
|
|
|
|
|
|
|
"C<yyyy/mm/dd hh:mm:ss>" is correctly parsed as "year month day, hour |
936
|
|
|
|
|
|
|
minute second". If C<%time> cannot determine whether you meant |
937
|
|
|
|
|
|
|
"month" or "minute", it leaves the C<mm>, C<m>, or C<?m> untranslated. |
938
|
|
|
|
|
|
|
To remove the ambiguity, you can use the following codes: |
939
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
m{on} month, 1-12 |
941
|
|
|
|
|
|
|
mm{on} month, 01-12 |
942
|
|
|
|
|
|
|
?m{on} month, 1-12 with leading space if < 10 |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
m{in} minute, 0-59 |
945
|
|
|
|
|
|
|
mm{in} minute, 00-59 |
946
|
|
|
|
|
|
|
?m{in} minute, 0-59 with leading space if < 10 |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
In other words, append "C<{on}>" or "C<{in}>" to make "C<m>", "C<mm>", |
949
|
|
|
|
|
|
|
or "C<?m>" unambiguous. |
950
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
=item strftime |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
$strftime{$format, $sec,$min,$hour, $mday,$mon,$year, $wday,$yday,$isdst} |
954
|
|
|
|
|
|
|
$strftime{$format, $unixtime} |
955
|
|
|
|
|
|
|
$strftime{$format} |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
For those who prefer L<strftime|POSIX/strftime>'s weird % formats, or |
958
|
|
|
|
|
|
|
who need POSIX compliance, or who need week numbers or other features |
959
|
|
|
|
|
|
|
C<%time> does not provide. |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
=item manip |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
$manip{$format}; |
964
|
|
|
|
|
|
|
$manip{$format,$when}; |
965
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
Provides an interface to the Date::Manip module's C<UnixDate> |
967
|
|
|
|
|
|
|
function. This function is rather slow, but can parse a very wide |
968
|
|
|
|
|
|
|
variety of date input. See the L<Date::Manip> module for details |
969
|
|
|
|
|
|
|
about the inputs accepted. |
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
If you want to use the C<%time> codes, but need the input flexibility |
972
|
|
|
|
|
|
|
of C<%manip>, you can use Date::Manip's C<ParseDate> function: |
973
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
print "$time{'yyyymmdd', ParseDate('last sunday')}"; |
975
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
=back |
977
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
=head1 FUNCTIONS |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
=over 4 |
981
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
=item time_format |
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
time_format($format); |
985
|
|
|
|
|
|
|
time_format($format, $unix_time); |
986
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
This is a function interface to C<%time>. It accepts the same |
988
|
|
|
|
|
|
|
formatting codes and everything. This is provided for people who want |
989
|
|
|
|
|
|
|
their function calls to I<look> like function calls, not hashes. :-) |
990
|
|
|
|
|
|
|
The following two are equivalent: |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
$x = $time{'yyyy/mm/dd'}; |
993
|
|
|
|
|
|
|
$x = time_format('yyyy/mm/dd'); |
994
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
=item time_strftime |
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
time_strftime($format, $sec,$min,$hour, $mday,$mon,$year, $wday,$yday,$isdst); |
998
|
|
|
|
|
|
|
time_strftime($format, $unixtime); |
999
|
|
|
|
|
|
|
time_strftime($format); |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
This is a function interface to C<%strftime>. It simply calls |
1002
|
|
|
|
|
|
|
POSIX::C<strftime>, but it does provide a bit of an advantage over |
1003
|
|
|
|
|
|
|
calling C<strftime> directly, in that you can pass the time as a unix |
1004
|
|
|
|
|
|
|
time (seconds since the epoch), or omit it in order to get the current |
1005
|
|
|
|
|
|
|
time. |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
=item time_manip |
1008
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
manip($format); |
1010
|
|
|
|
|
|
|
manip($format,$when); |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
This is a function interface to C<%manip>. It calls |
1013
|
|
|
|
|
|
|
Date::Manip::C<UnixDate> under the hood. It does not provide much of |
1014
|
|
|
|
|
|
|
an advantage over calling C<UnixDate> directly, except that you can |
1015
|
|
|
|
|
|
|
omit the C<$when> parameter in order to get the current time. |
1016
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
=back |
1018
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
=head1 QUOTING |
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
This section applies to the format strings used by C<%time> and |
1022
|
|
|
|
|
|
|
C<time_format> only. |
1023
|
|
|
|
|
|
|
|
1024
|
|
|
|
|
|
|
Sometimes it is necessary to suppress expansion of some format |
1025
|
|
|
|
|
|
|
characters in a format string. For example: |
1026
|
|
|
|
|
|
|
|
1027
|
|
|
|
|
|
|
$time{'Hour: hh; Minute: mm{in}; Second: ss'}; |
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
In the above expression, the "H" in "Hour" would be expanded, |
1030
|
|
|
|
|
|
|
as would the "d" in "Second". The result would be something like: |
1031
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
8our: 08; Minute: 10; Secon17: 30 |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
It would not be a good solution to break the above statement out |
1035
|
|
|
|
|
|
|
into three calls to %time: |
1036
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
"Hour: $time{hh}; Minute: $time{'mm{in}'}; Second: $time{ss}" |
1038
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
because the time could change from one call to the next, which would |
1040
|
|
|
|
|
|
|
be a problem when the numbers roll over (for example, a split second |
1041
|
|
|
|
|
|
|
after 7:59:59). |
1042
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
For this reason, you can escape individual format codes with a |
1044
|
|
|
|
|
|
|
backslash: |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
$time{'\Hour: hh; Minute: mm{in}; Secon\d: ss'}; |
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
Note that with double-quoted (and qq//) strings, the backslash must be |
1049
|
|
|
|
|
|
|
doubled, because Perl first interpolates the string: |
1050
|
|
|
|
|
|
|
|
1051
|
|
|
|
|
|
|
$time{"\\Hour: hh; Minute: mm{in}; Secon\\d: ss"}; |
1052
|
|
|
|
|
|
|
|
1053
|
|
|
|
|
|
|
For added convenience, Time::Format simulates Perl's built-in \Q and |
1054
|
|
|
|
|
|
|
\E inline quoting operators. Anything in a string between a \Q and \E |
1055
|
|
|
|
|
|
|
will not be interpolated as any part of any formatting code: |
1056
|
|
|
|
|
|
|
|
1057
|
|
|
|
|
|
|
$time{'\QHour:\E hh; \QMinute:\E mm{in}; \QSecond:\E ss'}; |
1058
|
|
|
|
|
|
|
|
1059
|
|
|
|
|
|
|
Again, within interpolated strings, the backslash must be doubled, or |
1060
|
|
|
|
|
|
|
else Perl will interpret and remove the \Q...\E sequence before |
1061
|
|
|
|
|
|
|
Time::Format gets it: |
1062
|
|
|
|
|
|
|
|
1063
|
|
|
|
|
|
|
$time{"\\QHour:\\E hh; \\QMinute:\\E mm{in}; \\QSecond\\E: ss"}; |
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
Time::Format also recognizes and simulates the \U, \L, \u, and \l |
1066
|
|
|
|
|
|
|
sequences. This is really only useful for finer control of the Month, |
1067
|
|
|
|
|
|
|
Mon, Weekday, and Day formats. For example, in some locales, the |
1068
|
|
|
|
|
|
|
month names are all-lowercase by convention. At the start of a |
1069
|
|
|
|
|
|
|
sentence, you may want to ensure that the first character is |
1070
|
|
|
|
|
|
|
uppercase: |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
$time{'\uMonth \Qis the finest month of all.'}; |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
Again, be sure to use \Q, and be sure to double the backslashes in |
1075
|
|
|
|
|
|
|
interpolated strings, otherwise you'll get something ugly like: |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
July i37 ste fine37t july of all. |
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
=head1 EXAMPLES |
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
$time{'Weekday Month d, yyyy'} Thursday June 5, 2003 |
1082
|
|
|
|
|
|
|
$time{'Day Mon d, yyyy'} Thu Jun 5, 2003 |
1083
|
|
|
|
|
|
|
$time{'dd/mm/yyyy'} 05/06/2003 |
1084
|
|
|
|
|
|
|
$time{yymmdd} 030605 |
1085
|
|
|
|
|
|
|
$time{'yymmdd',time-86400} 030604 |
1086
|
|
|
|
|
|
|
$time{'dth of Month'} 5th of June |
1087
|
|
|
|
|
|
|
|
1088
|
|
|
|
|
|
|
$time{'H:mm:ss am'} 1:02:14 pm |
1089
|
|
|
|
|
|
|
$time{'hh:mm:ss.uuuuuu'} 13:02:14.171447 |
1090
|
|
|
|
|
|
|
|
1091
|
|
|
|
|
|
|
$time{'yyyy/mm{on}/dd hh:mm{in}:ss.mmm'} 2003/06/05 13:02:14.171 |
1092
|
|
|
|
|
|
|
$time{'yyyy/mm/dd hh:mm:ss.mmm'} 2003/06/05 13:02:14.171 |
1093
|
|
|
|
|
|
|
|
1094
|
|
|
|
|
|
|
$time{"It's H:mm."} It'14 1:02. # OOPS! |
1095
|
|
|
|
|
|
|
$time{"It'\\s H:mm."} It's 1:02. # Backslash fixes it. |
1096
|
|
|
|
|
|
|
. |
1097
|
|
|
|
|
|
|
. |
1098
|
|
|
|
|
|
|
# Rename a file based on today's date: |
1099
|
|
|
|
|
|
|
rename $file, "${file}_$time{yyyymmdd}"; |
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
# Rename a file based on its last-modify date: |
1102
|
|
|
|
|
|
|
rename $file, "${file}_$time{'yyyymmdd',(stat $file)[9]}"; |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
# stftime examples |
1105
|
|
|
|
|
|
|
$strftime{'%A %B %d, %Y'} Thursday June 05, 2003 |
1106
|
|
|
|
|
|
|
$strftime{'%A %B %d, %Y',time+86400} Friday June 06, 2003 |
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
# manip examples |
1109
|
|
|
|
|
|
|
$manip{'%m/%d/%Y'} 06/05/2003 |
1110
|
|
|
|
|
|
|
$manip{'%m/%d/%Y','yesterday'} 06/04/2003 |
1111
|
|
|
|
|
|
|
$manip{'%m/%d/%Y','first monday in November 2000'} 11/06/2000 |
1112
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
=head1 INTERNATIONALIZATION |
1114
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
If the I18N::Langinfo module is available, Time::Format will return |
1116
|
|
|
|
|
|
|
weekday and month names in the language appropriate for the current |
1117
|
|
|
|
|
|
|
locale. If not, English names will be used. |
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
Programmers in non-English locales may want to provide an alias to |
1120
|
|
|
|
|
|
|
C<%time> in their own preferred language. This can be done by |
1121
|
|
|
|
|
|
|
assigning C<\%time> to a typeglob: |
1122
|
|
|
|
|
|
|
|
1123
|
|
|
|
|
|
|
# French |
1124
|
|
|
|
|
|
|
use Time::Format; |
1125
|
|
|
|
|
|
|
use vars '%temps'; *temps = \%time; |
1126
|
|
|
|
|
|
|
print "C'est aujourd'hui le $temps{'d Month'}\n"; |
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
# German |
1129
|
|
|
|
|
|
|
use Time::Format; |
1130
|
|
|
|
|
|
|
use vars '%zeit'; *zeit = \%time; |
1131
|
|
|
|
|
|
|
print "Heutiger Tag ist $zeit{'d.m.yyyy'}\n"; |
1132
|
|
|
|
|
|
|
|
1133
|
|
|
|
|
|
|
=head1 EXPORTS |
1134
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
The following symbols are exported into your namespace by default: |
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
%time |
1138
|
|
|
|
|
|
|
time_format |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
The following symbols are available for import into your namespace: |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
%strftime |
1143
|
|
|
|
|
|
|
%manip |
1144
|
|
|
|
|
|
|
time_strftime |
1145
|
|
|
|
|
|
|
time_manip |
1146
|
|
|
|
|
|
|
|
1147
|
|
|
|
|
|
|
The C<:all> tag will import all of these into your namespace. |
1148
|
|
|
|
|
|
|
Example: |
1149
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
use Time::Format ':all'; |
1151
|
|
|
|
|
|
|
|
1152
|
|
|
|
|
|
|
=head1 LIMITATIONS |
1153
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
The format string used by C<%time> must not have $; as a substring |
1155
|
|
|
|
|
|
|
anywhere. $; (by default, ASCII character 28, or 1C hex) is used to |
1156
|
|
|
|
|
|
|
separate values passed to the tied hash, and thus Time::Format will |
1157
|
|
|
|
|
|
|
interpret your format string to be two or more arguments if it |
1158
|
|
|
|
|
|
|
contains $;. The C<time_format> function does not have this |
1159
|
|
|
|
|
|
|
limitation. |
1160
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
=head1 REQUIREMENTS |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
Time::Local |
1164
|
|
|
|
|
|
|
I18N::Langinfo, if you want non-English locales to work. |
1165
|
|
|
|
|
|
|
POSIX, if you choose to use %strftime or want the C<tz> format to work. |
1166
|
|
|
|
|
|
|
Time::HiRes, if you want the C<mmm> and C<uuuuuu> time formats to work. |
1167
|
|
|
|
|
|
|
Date::Manip, if you choose to use %manip. |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
Time::Format_XS is optional but will make C<%time> and C<time_format> |
1170
|
|
|
|
|
|
|
much faster. The version of Time::Format_XS installed must match |
1171
|
|
|
|
|
|
|
the version of Time::Format installed; otherwise Time::Format will |
1172
|
|
|
|
|
|
|
not use it (and will issue a warning). |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
=head1 AUTHOR / COPYRIGHT |
1175
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
Copyright (c) 2003-2020 by Eric J. Roode, ROODE I<-at-> cpan I<-dot-> org |
1177
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
All rights reserved. |
1179
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
To avoid my spam filter, please include "Perl", "module", or this |
1181
|
|
|
|
|
|
|
module's name in the message's subject line, and/or GPG-sign your |
1182
|
|
|
|
|
|
|
message. |
1183
|
|
|
|
|
|
|
|
1184
|
|
|
|
|
|
|
This module is copyrighted only to ensure proper attribution of |
1185
|
|
|
|
|
|
|
authorship and to ensure that it remains available to all. This |
1186
|
|
|
|
|
|
|
module is free, open-source software. This module may be freely used |
1187
|
|
|
|
|
|
|
for any purpose, commercial, public, or private, provided that proper |
1188
|
|
|
|
|
|
|
credit is given, and that no more-restrictive license is applied to |
1189
|
|
|
|
|
|
|
derivative (not dependent) works. |
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
Substantial efforts have been made to ensure that this software meets |
1192
|
|
|
|
|
|
|
high quality standards; however, no guarantee can be made that there |
1193
|
|
|
|
|
|
|
are no undiscovered bugs, and no warranty is made as to suitability to |
1194
|
|
|
|
|
|
|
any given use, including merchantability. Should this module cause |
1195
|
|
|
|
|
|
|
your house to burn down, your dog to collapse, your heart-lung machine |
1196
|
|
|
|
|
|
|
to fail, your spouse to desert you, or George Bush to be re-elected, I |
1197
|
|
|
|
|
|
|
can offer only my sincere sympathy and apologies, and promise to |
1198
|
|
|
|
|
|
|
endeavor to improve the software. |
1199
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
=begin gpg |
1202
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
-----BEGIN PGP SIGNATURE----- |
1204
|
|
|
|
|
|
|
|
1205
|
|
|
|
|
|
|
iF0EARECAB0WIQTSmjxiQX/QfjsCVJLChJhzmpBWqgUCXk1aEwAKCRDChJhzmpBW |
1206
|
|
|
|
|
|
|
qu/jAKCil0ppbfA+FbEEub5E41qEWajl7wCfclrwa5dGIHb1+jL9sAVmACjvKlg= |
1207
|
|
|
|
|
|
|
=pSH2 |
1208
|
|
|
|
|
|
|
-----END PGP SIGNATURE----- |
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
=end gpg |