line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Time::Strptime::Format; |
2
|
4
|
|
|
4
|
|
51969
|
use strict; |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
110
|
|
3
|
4
|
|
|
4
|
|
19
|
use warnings; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
88
|
|
4
|
4
|
|
|
4
|
|
2209
|
use utf8; |
|
4
|
|
|
|
|
54
|
|
|
4
|
|
|
|
|
17
|
|
5
|
4
|
|
|
4
|
|
1693
|
use integer; |
|
4
|
|
|
|
|
47
|
|
|
4
|
|
|
|
|
22
|
|
6
|
|
|
|
|
|
|
|
7
|
4
|
|
|
4
|
|
109
|
use B; |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
138
|
|
8
|
4
|
|
|
4
|
|
17
|
use Carp (); |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
63
|
|
9
|
4
|
|
|
4
|
|
1624
|
use Time::Local qw/timegm timegm_nocheck/; |
|
4
|
|
|
|
|
5038
|
|
|
4
|
|
|
|
|
215
|
|
10
|
4
|
|
|
4
|
|
1813
|
use Encode qw/encode_utf8/; |
|
4
|
|
|
|
|
30199
|
|
|
4
|
|
|
|
|
253
|
|
11
|
4
|
|
|
4
|
|
1611
|
use DateTime::Locale; |
|
4
|
|
|
|
|
681638
|
|
|
4
|
|
|
|
|
143
|
|
12
|
4
|
|
|
4
|
|
2196
|
use List::MoreUtils qw/uniq/; |
|
4
|
|
|
|
|
26428
|
|
|
4
|
|
|
|
|
39
|
|
13
|
4
|
|
|
4
|
|
4403
|
use POSIX qw/strftime LC_ALL/; |
|
4
|
|
|
|
|
18406
|
|
|
4
|
|
|
|
|
24
|
|
14
|
4
|
|
|
4
|
|
6179
|
use Time::Strptime::TimeZone; |
|
4
|
|
|
|
|
24
|
|
|
4
|
|
|
|
|
166
|
|
15
|
|
|
|
|
|
|
|
16
|
4
|
|
33
|
4
|
|
24
|
use constant DEBUG => exists $ENV{PERL_TIME_STRPTIME_DEBUG} && $ENV{PERL_TIME_STRPTIME_DEBUG}; |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
6519
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
our $VERSION = 1.01; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
our %DEFAULT_HANDLER = ( |
21
|
|
|
|
|
|
|
A => [SKIP => sub { |
22
|
|
|
|
|
|
|
my $self = shift; |
23
|
|
|
|
|
|
|
my $wide = $self->{locale}->day_format_wide; |
24
|
|
|
|
|
|
|
my $abbr = $self->{locale}->day_format_abbreviated; |
25
|
|
|
|
|
|
|
return [map quotemeta, uniq map { lc, uc, $_ } map { $wide->[$_], $abbr->[$_] } 0..6]; |
26
|
|
|
|
|
|
|
}], |
27
|
|
|
|
|
|
|
a => [extend => q{%A} ], |
28
|
|
|
|
|
|
|
B => [localed_month => sub { |
29
|
|
|
|
|
|
|
my $self = shift; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
unless (exists $self->{format_table}{localed_month}) { |
32
|
|
|
|
|
|
|
my %format_table; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
my $wide = $self->{locale}->month_format_wide; |
35
|
|
|
|
|
|
|
my $abbr = $self->{locale}->month_format_abbreviated; |
36
|
|
|
|
|
|
|
for my $month (0..11) { |
37
|
|
|
|
|
|
|
for my $key ($wide->[$month], $abbr->[$month]) { |
38
|
|
|
|
|
|
|
$format_table{$key} = $month + 1; |
39
|
|
|
|
|
|
|
$format_table{lc $key} = $month + 1; |
40
|
|
|
|
|
|
|
$format_table{uc $key} = $month + 1; |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
$self->{format_table}{localed_month} = \%format_table; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
return [map quotemeta, keys %{ $self->{format_table}{localed_month} }]; |
47
|
|
|
|
|
|
|
} ], |
48
|
|
|
|
|
|
|
b => [extend => q{%B}], |
49
|
|
|
|
|
|
|
C => ['UNSUPPORTED'], |
50
|
|
|
|
|
|
|
c => ['UNSUPPORTED'], |
51
|
|
|
|
|
|
|
D => [extend => q{%m/%d/%Y} ], |
52
|
|
|
|
|
|
|
d => [day => ['0[1-9]','[12][0-9]','3[01]'] ], |
53
|
|
|
|
|
|
|
e => [day => [' [1-9]','[12][0-9]','3[01]'] ], |
54
|
|
|
|
|
|
|
F => [extend => q{%Y-%m-%d} ], |
55
|
|
|
|
|
|
|
G => ['UNSUPPORTED'], |
56
|
|
|
|
|
|
|
g => ['UNSUPPORTED'], |
57
|
|
|
|
|
|
|
H => [hour24 => ['[01][0-9]','2[0-3]'] ], |
58
|
|
|
|
|
|
|
h => [extend => q{%B} ], |
59
|
|
|
|
|
|
|
I => [hour12 => ['0[1-9]', '1[0-2]'] ], |
60
|
|
|
|
|
|
|
j => [day365 => ['00[1-9]', '0[1-9][0-9]', '[12][0-9][0-9]','3[0-5][0-9]','36[0-6]'] ], |
61
|
|
|
|
|
|
|
k => [hour24 => ['[ 1][0-9]','2[0-3]'] ], |
62
|
|
|
|
|
|
|
l => [hour12 => [' [1-9]', '1[0-2]'] ], |
63
|
|
|
|
|
|
|
M => [minute => q{[0-5][0-9]} ], |
64
|
|
|
|
|
|
|
m => [month => ['0[1-9]','1[0-2]'] ], |
65
|
|
|
|
|
|
|
n => [SKIP => q{\s+} ], |
66
|
|
|
|
|
|
|
p => [localed_pm => sub { |
67
|
|
|
|
|
|
|
my $self = shift; |
68
|
|
|
|
|
|
|
unless (exists $self->{format_table}{localed_pm}) { |
69
|
|
|
|
|
|
|
for my $pm (0, 1) { |
70
|
|
|
|
|
|
|
my $key = $self->{locale}->am_pm_abbreviated->[$pm]; |
71
|
|
|
|
|
|
|
$self->{format_table}{localed_pm}{$key} = $pm; |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
return [map quotemeta, keys %{ $self->{format_table}{localed_pm} }]; |
75
|
|
|
|
|
|
|
}], |
76
|
|
|
|
|
|
|
R => [extend => q{%H:%M} ], |
77
|
|
|
|
|
|
|
r => [extend => q{%I:%M:%S %p} ], |
78
|
|
|
|
|
|
|
S => [second => ['[0-5][0-9]','60'] ], |
79
|
|
|
|
|
|
|
s => [epoch => q{[0-9]+} ], |
80
|
|
|
|
|
|
|
T => [extend => q{%H:%M:%S} ], |
81
|
|
|
|
|
|
|
t => [char => "\t" ], |
82
|
|
|
|
|
|
|
U => ['UNSUPPORTED'], |
83
|
|
|
|
|
|
|
u => ['UNSUPPORTED'], |
84
|
|
|
|
|
|
|
V => ['UNSUPPORTED'], |
85
|
|
|
|
|
|
|
v => [extend => q{%e-%b-%Y} ], |
86
|
|
|
|
|
|
|
W => ['UNSUPPORTED'], |
87
|
|
|
|
|
|
|
w => ['UNSUPPORTED'], |
88
|
|
|
|
|
|
|
X => ['UNSUPPORTED'], |
89
|
|
|
|
|
|
|
x => ['UNSUPPORTED'], |
90
|
|
|
|
|
|
|
Y => [year => q{[0-9]{4}}], |
91
|
|
|
|
|
|
|
y => ['UNSUPPORTED'], |
92
|
|
|
|
|
|
|
Z => [timezone => ['[-A-Z0-9]+', '[A-Z][a-z]+(?:/[A-Z][a-z]+)+']], |
93
|
|
|
|
|
|
|
z => [offset => q{[-+][0-9]{4}}], |
94
|
|
|
|
|
|
|
); |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
our %FIXED_OFFSET = ( |
97
|
|
|
|
|
|
|
GMT => 0, |
98
|
|
|
|
|
|
|
UTC => 0, |
99
|
|
|
|
|
|
|
Z => 0, |
100
|
|
|
|
|
|
|
); |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub new { |
103
|
23
|
|
|
23
|
1
|
39898
|
my ($class, $format, $options) = @_; |
104
|
23
|
|
100
|
|
|
88
|
$options ||= +{}; |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
my $self = bless +{ |
107
|
|
|
|
|
|
|
format => $format, |
108
|
|
|
|
|
|
|
time_zone => Time::Strptime::TimeZone->new($options->{time_zone}), |
109
|
|
|
|
|
|
|
locale => DateTime::Locale->load($options->{locale} || 'C'), |
110
|
|
|
|
|
|
|
strict => $options->{strict} || 0, |
111
|
|
|
|
|
|
|
_handler => +{ |
112
|
|
|
|
|
|
|
%DEFAULT_HANDLER, |
113
|
23
|
50
|
100
|
|
|
120
|
%{ $options->{handler} || {} }, |
|
23
|
|
50
|
|
|
4777
|
|
114
|
|
|
|
|
|
|
}, |
115
|
|
|
|
|
|
|
} => $class; |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# compile and cache |
118
|
23
|
|
|
|
|
107
|
$self->_parser(); |
119
|
|
|
|
|
|
|
|
120
|
23
|
|
|
|
|
71
|
return $self; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub parse { |
124
|
23
|
|
|
23
|
1
|
43
|
my $self = shift; |
125
|
23
|
|
|
|
|
47
|
goto $self->_parser; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub _parser { |
129
|
46
|
|
|
46
|
|
77
|
my $self = shift; |
130
|
46
|
|
66
|
|
|
573
|
return $self->{_parser} ||= $self->_compile_format; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub _compile_format { |
134
|
23
|
|
|
23
|
|
35
|
my $self = shift; |
135
|
23
|
|
|
|
|
45
|
my $format = $self->{format}; |
136
|
|
|
|
|
|
|
|
137
|
23
|
|
|
|
|
43
|
my $parser = do { |
138
|
|
|
|
|
|
|
# setlocale |
139
|
23
|
|
|
|
|
33
|
my $time_zone = $self->{time_zone}; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
# assemble format to regexp |
142
|
23
|
|
|
|
|
39
|
my $handlers = join '', keys %{ $self->{_handler} }; |
|
23
|
|
|
|
|
156
|
|
143
|
23
|
|
|
|
|
60
|
my @types; |
144
|
23
|
|
|
|
|
257
|
$format =~ s{([^%]*)?%([${handlers}])([^%]*)?}{ |
145
|
95
|
|
100
|
|
|
392
|
my $prefix = quotemeta($1||''); |
146
|
95
|
|
100
|
|
|
272
|
my $suffix = quotemeta($3||''); |
147
|
95
|
|
|
|
|
211
|
$prefix.$self->_assemble_format($2, \@types).$suffix |
148
|
|
|
|
|
|
|
}geo; |
149
|
105
|
|
|
|
|
215
|
my %types_table = map { $_ => 1 } map { |
150
|
23
|
|
|
|
|
56
|
my $t = $_; |
|
105
|
|
|
|
|
137
|
|
151
|
105
|
|
|
|
|
154
|
$t =~ s/^localed_//; |
152
|
105
|
|
|
|
|
191
|
$t; |
153
|
|
|
|
|
|
|
} @types; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# define vars |
156
|
158
|
|
|
|
|
316
|
my $vars = join ', ', uniq map { '$'.$_ } map { |
157
|
23
|
|
|
|
|
56
|
my $t = $_; |
|
151
|
|
|
|
|
218
|
|
158
|
151
|
100
|
|
|
|
307
|
$t =~ s/^localed_// ? ($_, $t) : $_; |
159
|
|
|
|
|
|
|
} @types, 'offset', 'epoch'; |
160
|
23
|
|
|
|
|
572
|
my $captures = join ', ', map { '$'.$_ } @types; |
|
105
|
|
|
|
|
192
|
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# generate base src |
163
|
23
|
|
|
|
|
47
|
local $" = ' '; |
164
|
23
|
|
|
|
|
67
|
my $parser_src = <<EOD; |
165
|
|
|
|
|
|
|
my ($vars); |
166
|
|
|
|
|
|
|
\$offset = 0; |
167
|
|
|
|
|
|
|
sub { |
168
|
|
|
|
|
|
|
($captures) = \$_[0] =~ m{^$format\$} |
169
|
|
|
|
|
|
|
or Carp::croak 'cannot parse datetime. text: "'.\$_[0].'", format: '.\%s; |
170
|
|
|
|
|
|
|
\%s |
171
|
|
|
|
|
|
|
(\$epoch, \$offset); |
172
|
|
|
|
|
|
|
}; |
173
|
|
|
|
|
|
|
EOD |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# generate formatter src |
176
|
23
|
|
|
|
|
39
|
my $formatter_src = ''; |
177
|
23
|
|
|
|
|
50
|
for my $type (@types) { |
178
|
105
|
|
|
|
|
194
|
$formatter_src .= $self->_gen_stash_initialize_src($type); |
179
|
|
|
|
|
|
|
} |
180
|
23
|
|
|
|
|
59
|
$formatter_src .= $self->_gen_calc_epoch_src(\%types_table); |
181
|
23
|
|
|
|
|
72
|
$formatter_src .= $self->_gen_calc_offset_src(\%types_table); |
182
|
|
|
|
|
|
|
|
183
|
23
|
|
|
|
|
206
|
my $combined_src = sprintf $parser_src, B::perlstring(B::perlstring($self->{format})), $formatter_src; |
184
|
23
|
|
|
|
|
60
|
$self->{parser_src} = $combined_src; |
185
|
23
|
|
|
|
|
36
|
warn encode_utf8 "[DEBUG] src: $combined_src" if DEBUG; |
186
|
|
|
|
|
|
|
|
187
|
23
|
|
100
|
|
|
89
|
my $format_table = $self->{format_table} || {}; |
188
|
23
|
|
|
|
|
4549
|
eval $combined_src; ## no critic |
189
|
|
|
|
|
|
|
}; |
190
|
23
|
50
|
|
|
|
80
|
die $@ if $@; |
191
|
|
|
|
|
|
|
|
192
|
23
|
|
|
|
|
89
|
return $parser; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
sub _assemble_format { |
196
|
127
|
|
|
127
|
|
310
|
my ($self, $c, $types) = @_; |
197
|
127
|
|
|
|
|
214
|
my ($type, $val) = @{ $self->{_handler}->{$c} }; |
|
127
|
|
|
|
|
273
|
|
198
|
127
|
50
|
|
|
|
287
|
die "unsupported: \%$c. patches welcome :)" if $type eq 'UNSUPPORTED'; |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# normalize |
201
|
127
|
100
|
|
|
|
259
|
if (ref $val) { |
202
|
69
|
100
|
|
|
|
157
|
$val = $self->$val($type) if ref $val eq 'CODE'; |
203
|
69
|
50
|
|
|
|
568
|
$val = join '|', @$val if ref $val eq 'ARRAY'; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
# assemble to regexp |
207
|
127
|
100
|
|
|
|
260
|
if ($type eq 'extend') { |
208
|
14
|
|
|
|
|
25
|
my $handlers = join '', keys %{ $self->{_handler} }; |
|
14
|
|
|
|
|
73
|
|
209
|
14
|
|
|
|
|
542
|
$val =~ s{([^%]*)?%([${handlers}])([^%]*)?}{ |
210
|
32
|
|
50
|
|
|
143
|
my $prefix = quotemeta($1||''); |
211
|
32
|
|
100
|
|
|
96
|
my $suffix = quotemeta($3||''); |
212
|
32
|
|
|
|
|
73
|
$prefix.$self->_assemble_format($2, $types).$suffix |
213
|
|
|
|
|
|
|
}ge; |
214
|
14
|
|
|
|
|
69
|
return $val; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
else { |
217
|
113
|
100
|
|
|
|
243
|
return "(?:$val)" if $type eq 'SKIP'; |
218
|
109
|
100
|
|
|
|
223
|
return quotemeta $val if $type eq 'char'; |
219
|
|
|
|
|
|
|
|
220
|
105
|
|
|
|
|
158
|
push @$types => $type; |
221
|
105
|
|
|
|
|
480
|
return "($val)"; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub _gen_stash_initialize_src { |
226
|
105
|
|
|
105
|
|
195
|
my ($self, $type) = @_; |
227
|
|
|
|
|
|
|
|
228
|
105
|
50
|
|
|
|
237
|
if ($type eq 'timezone') { |
|
|
100
|
|
|
|
|
|
229
|
0
|
|
|
|
|
0
|
return <<'EOD'; |
230
|
|
|
|
|
|
|
$time_zone->set_timezone($timezone); |
231
|
|
|
|
|
|
|
EOD |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
elsif ($type =~ /^localed_([a-z]+)$/) { |
234
|
7
|
|
|
|
|
31
|
return <<EOD; |
235
|
|
|
|
|
|
|
\$${1} = \$format_table->{localed_${1}}->{\$localed_${1}}; |
236
|
|
|
|
|
|
|
EOD |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
else { |
239
|
98
|
|
|
|
|
194
|
return ''; # default: none |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub _gen_calc_epoch_src { |
244
|
23
|
|
|
23
|
|
44
|
my ($self, $types_table) = @_; |
245
|
|
|
|
|
|
|
|
246
|
23
|
50
|
|
|
|
55
|
my $timegm = $self->{strict} ? 'timegm' : 'timegm_nocheck'; |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# hour24&minute&second |
249
|
|
|
|
|
|
|
# year&day365 or year&month&day |
250
|
23
|
100
|
|
|
|
56
|
my $second = $types_table->{second} ? '$second' : 0; |
251
|
23
|
100
|
|
|
|
49
|
my $minute = $types_table->{minute} ? '$minute' : 0; |
252
|
23
|
|
|
|
|
51
|
my $hour = $self->_gen_calc_hour_src($types_table); |
253
|
23
|
100
|
33
|
|
|
131
|
if ($types_table->{epoch}) { |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
33
|
|
|
|
|
|
|
50
|
33
|
|
|
|
|
254
|
3
|
|
|
|
|
7
|
return ''; # nothing to do |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
elsif ($types_table->{year} && $types_table->{month} && $types_table->{day}) { |
257
|
16
|
|
|
|
|
54
|
return <<EOD; |
258
|
|
|
|
|
|
|
\$epoch = $timegm($second, $minute, $hour, \$day, \$month - 1, \$year); |
259
|
|
|
|
|
|
|
EOD |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
elsif ($types_table->{year} && $types_table->{month}) { |
262
|
1
|
|
|
|
|
5
|
return <<EOD; |
263
|
|
|
|
|
|
|
\$epoch = $timegm($second, $minute, $hour, 1, \$month - 1, \$year); |
264
|
|
|
|
|
|
|
EOD |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
elsif ($types_table->{year} && $types_table->{day365}) { |
267
|
3
|
|
|
|
|
11
|
return <<EOD; |
268
|
|
|
|
|
|
|
\$epoch = $timegm($second, $minute, $hour, 1, 0, \$year) + (\$day365 - 1) * 60 * 60 * 24; |
269
|
|
|
|
|
|
|
EOD |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
|
272
|
0
|
|
|
|
|
0
|
die 'unknown case. types: '. join ', ', keys %$types_table; |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
sub _gen_calc_offset_src { |
276
|
23
|
|
|
23
|
|
43
|
my ($self, $types_table) = @_; |
277
|
|
|
|
|
|
|
|
278
|
23
|
|
|
|
|
37
|
my $src = ''; |
279
|
|
|
|
|
|
|
|
280
|
23
|
100
|
|
|
|
63
|
my $second = $types_table->{second} ? '$second' : 0; |
281
|
23
|
100
|
|
|
|
47
|
my $minute = $types_table->{minute} ? '$minute' : 0; |
282
|
23
|
|
|
|
|
42
|
my $hour = $self->_gen_calc_hour_src($types_table); |
283
|
|
|
|
|
|
|
|
284
|
23
|
|
|
|
|
51
|
my $fixed_offset = $self->_fixed_offset($types_table); |
285
|
23
|
100
|
|
|
|
103
|
if (defined $fixed_offset) { |
|
|
50
|
|
|
|
|
|
286
|
20
|
50
|
|
|
|
62
|
if ($fixed_offset != 0) { |
287
|
0
|
|
|
|
|
0
|
$src .= sprintf <<'EOD', $fixed_offset; |
288
|
|
|
|
|
|
|
$offset -= %d; |
289
|
|
|
|
|
|
|
EOD |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
elsif ($types_table->{offset}) { |
293
|
3
|
|
|
|
|
8
|
$src .= <<'EOD'; |
294
|
|
|
|
|
|
|
$offset = (abs($offset) == $offset ? 1 : -1) * (60 * 60 * substr($offset, 1, 2) + 60 * substr($offset, 3, 2)); |
295
|
|
|
|
|
|
|
EOD |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
else { |
298
|
0
|
|
|
|
|
0
|
$src .= <<EOD; |
299
|
|
|
|
|
|
|
\$offset = \$time_zone->offset(\$epoch); |
300
|
|
|
|
|
|
|
EOD |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
23
|
50
|
66
|
|
|
62
|
if (!defined $fixed_offset && !$types_table->{epoch}) { |
304
|
0
|
|
|
|
|
0
|
$src .= <<'EOD' |
305
|
|
|
|
|
|
|
$epoch -= $offset; |
306
|
|
|
|
|
|
|
EOD |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
|
309
|
23
|
|
|
|
|
51
|
return $src; |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub _gen_calc_hour_src { |
313
|
46
|
|
|
46
|
|
74
|
my ($self, $types_table) = @_; |
314
|
|
|
|
|
|
|
|
315
|
46
|
100
|
66
|
|
|
132
|
if ($types_table->{hour24}) { |
|
|
100
|
|
|
|
|
|
316
|
18
|
|
|
|
|
37
|
return '$hour24'; |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
elsif ($types_table->{hour12} && $types_table->{pm}) { |
319
|
8
|
|
|
|
|
18
|
return '(0,12)[$pm] + ($hour12 % 12)'; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
else { |
322
|
20
|
|
|
|
|
36
|
return '0'; |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
sub _fixed_offset { |
327
|
23
|
|
|
23
|
|
34
|
my ($self, $types_table) = @_; |
328
|
23
|
100
|
|
|
|
58
|
return if $types_table->{offset}; |
329
|
20
|
50
|
|
|
|
44
|
return if $types_table->{timezone}; |
330
|
20
|
50
|
|
|
|
77
|
return if not exists $FIXED_OFFSET{$self->{time_zone}->name}; |
331
|
20
|
|
|
|
|
121
|
return $FIXED_OFFSET{$self->{time_zone}->name}; |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
1; |
335
|
|
|
|
|
|
|
__END__ |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=encoding utf-8 |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=for stopwords strptime |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=head1 NAME |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
Time::Strptime::Format - L<strptime(3)> format compiler and parser. |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=head1 SYNOPSIS |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
use Time::Strptime::Format; |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
# OO style |
350
|
|
|
|
|
|
|
my $fmt = Time::Strptime::Format->new('%Y-%m-%d %H:%M:%S'); |
351
|
|
|
|
|
|
|
my ($epoch_o, $offset_o) = $fmt->parse('2014-01-01 00:00:00'); |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
=head1 DESCRIPTION |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
This is L<Time::Strptime> engine. |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=head1 METHODS |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
This class offers the following methods. |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
=head2 Time::Strptime::Format->new($format, \%args) |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
This methods creates a new format object. It accepts the following arguments: |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=over 4 |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=item * time_zone |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
The default time zone to use for objects returned from parsing. |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
=item * locale |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
The locale to use for objects returned from parsing. |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
=item * strict |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
Strict range check for date and time. |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
Example. C<"2016-02-31"> is wrong date string, but Time::Strptime parses as C<2016-02-31> in default. |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
=back |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=head2 $strptime->parse($string) |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
Given a string in the pattern specified in the constructor, this method will return the epoch and offset. |
386
|
|
|
|
|
|
|
If given a string that doesn't match the pattern, the formatter will throw the error. |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=head1 STRPTIME PATTERN TOKENS |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
The following tokens are allowed in the pattern string for strptime: |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
=over 4 |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
=item * %% |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
The % character. |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
=item * %a or %A |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
The weekday name according to the current locale, in abbreviated form or the full name. (ignored) |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=item * %b or %B or %h |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
The month name according to the current locale, in abbreviated form or the full name. |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
=item * %d or %e |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
The day of month (01-31). This will parse single digit numbers as well. |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=item * %D |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
Equivalent to %m/%d/%y. (This is the American style date, very confusing to non-Americans, especially since %d/%m/%y is widely used in Europe. The ISO 8601 standard pattern is %F.) |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
=item * %F |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
Equivalent to %Y-%m-%d. (This is the ISO style date) |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=item * %H |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
The hour (00-23). This will parse single digit numbers as well. |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
=item * %I |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
The hour on a 12-hour clock (1-12). |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
=item * %j |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
The day number in the year (1-366). |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
=item * %m |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
The month number (01-12). This will parse single digit numbers as well. |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
=item * %M |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
The minute (00-59). This will parse single digit numbers as well. |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=item * %n |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
Arbitrary white-space. (ignored) |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
=item * %p |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
The equivalent of AM or PM according to the locale in use. (See L<DateTime::Locale>) |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
=item * %r |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
Equivalent to %I:%M:%S %p. |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
=item * %R |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
Equivalent to %H:%M. |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=item * %s |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
Number of seconds since the Epoch. |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
=item * %S |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
The second (0-60; 60 may occur for leap seconds.). |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
=item * %t |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
Tab space. (ignored) |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
=item * %T |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
Equivalent to %H:%M:%S. |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
=item * %Y |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
A 4-digit year, including century (for example, 1991). |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=item * %z |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
An RFC-822/ISO 8601 standard time zone specification. (e.g. +1100) |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
=item * %Z |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
The time zone name. (e.g. EST) |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
=back |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
=head1 LICENSE |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
Copyright (C) karupanerura. |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
489
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
=head1 AUTHOR |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
karupanerura E<lt>karupa@cpan.orgE<gt> |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
=cut |