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