line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package DateTime::Format::Strptime; |
2
|
|
|
|
|
|
|
|
3
|
12
|
|
|
12
|
|
1282622
|
use strict; |
|
12
|
|
|
|
|
141
|
|
|
12
|
|
|
|
|
356
|
|
4
|
12
|
|
|
12
|
|
75
|
use warnings; |
|
12
|
|
|
|
|
26
|
|
|
12
|
|
|
|
|
652
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '1.77'; |
7
|
|
|
|
|
|
|
|
8
|
12
|
|
|
12
|
|
87
|
use Carp qw( carp croak ); |
|
12
|
|
|
|
|
24
|
|
|
12
|
|
|
|
|
758
|
|
9
|
12
|
|
|
12
|
|
11232
|
use DateTime 1.00; |
|
12
|
|
|
|
|
6114609
|
|
|
12
|
|
|
|
|
685
|
|
10
|
12
|
|
|
12
|
|
126
|
use DateTime::Locale 1.23; |
|
12
|
|
|
|
|
200
|
|
|
12
|
|
|
|
|
327
|
|
11
|
12
|
|
|
12
|
|
6599
|
use DateTime::Format::Strptime::Types; |
|
12
|
|
|
|
|
43
|
|
|
12
|
|
|
|
|
122
|
|
12
|
12
|
|
|
12
|
|
217065
|
use DateTime::TimeZone 2.09; |
|
12
|
|
|
|
|
408
|
|
|
12
|
|
|
|
|
322
|
|
13
|
12
|
|
|
12
|
|
77
|
use Exporter (); |
|
12
|
|
|
|
|
31
|
|
|
12
|
|
|
|
|
320
|
|
14
|
12
|
|
|
12
|
|
190
|
use Params::ValidationCompiler qw( validation_for ); |
|
12
|
|
|
|
|
34
|
|
|
12
|
|
|
|
|
757
|
|
15
|
12
|
|
|
12
|
|
115
|
use Try::Tiny; |
|
12
|
|
|
|
|
28
|
|
|
12
|
|
|
|
|
1254
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our @EXPORT_OK = qw( strftime strptime ); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
## no critic (ValuesAndExpressions::ProhibitConstantPragma) |
20
|
12
|
|
|
12
|
|
99
|
use constant PERL_58 => $] < 5.010; |
|
12
|
|
|
|
|
27
|
|
|
12
|
|
|
|
|
65838
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# We previously used Package::DeprecationManager which allowed passing of |
23
|
|
|
|
|
|
|
# "-api_version => X" on import. We don't want any such imports to blow up but |
24
|
|
|
|
|
|
|
# we no longer have anything to deprecate. |
25
|
|
|
|
|
|
|
sub import { |
26
|
14
|
|
|
14
|
|
2646
|
my $class = shift; |
27
|
14
|
|
|
|
|
31
|
my @args; |
28
|
|
|
|
|
|
|
## no critic (ControlStructures::ProhibitCStyleForLoops) |
29
|
14
|
|
|
|
|
79
|
for ( my $i = 0; $i < @_; $i++ ) { |
30
|
3
|
100
|
|
|
|
10
|
if ( $_[$i] eq '-api_version' ) { |
31
|
1
|
|
|
|
|
3
|
$i++; |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
else { |
34
|
2
|
|
|
|
|
6
|
push @args, $_[$i]; |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
} |
37
|
14
|
|
|
|
|
43
|
@_ = ( $class, @args ); |
38
|
14
|
|
|
|
|
14095
|
goto &Exporter::import; |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
{ |
42
|
|
|
|
|
|
|
my $en_locale = DateTime::Locale->load('en'); |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
my $validator = validation_for( |
45
|
|
|
|
|
|
|
params => { |
46
|
|
|
|
|
|
|
pattern => { type => t('NonEmptyStr') }, |
47
|
|
|
|
|
|
|
time_zone => { |
48
|
|
|
|
|
|
|
type => t('TimeZone'), |
49
|
|
|
|
|
|
|
optional => 1, |
50
|
|
|
|
|
|
|
}, |
51
|
|
|
|
|
|
|
zone_map => { |
52
|
|
|
|
|
|
|
type => t('HashRef'), |
53
|
|
|
|
|
|
|
default => sub { {} }, |
54
|
|
|
|
|
|
|
}, |
55
|
|
|
|
|
|
|
locale => { |
56
|
|
|
|
|
|
|
type => t('Locale'), |
57
|
|
|
|
|
|
|
default => sub {$en_locale}, |
58
|
|
|
|
|
|
|
}, |
59
|
|
|
|
|
|
|
on_error => { |
60
|
|
|
|
|
|
|
type => t('OnError'), |
61
|
|
|
|
|
|
|
default => 'undef', |
62
|
|
|
|
|
|
|
}, |
63
|
|
|
|
|
|
|
strict => { |
64
|
|
|
|
|
|
|
type => t('Bool'), |
65
|
|
|
|
|
|
|
default => 0, |
66
|
|
|
|
|
|
|
}, |
67
|
|
|
|
|
|
|
debug => { |
68
|
|
|
|
|
|
|
type => t('Bool'), |
69
|
|
|
|
|
|
|
default => $ENV{DATETIME_FORMAT_STRPTIME_DEBUG}, |
70
|
|
|
|
|
|
|
}, |
71
|
|
|
|
|
|
|
}, |
72
|
|
|
|
|
|
|
); |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub new { |
75
|
294
|
|
|
294
|
1
|
1483696
|
my $class = shift; |
76
|
294
|
|
|
|
|
7372
|
my %args = $validator->(@_); |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
my $self = bless { |
79
|
|
|
|
|
|
|
%args, |
80
|
294
|
|
|
|
|
8330
|
zone_map => $class->_build_zone_map( $args{zone_map} ), |
81
|
|
|
|
|
|
|
}, $class; |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# Forces a check that the pattern is valid |
84
|
294
|
|
|
|
|
1277
|
$self->_parser; |
85
|
|
|
|
|
|
|
|
86
|
293
|
50
|
|
|
|
9636
|
if ( $self->{debug} ) { |
87
|
0
|
0
|
|
|
|
0
|
binmode STDERR, ':encoding(UTF-8)' or die $!; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
293
|
|
|
|
|
3538
|
return $self; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
{ |
95
|
|
|
|
|
|
|
my %zone_map = ( |
96
|
|
|
|
|
|
|
'A' => '+0100', 'ACDT' => '+1030', 'ACST' => '+0930', |
97
|
|
|
|
|
|
|
'ADT' => undef, 'AEDT' => '+1100', 'AES' => '+1000', |
98
|
|
|
|
|
|
|
'AEST' => '+1000', 'AFT' => '+0430', 'AHDT' => '-0900', |
99
|
|
|
|
|
|
|
'AHST' => '-1000', 'AKDT' => '-0800', 'AKST' => '-0900', |
100
|
|
|
|
|
|
|
'AMST' => '+0400', 'AMT' => '+0400', 'ANAST' => '+1300', |
101
|
|
|
|
|
|
|
'ANAT' => '+1200', 'ART' => '-0300', 'AST' => undef, |
102
|
|
|
|
|
|
|
'AT' => '-0100', 'AWST' => '+0800', 'AZOST' => '+0000', |
103
|
|
|
|
|
|
|
'AZOT' => '-0100', 'AZST' => '+0500', 'AZT' => '+0400', |
104
|
|
|
|
|
|
|
'B' => '+0200', 'BADT' => '+0400', 'BAT' => '+0600', |
105
|
|
|
|
|
|
|
'BDST' => '+0200', 'BDT' => '+0600', 'BET' => '-1100', |
106
|
|
|
|
|
|
|
'BNT' => '+0800', 'BORT' => '+0800', 'BOT' => '-0400', |
107
|
|
|
|
|
|
|
'BRA' => '-0300', 'BST' => undef, 'BT' => undef, |
108
|
|
|
|
|
|
|
'BTT' => '+0600', 'C' => '+0300', 'CAST' => '+0930', |
109
|
|
|
|
|
|
|
'CAT' => undef, 'CCT' => undef, 'CDT' => undef, |
110
|
|
|
|
|
|
|
'CEST' => '+0200', 'CET' => '+0100', 'CETDST' => '+0200', |
111
|
|
|
|
|
|
|
'CHADT' => '+1345', 'CHAST' => '+1245', 'CKT' => '-1000', |
112
|
|
|
|
|
|
|
'CLST' => '-0300', 'CLT' => '-0400', 'COT' => '-0500', |
113
|
|
|
|
|
|
|
'CST' => undef, 'CSuT' => '+1030', 'CUT' => '+0000', |
114
|
|
|
|
|
|
|
'CVT' => '-0100', 'CXT' => '+0700', 'ChST' => '+1000', |
115
|
|
|
|
|
|
|
'D' => '+0400', 'DAVT' => '+0700', 'DDUT' => '+1000', |
116
|
|
|
|
|
|
|
'DNT' => '+0100', 'DST' => '+0200', 'E' => '+0500', |
117
|
|
|
|
|
|
|
'EASST' => '-0500', 'EAST' => undef, 'EAT' => '+0300', |
118
|
|
|
|
|
|
|
'ECT' => undef, 'EDT' => undef, 'EEST' => '+0300', |
119
|
|
|
|
|
|
|
'EET' => '+0200', 'EETDST' => '+0300', 'EGST' => '+0000', |
120
|
|
|
|
|
|
|
'EGT' => '-0100', 'EMT' => '+0100', 'EST' => undef, |
121
|
|
|
|
|
|
|
'ESuT' => '+1100', 'F' => '+0600', 'FDT' => undef, |
122
|
|
|
|
|
|
|
'FJST' => '+1300', 'FJT' => '+1200', 'FKST' => '-0300', |
123
|
|
|
|
|
|
|
'FKT' => '-0400', 'FST' => undef, 'FWT' => '+0100', |
124
|
|
|
|
|
|
|
'G' => '+0700', 'GALT' => '-0600', 'GAMT' => '-0900', |
125
|
|
|
|
|
|
|
'GEST' => '+0500', 'GET' => '+0400', 'GFT' => '-0300', |
126
|
|
|
|
|
|
|
'GILT' => '+1200', 'GMT' => '+0000', 'GST' => undef, |
127
|
|
|
|
|
|
|
'GT' => '+0000', 'GYT' => '-0400', 'GZ' => '+0000', |
128
|
|
|
|
|
|
|
'H' => '+0800', 'HAA' => '-0300', 'HAC' => '-0500', |
129
|
|
|
|
|
|
|
'HAE' => '-0400', 'HAP' => '-0700', 'HAR' => '-0600', |
130
|
|
|
|
|
|
|
'HAT' => '-0230', 'HAY' => '-0800', 'HDT' => '-0930', |
131
|
|
|
|
|
|
|
'HFE' => '+0200', 'HFH' => '+0100', 'HG' => '+0000', |
132
|
|
|
|
|
|
|
'HKT' => '+0800', 'HL' => 'local', 'HNA' => '-0400', |
133
|
|
|
|
|
|
|
'HNC' => '-0600', 'HNE' => '-0500', 'HNP' => '-0800', |
134
|
|
|
|
|
|
|
'HNR' => '-0700', 'HNT' => '-0330', 'HNY' => '-0900', |
135
|
|
|
|
|
|
|
'HOE' => '+0100', 'HST' => '-1000', 'I' => '+0900', |
136
|
|
|
|
|
|
|
'ICT' => '+0700', 'IDLE' => '+1200', 'IDLW' => '-1200', |
137
|
|
|
|
|
|
|
'IDT' => undef, 'IOT' => '+0500', 'IRDT' => '+0430', |
138
|
|
|
|
|
|
|
'IRKST' => '+0900', 'IRKT' => '+0800', 'IRST' => '+0430', |
139
|
|
|
|
|
|
|
'IRT' => '+0330', 'IST' => undef, 'IT' => '+0330', |
140
|
|
|
|
|
|
|
'ITA' => '+0100', 'JAVT' => '+0700', 'JAYT' => '+0900', |
141
|
|
|
|
|
|
|
'JST' => '+0900', 'JT' => '+0700', 'K' => '+1000', |
142
|
|
|
|
|
|
|
'KDT' => '+1000', 'KGST' => '+0600', 'KGT' => '+0500', |
143
|
|
|
|
|
|
|
'KOST' => '+1200', 'KRAST' => '+0800', 'KRAT' => '+0700', |
144
|
|
|
|
|
|
|
'KST' => '+0900', 'L' => '+1100', 'LHDT' => '+1100', |
145
|
|
|
|
|
|
|
'LHST' => '+1030', 'LIGT' => '+1000', 'LINT' => '+1400', |
146
|
|
|
|
|
|
|
'LKT' => '+0600', 'LST' => 'local', 'LT' => 'local', |
147
|
|
|
|
|
|
|
'M' => '+1200', 'MAGST' => '+1200', 'MAGT' => '+1100', |
148
|
|
|
|
|
|
|
'MAL' => '+0800', 'MART' => '-0930', 'MAT' => '+0300', |
149
|
|
|
|
|
|
|
'MAWT' => '+0600', 'MDT' => '-0600', 'MED' => '+0200', |
150
|
|
|
|
|
|
|
'MEDST' => '+0200', 'MEST' => '+0200', 'MESZ' => '+0200', |
151
|
|
|
|
|
|
|
'MET' => undef, 'MEWT' => '+0100', 'MEX' => '-0600', |
152
|
|
|
|
|
|
|
'MEZ' => '+0100', 'MHT' => '+1200', 'MMT' => '+0630', |
153
|
|
|
|
|
|
|
'MPT' => '+1000', 'MSD' => '+0400', 'MSK' => '+0300', |
154
|
|
|
|
|
|
|
'MSKS' => '+0400', 'MST' => '-0700', 'MT' => '+0830', |
155
|
|
|
|
|
|
|
'MUT' => '+0400', 'MVT' => '+0500', 'MYT' => '+0800', |
156
|
|
|
|
|
|
|
'N' => '-0100', 'NCT' => '+1100', 'NDT' => '-0230', |
157
|
|
|
|
|
|
|
'NFT' => undef, 'NOR' => '+0100', 'NOVST' => '+0700', |
158
|
|
|
|
|
|
|
'NOVT' => '+0600', 'NPT' => '+0545', 'NRT' => '+1200', |
159
|
|
|
|
|
|
|
'NST' => undef, 'NSUT' => '+0630', 'NT' => '-1100', |
160
|
|
|
|
|
|
|
'NUT' => '-1100', 'NZDT' => '+1300', 'NZST' => '+1200', |
161
|
|
|
|
|
|
|
'NZT' => '+1200', 'O' => '-0200', 'OESZ' => '+0300', |
162
|
|
|
|
|
|
|
'OEZ' => '+0200', 'OMSST' => '+0700', 'OMST' => '+0600', |
163
|
|
|
|
|
|
|
'OZ' => 'local', 'P' => '-0300', 'PDT' => '-0700', |
164
|
|
|
|
|
|
|
'PET' => '-0500', 'PETST' => '+1300', 'PETT' => '+1200', |
165
|
|
|
|
|
|
|
'PGT' => '+1000', 'PHOT' => '+1300', 'PHT' => '+0800', |
166
|
|
|
|
|
|
|
'PKT' => '+0500', 'PMDT' => '-0200', 'PMT' => '-0300', |
167
|
|
|
|
|
|
|
'PNT' => '-0830', 'PONT' => '+1100', 'PST' => undef, |
168
|
|
|
|
|
|
|
'PWT' => '+0900', 'PYST' => '-0300', 'PYT' => '-0400', |
169
|
|
|
|
|
|
|
'Q' => '-0400', 'R' => '-0500', 'R1T' => '+0200', |
170
|
|
|
|
|
|
|
'R2T' => '+0300', 'RET' => '+0400', 'ROK' => '+0900', |
171
|
|
|
|
|
|
|
'S' => '-0600', 'SADT' => '+1030', 'SAST' => undef, |
172
|
|
|
|
|
|
|
'SBT' => '+1100', 'SCT' => '+0400', 'SET' => '+0100', |
173
|
|
|
|
|
|
|
'SGT' => '+0800', 'SRT' => '-0300', 'SST' => undef, |
174
|
|
|
|
|
|
|
'SWT' => '+0100', 'T' => '-0700', 'TFT' => '+0500', |
175
|
|
|
|
|
|
|
'THA' => '+0700', 'THAT' => '-1000', 'TJT' => '+0500', |
176
|
|
|
|
|
|
|
'TKT' => '-1000', 'TMT' => '+0500', 'TOT' => '+1300', |
177
|
|
|
|
|
|
|
'TRUT' => '+1000', 'TST' => '+0300', 'TUC ' => '+0000', |
178
|
|
|
|
|
|
|
'TVT' => '+1200', 'U' => '-0800', 'ULAST' => '+0900', |
179
|
|
|
|
|
|
|
'ULAT' => '+0800', 'USZ1' => '+0200', 'USZ1S' => '+0300', |
180
|
|
|
|
|
|
|
'USZ3' => '+0400', 'USZ3S' => '+0500', 'USZ4' => '+0500', |
181
|
|
|
|
|
|
|
'USZ4S' => '+0600', 'USZ5' => '+0600', 'USZ5S' => '+0700', |
182
|
|
|
|
|
|
|
'USZ6' => '+0700', 'USZ6S' => '+0800', 'USZ7' => '+0800', |
183
|
|
|
|
|
|
|
'USZ7S' => '+0900', 'USZ8' => '+0900', 'USZ8S' => '+1000', |
184
|
|
|
|
|
|
|
'USZ9' => '+1000', 'USZ9S' => '+1100', 'UTZ' => '-0300', |
185
|
|
|
|
|
|
|
'UYT' => '-0300', 'UZ10' => '+1100', 'UZ10S' => '+1200', |
186
|
|
|
|
|
|
|
'UZ11' => '+1200', 'UZ11S' => '+1300', 'UZ12' => '+1200', |
187
|
|
|
|
|
|
|
'UZ12S' => '+1300', 'UZT' => '+0500', 'V' => '-0900', |
188
|
|
|
|
|
|
|
'VET' => '-0400', 'VLAST' => '+1100', 'VLAT' => '+1000', |
189
|
|
|
|
|
|
|
'VTZ' => '-0200', 'VUT' => '+1100', 'W' => '-1000', |
190
|
|
|
|
|
|
|
'WAKT' => '+1200', 'WAST' => undef, 'WAT' => '+0100', |
191
|
|
|
|
|
|
|
'WEST' => '+0100', 'WESZ' => '+0100', 'WET' => '+0000', |
192
|
|
|
|
|
|
|
'WETDST' => '+0100', 'WEZ' => '+0000', 'WFT' => '+1200', |
193
|
|
|
|
|
|
|
'WGST' => '-0200', 'WGT' => '-0300', 'WIB' => '+0700', |
194
|
|
|
|
|
|
|
'WIT' => '+0900', 'WITA' => '+0800', 'WST' => undef, |
195
|
|
|
|
|
|
|
'WTZ' => '-0100', 'WUT' => '+0100', 'X' => '-1100', |
196
|
|
|
|
|
|
|
'Y' => '-1200', 'YAKST' => '+1000', 'YAKT' => '+0900', |
197
|
|
|
|
|
|
|
'YAPT' => '+1000', 'YDT' => '-0800', 'YEKST' => '+0600', |
198
|
|
|
|
|
|
|
'YEKT' => '+0500', 'YST' => '-0900', 'Z' => '+0000', |
199
|
|
|
|
|
|
|
'UTC' => '+0000', |
200
|
|
|
|
|
|
|
); |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
for my $i ( map { sprintf( '%02d', $_ ) } 1 .. 12 ) { |
203
|
|
|
|
|
|
|
$zone_map{ '-' . $i } = '-' . $i . '00'; |
204
|
|
|
|
|
|
|
$zone_map{ '+' . $i } = '+' . $i . '00'; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
sub _build_zone_map { |
208
|
|
|
|
|
|
|
return { |
209
|
|
|
|
|
|
|
%zone_map, |
210
|
294
|
|
|
294
|
|
10728
|
%{ $_[1] }, |
|
294
|
|
|
|
|
30582
|
|
211
|
|
|
|
|
|
|
}; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub parse_datetime { |
216
|
289
|
|
|
289
|
1
|
135872
|
my $self = shift; |
217
|
289
|
|
|
|
|
566
|
my $string = shift; |
218
|
|
|
|
|
|
|
|
219
|
289
|
|
|
|
|
655
|
my $parser = $self->_parser; |
220
|
289
|
50
|
|
|
|
755
|
if ( $self->{debug} ) { |
221
|
0
|
|
|
|
|
0
|
warn "Regex for $self->{pattern}: $parser->{regex}\n"; |
222
|
0
|
|
|
|
|
0
|
warn "Fields: @{$parser->{fields}}\n"; |
|
0
|
|
|
|
|
0
|
|
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
|
225
|
289
|
|
|
|
|
3525
|
my @matches = ( $string =~ $parser->{regex} ); |
226
|
289
|
100
|
|
|
|
870
|
unless (@matches) { |
227
|
6
|
|
|
|
|
11
|
my $msg = 'Your datetime does not match your pattern'; |
228
|
6
|
50
|
|
|
|
16
|
if ( $self->{debug} ) { |
229
|
0
|
|
|
|
|
0
|
$msg .= qq{ - string = "$string" - regex = $parser->{regex}}; |
230
|
|
|
|
|
|
|
} |
231
|
6
|
|
|
|
|
13
|
$msg .= q{.}; |
232
|
6
|
|
|
|
|
19
|
$self->_our_croak($msg); |
233
|
2
|
|
|
|
|
6
|
return; |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
|
236
|
283
|
|
|
|
|
472
|
my %args; |
237
|
283
|
|
|
|
|
453
|
my $i = 0; |
238
|
283
|
|
|
|
|
421
|
for my $f ( @{ $parser->{fields} } ) { |
|
283
|
|
|
|
|
737
|
|
239
|
1111
|
50
|
|
|
|
2218
|
unless ( defined $matches[$i] ) { |
240
|
0
|
|
|
|
|
0
|
die |
241
|
|
|
|
|
|
|
"Something horrible happened - the string matched $parser->{regex}" |
242
|
0
|
|
|
|
|
0
|
. " but did not return the expected fields: [@{$parser->{fields}}]"; |
243
|
|
|
|
|
|
|
} |
244
|
1111
|
|
|
|
|
2610
|
$args{$f} = $matches[ $i++ ]; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
# We need to copy the %args here because _munge_args will delete keys in |
248
|
|
|
|
|
|
|
# order to turn this into something that can be passed to a DateTime |
249
|
|
|
|
|
|
|
# constructor. |
250
|
283
|
|
|
|
|
1486
|
my ( $constructor, $args, $post_construct ) |
251
|
|
|
|
|
|
|
= $self->_munge_args( {%args} ); |
252
|
272
|
100
|
66
|
|
|
1225
|
return unless $constructor && $args; |
253
|
|
|
|
|
|
|
|
254
|
267
|
|
|
267
|
|
1518
|
my $dt = try { DateTime->$constructor($args) }; |
|
267
|
|
|
|
|
7406
|
|
255
|
267
|
100
|
|
|
|
126885
|
$self->_our_croak('Parsed values did not produce a valid date') |
256
|
|
|
|
|
|
|
unless $dt; |
257
|
261
|
100
|
|
|
|
1741
|
if ($post_construct) { |
258
|
2
|
|
|
|
|
7
|
$post_construct->($dt); |
259
|
|
|
|
|
|
|
} |
260
|
261
|
100
|
100
|
|
|
2131
|
return unless $dt && $self->_check_dt( $dt, \%args ); |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
$dt->set_time_zone( $self->{time_zone} ) |
263
|
192
|
100
|
|
|
|
477
|
if $self->{time_zone}; |
264
|
|
|
|
|
|
|
|
265
|
192
|
|
|
|
|
1469
|
return $dt; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub _parser { |
269
|
583
|
|
|
583
|
|
1000
|
my $self = shift; |
270
|
|
|
|
|
|
|
|
271
|
583
|
|
66
|
|
|
2265
|
return $self->{parser} ||= $self->_build_parser; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
sub _build_parser { |
275
|
294
|
|
|
294
|
|
487
|
my $self = shift; |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
my ( |
278
|
294
|
|
|
|
|
698
|
$replacement_tokens_re, |
279
|
|
|
|
|
|
|
$replacements, |
280
|
|
|
|
|
|
|
$pattern_tokens_re, |
281
|
|
|
|
|
|
|
$patterns, |
282
|
|
|
|
|
|
|
) = $self->_parser_pieces; |
283
|
|
|
|
|
|
|
|
284
|
294
|
|
|
|
|
1572
|
my $pattern = $self->{pattern}; |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
# When the first replacement is a glibc pattern, the first round of |
287
|
|
|
|
|
|
|
# replacements may simply replace one replacement token (like %X) with |
288
|
|
|
|
|
|
|
# another replacement token (like %I). |
289
|
294
|
|
|
|
|
3596
|
$pattern =~ s/%($replacement_tokens_re)/$replacements->{$1}/g for 1 .. 2; |
290
|
|
|
|
|
|
|
|
291
|
294
|
50
|
33
|
|
|
1049
|
if ( $self->{debug} && $pattern ne $self->{pattern} ) { |
292
|
0
|
|
|
|
|
0
|
warn "Pattern after replacement substitution: $pattern\n"; |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
294
|
|
|
|
|
514
|
my $regex = q{}; |
296
|
294
|
|
|
|
|
468
|
my @fields; |
297
|
|
|
|
|
|
|
|
298
|
294
|
|
|
|
|
2809
|
while ( |
299
|
|
|
|
|
|
|
$pattern =~ / |
300
|
|
|
|
|
|
|
\G |
301
|
|
|
|
|
|
|
%($pattern_tokens_re) |
302
|
|
|
|
|
|
|
| |
303
|
|
|
|
|
|
|
%([1-9]?)(N) |
304
|
|
|
|
|
|
|
| |
305
|
|
|
|
|
|
|
(%[0-9]*[a-zA-Z]) |
306
|
|
|
|
|
|
|
| |
307
|
|
|
|
|
|
|
([^%]+) |
308
|
|
|
|
|
|
|
/xg |
309
|
|
|
|
|
|
|
) { |
310
|
|
|
|
|
|
|
# Using \G in the regex match fails for some reason on Perl 5.8, so we |
311
|
|
|
|
|
|
|
# do this hack instead. |
312
|
1982
|
|
|
|
|
3438
|
substr( $pattern, 0, pos $pattern, q{} ) |
313
|
|
|
|
|
|
|
if PERL_58; |
314
|
1982
|
100
|
|
|
|
5450
|
if ($1) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
315
|
1141
|
50
|
|
|
|
2874
|
my $p = $patterns->{$1} |
316
|
|
|
|
|
|
|
or croak |
317
|
|
|
|
|
|
|
"Unidentified token in pattern: $1 in $self->{pattern}"; |
318
|
1141
|
100
|
|
|
|
2266
|
if ( $p->{field} ) { |
319
|
1130
|
|
|
|
|
25692
|
$regex .= qr/($p->{regex})/; |
320
|
1130
|
|
|
|
|
8734
|
push @fields, $p->{field}; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
else { |
323
|
11
|
|
|
|
|
83
|
$regex .= qr/$p->{regex}/; |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
elsif ($3) { |
327
|
6
|
100
|
|
|
|
56
|
$regex .= $2 ? qr/([0-9]{$2})/ : qr/([0-9]+)/; |
328
|
6
|
|
|
|
|
39
|
push @fields, 'nanosecond'; |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
elsif ($4) { |
331
|
1
|
|
|
|
|
268
|
croak qq{Pattern contained an unrecognized strptime token, "$4"}; |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
else { |
334
|
834
|
|
|
|
|
8127
|
$regex .= qr/\Q$5/; |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
return { |
339
|
|
|
|
|
|
|
regex => |
340
|
293
|
100
|
|
|
|
9494
|
( $self->{strict} ? qr/(?:\A|\b)$regex(?:\b|\Z)/ : qr/$regex/ ), |
341
|
|
|
|
|
|
|
fields => \@fields, |
342
|
|
|
|
|
|
|
}; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
{ |
346
|
|
|
|
|
|
|
my $digit = qr/(?:[0-9])/; |
347
|
|
|
|
|
|
|
my $one_or_two_digits = qr/[0-9 ]?$digit/; |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
# These patterns are all locale-independent. There are a few that depend |
350
|
|
|
|
|
|
|
# on the locale, and must be re-calculated for each new parser object. |
351
|
|
|
|
|
|
|
my %universal_patterns = ( |
352
|
|
|
|
|
|
|
'%' => { |
353
|
|
|
|
|
|
|
regex => qr/%/, |
354
|
|
|
|
|
|
|
}, |
355
|
|
|
|
|
|
|
C => { |
356
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
357
|
|
|
|
|
|
|
field => 'century', |
358
|
|
|
|
|
|
|
}, |
359
|
|
|
|
|
|
|
d => { |
360
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
361
|
|
|
|
|
|
|
field => 'day', |
362
|
|
|
|
|
|
|
}, |
363
|
|
|
|
|
|
|
g => { |
364
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
365
|
|
|
|
|
|
|
field => 'iso_week_year_100', |
366
|
|
|
|
|
|
|
}, |
367
|
|
|
|
|
|
|
G => { |
368
|
|
|
|
|
|
|
regex => qr/$digit{4}/, |
369
|
|
|
|
|
|
|
field => 'iso_week_year', |
370
|
|
|
|
|
|
|
}, |
371
|
|
|
|
|
|
|
H => { |
372
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
373
|
|
|
|
|
|
|
field => 'hour', |
374
|
|
|
|
|
|
|
}, |
375
|
|
|
|
|
|
|
I => { |
376
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
377
|
|
|
|
|
|
|
field => 'hour_12', |
378
|
|
|
|
|
|
|
}, |
379
|
|
|
|
|
|
|
j => { |
380
|
|
|
|
|
|
|
regex => qr/$digit{1,3}/, |
381
|
|
|
|
|
|
|
field => 'day_of_year', |
382
|
|
|
|
|
|
|
}, |
383
|
|
|
|
|
|
|
m => { |
384
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
385
|
|
|
|
|
|
|
field => 'month', |
386
|
|
|
|
|
|
|
}, |
387
|
|
|
|
|
|
|
M => { |
388
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
389
|
|
|
|
|
|
|
field => 'minute', |
390
|
|
|
|
|
|
|
}, |
391
|
|
|
|
|
|
|
n => { |
392
|
|
|
|
|
|
|
regex => qr/\s+/, |
393
|
|
|
|
|
|
|
}, |
394
|
|
|
|
|
|
|
O => { |
395
|
|
|
|
|
|
|
regex => qr{[a-zA-Z_]+(?:/[a-zA-Z_]+(?:/[a-zA-Z_]+)?)?}, |
396
|
|
|
|
|
|
|
field => 'time_zone_name', |
397
|
|
|
|
|
|
|
}, |
398
|
|
|
|
|
|
|
s => { |
399
|
|
|
|
|
|
|
regex => qr/$digit+/, |
400
|
|
|
|
|
|
|
field => 'epoch', |
401
|
|
|
|
|
|
|
}, |
402
|
|
|
|
|
|
|
S => { |
403
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
404
|
|
|
|
|
|
|
field => 'second', |
405
|
|
|
|
|
|
|
}, |
406
|
|
|
|
|
|
|
U => { |
407
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
408
|
|
|
|
|
|
|
field => 'week_sun_0', |
409
|
|
|
|
|
|
|
}, |
410
|
|
|
|
|
|
|
u => { |
411
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
412
|
|
|
|
|
|
|
field => 'day_of_week', |
413
|
|
|
|
|
|
|
}, |
414
|
|
|
|
|
|
|
w => { |
415
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
416
|
|
|
|
|
|
|
field => 'day_of_week_sun_0', |
417
|
|
|
|
|
|
|
}, |
418
|
|
|
|
|
|
|
W => { |
419
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
420
|
|
|
|
|
|
|
field => 'week_mon_1', |
421
|
|
|
|
|
|
|
}, |
422
|
|
|
|
|
|
|
y => { |
423
|
|
|
|
|
|
|
regex => $one_or_two_digits, |
424
|
|
|
|
|
|
|
field => 'year_100', |
425
|
|
|
|
|
|
|
}, |
426
|
|
|
|
|
|
|
Y => { |
427
|
|
|
|
|
|
|
regex => qr/$digit{4}/, |
428
|
|
|
|
|
|
|
field => 'year', |
429
|
|
|
|
|
|
|
}, |
430
|
|
|
|
|
|
|
z => { |
431
|
|
|
|
|
|
|
regex => qr/(?:Z|[+-]$digit{2}(?:[:]?$digit{2})?)/, |
432
|
|
|
|
|
|
|
field => 'time_zone_offset', |
433
|
|
|
|
|
|
|
}, |
434
|
|
|
|
|
|
|
Z => { |
435
|
|
|
|
|
|
|
regex => qr/[a-zA-Z]{1,6}|[\-\+]$digit{2}/, |
436
|
|
|
|
|
|
|
field => 'time_zone_abbreviation', |
437
|
|
|
|
|
|
|
}, |
438
|
|
|
|
|
|
|
); |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
$universal_patterns{e} = $universal_patterns{d}; |
441
|
|
|
|
|
|
|
$universal_patterns{k} = $universal_patterns{H}; |
442
|
|
|
|
|
|
|
$universal_patterns{l} = $universal_patterns{I}; |
443
|
|
|
|
|
|
|
$universal_patterns{t} = $universal_patterns{n}; |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
my %universal_replacements = ( |
446
|
|
|
|
|
|
|
D => '%m/%d/%y', |
447
|
|
|
|
|
|
|
F => '%Y-%m-%d', |
448
|
|
|
|
|
|
|
r => '%I:%M:%S %p', |
449
|
|
|
|
|
|
|
R => '%H:%M', |
450
|
|
|
|
|
|
|
T => '%H:%M:%S', |
451
|
|
|
|
|
|
|
); |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
sub _parser_pieces { |
454
|
294
|
|
|
294
|
|
457
|
my $self = shift; |
455
|
|
|
|
|
|
|
|
456
|
294
|
|
|
|
|
1337
|
my %replacements = %universal_replacements; |
457
|
294
|
|
|
|
|
1273
|
$replacements{c} = $self->{locale}->glibc_datetime_format; |
458
|
294
|
|
|
|
|
1770
|
$replacements{x} = $self->{locale}->glibc_date_format; |
459
|
294
|
|
|
|
|
1360
|
$replacements{X} = $self->{locale}->glibc_time_format; |
460
|
|
|
|
|
|
|
|
461
|
294
|
|
|
|
|
3783
|
my %patterns = %universal_patterns; |
462
|
|
|
|
|
|
|
$patterns{a} = $patterns{A} = { |
463
|
294
|
|
|
|
|
781
|
regex => do { |
464
|
4116
|
|
|
|
|
7845
|
my $days = join '|', map {quotemeta} |
465
|
11029
|
50
|
|
|
|
19932
|
sort { ( length $b <=> length $a ) or ( $a cmp $b ) } |
466
|
294
|
|
|
|
|
512
|
keys %{ $self->_locale_days }; |
|
294
|
|
|
|
|
635
|
|
467
|
294
|
|
|
|
|
3332
|
qr/$days/i; |
468
|
|
|
|
|
|
|
}, |
469
|
|
|
|
|
|
|
field => 'day_name', |
470
|
|
|
|
|
|
|
}; |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
$patterns{b} = $patterns{B} = $patterns{h} = { |
473
|
294
|
|
|
|
|
33879
|
regex => do { |
474
|
6698
|
|
|
|
|
11599
|
my $months = join '|', map {quotemeta} |
475
|
22333
|
50
|
|
|
|
38871
|
sort { ( length $b <=> length $a ) or ( $a cmp $b ) } |
476
|
294
|
|
|
|
|
529
|
keys %{ $self->_locale_months }; |
|
294
|
|
|
|
|
695
|
|
477
|
294
|
|
|
|
|
4027
|
qr/$months/i; |
478
|
|
|
|
|
|
|
}, |
479
|
|
|
|
|
|
|
field => 'month_name', |
480
|
|
|
|
|
|
|
}; |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
$patterns{p} = $patterns{P} = { |
483
|
294
|
|
|
|
|
9066
|
regex => do { |
484
|
|
|
|
|
|
|
my $am_pm = join '|', |
485
|
588
|
|
|
|
|
1415
|
map {quotemeta} |
486
|
294
|
0
|
|
|
|
1864
|
sort { ( length $b <=> length $a ) or ( $a cmp $b ) } |
487
|
294
|
|
|
|
|
455
|
@{ $self->{locale}->am_pm_abbreviated }; |
|
294
|
|
|
|
|
926
|
|
488
|
294
|
|
|
|
|
2679
|
qr/$am_pm/i; |
489
|
|
|
|
|
|
|
}, |
490
|
|
|
|
|
|
|
field => 'am_pm', |
491
|
|
|
|
|
|
|
}; |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
return ( |
494
|
294
|
|
|
|
|
1404
|
$self->_token_re_for( keys %replacements ), |
495
|
|
|
|
|
|
|
\%replacements, |
496
|
|
|
|
|
|
|
$self->_token_re_for( keys %patterns ), |
497
|
|
|
|
|
|
|
\%patterns, |
498
|
|
|
|
|
|
|
); |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
} |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
sub _locale_days { |
503
|
338
|
|
|
338
|
|
567
|
my $self = shift; |
504
|
|
|
|
|
|
|
|
505
|
338
|
100
|
|
|
|
952
|
return $self->{locale_days} if $self->{locale_days}; |
506
|
|
|
|
|
|
|
|
507
|
294
|
|
|
|
|
816
|
my $wide = $self->{locale}->day_format_wide; |
508
|
294
|
|
|
|
|
1356
|
my $abbr = $self->{locale}->day_format_abbreviated; |
509
|
|
|
|
|
|
|
|
510
|
294
|
|
|
|
|
975
|
my %locale_days; |
511
|
294
|
|
|
|
|
784
|
for my $i ( 0 .. 6 ) { |
512
|
2058
|
|
|
|
|
4512
|
$locale_days{ lc $wide->[$i] } = $i; |
513
|
2058
|
|
|
|
|
4348
|
$locale_days{ lc $abbr->[$i] } = $i; |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
|
516
|
294
|
|
50
|
|
|
3101
|
return $self->{locale_days} ||= \%locale_days; |
517
|
|
|
|
|
|
|
} |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
sub _locale_months { |
520
|
369
|
|
|
369
|
|
605
|
my $self = shift; |
521
|
|
|
|
|
|
|
|
522
|
369
|
100
|
|
|
|
1126
|
return $self->{locale_months} if $self->{locale_months}; |
523
|
|
|
|
|
|
|
|
524
|
294
|
|
|
|
|
914
|
my $wide = $self->{locale}->month_format_wide; |
525
|
294
|
|
|
|
|
1335
|
my $abbr = $self->{locale}->month_format_abbreviated; |
526
|
|
|
|
|
|
|
|
527
|
294
|
|
|
|
|
940
|
my %locale_months; |
528
|
294
|
|
|
|
|
625
|
for my $i ( 0 .. 11 ) { |
529
|
3528
|
|
|
|
|
6784
|
$locale_months{ lc $wide->[$i] } = $i + 1; |
530
|
3528
|
|
|
|
|
6990
|
$locale_months{ lc $abbr->[$i] } = $i + 1; |
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
|
533
|
294
|
|
50
|
|
|
2555
|
return $self->{locale_months} ||= \%locale_months; |
534
|
|
|
|
|
|
|
} |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
sub _token_re_for { |
537
|
588
|
|
|
588
|
|
1290
|
shift; |
538
|
|
|
|
|
|
|
my $t = join '|', |
539
|
588
|
0
|
|
|
|
1473
|
sort { ( length $b <=> length $a ) or ( $a cmp $b ) } @_; |
|
42123
|
|
|
|
|
70307
|
|
540
|
|
|
|
|
|
|
|
541
|
588
|
|
|
|
|
31517
|
return qr/$t/; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
{ |
545
|
|
|
|
|
|
|
# These are fields we parse that cannot be passed to a DateTime |
546
|
|
|
|
|
|
|
# constructor |
547
|
|
|
|
|
|
|
my @non_dt_keys = qw( |
548
|
|
|
|
|
|
|
am_pm |
549
|
|
|
|
|
|
|
century |
550
|
|
|
|
|
|
|
day_name |
551
|
|
|
|
|
|
|
day_of_week |
552
|
|
|
|
|
|
|
day_of_week_sun_0 |
553
|
|
|
|
|
|
|
hour_12 |
554
|
|
|
|
|
|
|
iso_week_year |
555
|
|
|
|
|
|
|
iso_week_year_100 |
556
|
|
|
|
|
|
|
month_name |
557
|
|
|
|
|
|
|
time_zone_abbreviation |
558
|
|
|
|
|
|
|
time_zone_name |
559
|
|
|
|
|
|
|
time_zone_offset |
560
|
|
|
|
|
|
|
week_mon_1 |
561
|
|
|
|
|
|
|
week_sun_0 |
562
|
|
|
|
|
|
|
year_100 |
563
|
|
|
|
|
|
|
); |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
## no critic (Subroutines::ProhibitExcessComplexity) |
566
|
|
|
|
|
|
|
sub _munge_args { |
567
|
283
|
|
|
283
|
|
465
|
my $self = shift; |
568
|
283
|
|
|
|
|
435
|
my $args = shift; |
569
|
|
|
|
|
|
|
|
570
|
283
|
100
|
|
|
|
722
|
if ( defined $args->{month_name} ) { |
571
|
|
|
|
|
|
|
my $num = $self->_locale_months->{ lc $args->{month_name} } |
572
|
75
|
50
|
|
|
|
174
|
or die "We somehow parsed a month name ($args->{month_name})" |
573
|
|
|
|
|
|
|
. ' that does not correspond to any month in this locale!'; |
574
|
|
|
|
|
|
|
|
575
|
75
|
|
|
|
|
190
|
$args->{month} = $num; |
576
|
|
|
|
|
|
|
} |
577
|
|
|
|
|
|
|
|
578
|
283
|
100
|
100
|
|
|
1163
|
if ( defined $args->{am_pm} && defined $args->{hour_12} ) { |
|
|
100
|
|
|
|
|
|
579
|
12
|
|
|
|
|
34
|
my ( $am, $pm ) = @{ $self->{locale}->am_pm_abbreviated }; |
|
12
|
|
|
|
|
46
|
|
580
|
12
|
|
|
|
|
73
|
$args->{hour} = $args->{hour_12}; |
581
|
|
|
|
|
|
|
|
582
|
12
|
100
|
|
|
|
42
|
if ( lc $args->{am_pm} eq lc $am ) { |
583
|
4
|
50
|
|
|
|
19
|
$args->{hour} = 0 if $args->{hour} == 12; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
else { |
586
|
8
|
50
|
|
|
|
40
|
$args->{hour} += 12 unless $args->{hour} == 12; |
587
|
|
|
|
|
|
|
} |
588
|
|
|
|
|
|
|
} |
589
|
|
|
|
|
|
|
elsif ( defined $args->{hour_12} ) { |
590
|
3
|
|
|
|
|
15
|
$self->_our_croak( |
591
|
|
|
|
|
|
|
qq{Parsed a 12-hour based hour, "$args->{hour_12}",} |
592
|
|
|
|
|
|
|
. ' but the pattern does not include an AM/PM specifier' |
593
|
|
|
|
|
|
|
); |
594
|
1
|
|
|
|
|
3
|
return; |
595
|
|
|
|
|
|
|
} |
596
|
|
|
|
|
|
|
|
597
|
280
|
100
|
|
|
|
615
|
if ( defined $args->{year_100} ) { |
598
|
10
|
100
|
|
|
|
46
|
if ( defined $args->{century} ) { |
599
|
|
|
|
|
|
|
$args->{year} |
600
|
1
|
|
|
|
|
7
|
= $args->{year_100} + ( $args->{century} * 100 ); |
601
|
|
|
|
|
|
|
} |
602
|
|
|
|
|
|
|
else { |
603
|
|
|
|
|
|
|
$args->{year} = $args->{year_100} + ( |
604
|
9
|
100
|
|
|
|
43
|
$args->{year_100} >= 69 |
605
|
|
|
|
|
|
|
? 1900 |
606
|
|
|
|
|
|
|
: 2000 |
607
|
|
|
|
|
|
|
); |
608
|
|
|
|
|
|
|
} |
609
|
|
|
|
|
|
|
} |
610
|
|
|
|
|
|
|
|
611
|
280
|
100
|
|
|
|
656
|
if ( $args->{time_zone_offset} ) { |
612
|
14
|
|
|
|
|
44
|
my $offset = $args->{time_zone_offset}; |
613
|
|
|
|
|
|
|
|
614
|
14
|
100
|
|
|
|
68
|
if ( $offset eq 'Z' ) { |
|
|
100
|
|
|
|
|
|
615
|
1
|
|
|
|
|
3
|
$offset = '+0000'; |
616
|
|
|
|
|
|
|
} |
617
|
|
|
|
|
|
|
elsif ( $offset =~ /^[+-][0-9]{2}$/ ) { |
618
|
2
|
|
|
|
|
8
|
$offset .= '00'; |
619
|
|
|
|
|
|
|
} |
620
|
|
|
|
|
|
|
|
621
|
14
|
|
|
14
|
|
76
|
my $tz = try { DateTime::TimeZone->new( name => $offset ) }; |
|
14
|
|
|
|
|
422
|
|
622
|
14
|
100
|
|
|
|
3659
|
unless ($tz) { |
623
|
3
|
|
|
|
|
15
|
$self->_our_croak( |
624
|
|
|
|
|
|
|
qq{The time zone name offset that was parsed does not appear to be valid, "$args->{time_zone_offset}"} |
625
|
|
|
|
|
|
|
); |
626
|
1
|
|
|
|
|
3
|
return; |
627
|
|
|
|
|
|
|
} |
628
|
|
|
|
|
|
|
|
629
|
11
|
|
|
|
|
32
|
$args->{time_zone} = $tz; |
630
|
|
|
|
|
|
|
} |
631
|
|
|
|
|
|
|
|
632
|
277
|
100
|
|
|
|
587
|
if ( defined $args->{time_zone_abbreviation} ) { |
633
|
20
|
|
|
|
|
45
|
my $abbr = $args->{time_zone_abbreviation}; |
634
|
20
|
100
|
|
|
|
62
|
unless ( exists $self->{zone_map}{$abbr} ) { |
635
|
3
|
|
|
|
|
14
|
$self->_our_croak( |
636
|
|
|
|
|
|
|
qq{Parsed an unrecognized time zone abbreviation, "$args->{time_zone_abbreviation}"} |
637
|
|
|
|
|
|
|
); |
638
|
1
|
|
|
|
|
3
|
return; |
639
|
|
|
|
|
|
|
} |
640
|
17
|
100
|
|
|
|
48
|
if ( !defined $self->{zone_map}{$abbr} ) { |
641
|
4
|
|
|
|
|
21
|
$self->_our_croak( |
642
|
|
|
|
|
|
|
qq{The time zone abbreviation that was parsed is ambiguous, "$args->{time_zone_abbreviation}"} |
643
|
|
|
|
|
|
|
); |
644
|
1
|
|
|
|
|
3
|
return; |
645
|
|
|
|
|
|
|
} |
646
|
|
|
|
|
|
|
$args->{time_zone} |
647
|
13
|
|
|
|
|
65
|
= DateTime::TimeZone->new( name => $self->{zone_map}{$abbr} ); |
648
|
|
|
|
|
|
|
} |
649
|
|
|
|
|
|
|
else { |
650
|
257
|
|
100
|
|
|
1068
|
$args->{time_zone} ||= 'floating'; |
651
|
|
|
|
|
|
|
} |
652
|
|
|
|
|
|
|
|
653
|
270
|
100
|
|
|
|
3847
|
if ( $args->{time_zone_name} ) { |
654
|
8
|
|
|
|
|
18
|
my $name = $args->{time_zone_name}; |
655
|
8
|
|
|
|
|
21
|
my $tz; |
656
|
8
|
100
|
|
8
|
|
46
|
unless ( $tz = try { DateTime::TimeZone->new( name => $name ) } ) |
|
8
|
|
|
|
|
220
|
|
657
|
|
|
|
|
|
|
{ |
658
|
6
|
|
|
|
|
2617
|
$name = lc $name; |
659
|
6
|
|
|
|
|
93
|
$name =~ s{(^|[/_])(.)}{$1\U$2}g; |
660
|
|
|
|
|
|
|
} |
661
|
8
|
|
|
8
|
|
19655
|
$tz = try { DateTime::TimeZone->new( name => $name ) }; |
|
8
|
|
|
|
|
222
|
|
662
|
8
|
100
|
|
|
|
16924
|
unless ($tz) { |
663
|
3
|
|
|
|
|
15
|
$self->_our_croak( |
664
|
|
|
|
|
|
|
qq{The Olson time zone name that was parsed does not appear to be valid, "$args->{time_zone_name}"} |
665
|
|
|
|
|
|
|
); |
666
|
1
|
|
|
|
|
4
|
return; |
667
|
|
|
|
|
|
|
} |
668
|
5
|
50
|
|
|
|
24
|
$args->{time_zone} = $tz |
669
|
|
|
|
|
|
|
if $tz; |
670
|
|
|
|
|
|
|
} |
671
|
|
|
|
|
|
|
|
672
|
267
|
|
|
|
|
487
|
delete @{$args}{@non_dt_keys}; |
|
267
|
|
|
|
|
1150
|
|
673
|
267
|
|
|
|
|
600
|
$args->{locale} = $self->{locale}; |
674
|
|
|
|
|
|
|
|
675
|
267
|
|
|
|
|
549
|
for my $k ( grep { defined $args->{$_} } |
|
1602
|
|
|
|
|
3434
|
|
676
|
|
|
|
|
|
|
qw( month day hour minute second nanosecond ) ) { |
677
|
587
|
|
|
|
|
1951
|
$args->{$k} =~ s/^\s+//; |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
|
680
|
267
|
100
|
|
|
|
623
|
if ( defined $args->{nanosecond} ) { |
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
# If we parsed "12345" we treat it as "123450000" but if we parsed |
683
|
|
|
|
|
|
|
# "000123456" we treat it as 123,456 nanoseconds. This is all a bit |
684
|
|
|
|
|
|
|
# weird and confusing but it matches how this module has always |
685
|
|
|
|
|
|
|
# worked. |
686
|
|
|
|
|
|
|
$args->{nanosecond} *= 10**( 9 - length $args->{nanosecond} ) |
687
|
6
|
100
|
|
|
|
38
|
if length $args->{nanosecond} != 9; |
688
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
# If we parsed 000000123 we want to turn this into a number. |
690
|
6
|
|
|
|
|
16
|
$args->{nanosecond} += 0; |
691
|
|
|
|
|
|
|
} |
692
|
|
|
|
|
|
|
|
693
|
267
|
|
|
|
|
484
|
for my $k (qw( year month day )) { |
694
|
801
|
100
|
|
|
|
1900
|
$args->{$k} = 1 unless defined $args->{$k}; |
695
|
|
|
|
|
|
|
} |
696
|
|
|
|
|
|
|
|
697
|
267
|
100
|
|
|
|
755
|
if ( defined $args->{epoch} ) { |
|
|
100
|
|
|
|
|
|
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
# We don't want to pass a non-integer epoch value since that gets |
700
|
|
|
|
|
|
|
# truncated as of DateTime 1.22. Instead, we'll set the nanosecond |
701
|
|
|
|
|
|
|
# to parsed value after constructing the object. This is a hack, |
702
|
|
|
|
|
|
|
# but it's the best I can come up with. |
703
|
28
|
|
|
|
|
42
|
my $post_construct; |
704
|
28
|
100
|
|
|
|
68
|
if ( my $nano = $args->{nanosecond} ) { |
705
|
2
|
|
|
2
|
|
11
|
$post_construct = sub { $_[0]->set( nanosecond => $nano ) }; |
|
2
|
|
|
|
|
11
|
|
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
|
708
|
28
|
|
|
|
|
88
|
delete @{$args}{ |
709
|
28
|
|
|
|
|
48
|
qw( day_of_year year month day hour minute second nanosecond ) |
710
|
|
|
|
|
|
|
}; |
711
|
|
|
|
|
|
|
|
712
|
28
|
|
|
|
|
154
|
return ( 'from_epoch', $args, $post_construct ); |
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
elsif ( $args->{day_of_year} ) { |
715
|
4
|
|
|
|
|
9
|
delete @{$args}{qw( epoch month day )}; |
|
4
|
|
|
|
|
14
|
|
716
|
4
|
|
|
|
|
14
|
return ( 'from_day_of_year', $args ); |
717
|
|
|
|
|
|
|
} |
718
|
|
|
|
|
|
|
|
719
|
235
|
|
|
|
|
744
|
return ( 'new', $args ); |
720
|
|
|
|
|
|
|
} |
721
|
|
|
|
|
|
|
} |
722
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
## no critic (Subroutines::ProhibitExcessComplexity) |
724
|
|
|
|
|
|
|
sub _check_dt { |
725
|
258
|
|
|
258
|
|
1684
|
my $self = shift; |
726
|
258
|
|
|
|
|
397
|
my $dt = shift; |
727
|
258
|
|
|
|
|
397
|
my $args = shift; |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
my $is_am = defined $args->{am_pm} |
730
|
258
|
|
100
|
|
|
840
|
&& lc $args->{am_pm} eq lc $self->{locale}->am_pm_abbreviated->[0]; |
731
|
258
|
100
|
100
|
|
|
983
|
if ( defined $args->{hour} && defined $args->{hour_12} ) { |
732
|
4
|
100
|
|
|
|
23
|
unless ( ( $args->{hour} % 12 ) == $args->{hour_12} ) { |
733
|
3
|
|
|
|
|
17
|
$self->_our_croak( |
734
|
|
|
|
|
|
|
'Parsed an input with 24-hour and 12-hour time values that do not match' |
735
|
|
|
|
|
|
|
. qq{ - "$args->{hour}" versus "$args->{hour_12}"} ); |
736
|
1
|
|
|
|
|
12
|
return; |
737
|
|
|
|
|
|
|
} |
738
|
|
|
|
|
|
|
} |
739
|
|
|
|
|
|
|
|
740
|
255
|
100
|
100
|
|
|
683
|
if ( defined $args->{hour} && defined $args->{am_pm} ) { |
741
|
27
|
100
|
100
|
|
|
255
|
if ( ( $is_am && $args->{hour} >= 12 ) |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
742
|
|
|
|
|
|
|
|| ( !$is_am && $args->{hour} < 12 ) ) { |
743
|
6
|
|
|
|
|
32
|
$self->_our_croak( |
744
|
|
|
|
|
|
|
'Parsed an input with 24-hour and AM/PM values that do not match' |
745
|
|
|
|
|
|
|
. qq{ - "$args->{hour}" versus "$args->{am_pm}"} ); |
746
|
2
|
|
|
|
|
21
|
return; |
747
|
|
|
|
|
|
|
} |
748
|
|
|
|
|
|
|
} |
749
|
|
|
|
|
|
|
|
750
|
249
|
100
|
100
|
|
|
992
|
if ( defined $args->{year} && defined $args->{century} ) { |
751
|
4
|
100
|
|
|
|
23
|
unless ( int( $args->{year} / 100 ) == $args->{century} ) { |
752
|
3
|
|
|
|
|
17
|
$self->_our_croak( |
753
|
|
|
|
|
|
|
'Parsed an input with year and century values that do not match' |
754
|
|
|
|
|
|
|
. qq{ - "$args->{year}" versus "$args->{century}"} ); |
755
|
1
|
|
|
|
|
11
|
return; |
756
|
|
|
|
|
|
|
} |
757
|
|
|
|
|
|
|
} |
758
|
|
|
|
|
|
|
|
759
|
246
|
100
|
100
|
|
|
856
|
if ( defined $args->{year} && defined $args->{year_100} ) { |
760
|
4
|
100
|
|
|
|
26
|
unless ( ( $args->{year} % 100 ) == $args->{year_100} ) { |
761
|
3
|
|
|
|
|
18
|
$self->_our_croak( |
762
|
|
|
|
|
|
|
'Parsed an input with year and year-within-century values that do not match' |
763
|
|
|
|
|
|
|
. qq{ - "$args->{year}" versus "$args->{year_100}"} ); |
764
|
1
|
|
|
|
|
11
|
return; |
765
|
|
|
|
|
|
|
} |
766
|
|
|
|
|
|
|
} |
767
|
|
|
|
|
|
|
|
768
|
243
|
100
|
100
|
|
|
615
|
if ( defined $args->{time_zone_abbreviation} |
769
|
|
|
|
|
|
|
&& defined $args->{time_zone_offset} ) { |
770
|
4
|
100
|
66
|
|
|
26
|
unless ( $self->{zone_map}{ $args->{time_zone_abbreviation} } |
771
|
|
|
|
|
|
|
&& $self->{zone_map}{ $args->{time_zone_abbreviation} } eq |
772
|
|
|
|
|
|
|
$args->{time_zone_offset} ) { |
773
|
|
|
|
|
|
|
|
774
|
3
|
|
|
|
|
19
|
$self->_our_croak( |
775
|
|
|
|
|
|
|
'Parsed an input with time zone abbreviation and time zone offset values that do not match' |
776
|
|
|
|
|
|
|
. qq{ - "$args->{time_zone_abbreviation}" versus "$args->{time_zone_offset}"} |
777
|
|
|
|
|
|
|
); |
778
|
1
|
|
|
|
|
11
|
return; |
779
|
|
|
|
|
|
|
} |
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
|
782
|
240
|
100
|
|
|
|
531
|
if ( defined $args->{epoch} ) { |
783
|
28
|
|
|
|
|
66
|
for my $key ( |
784
|
|
|
|
|
|
|
qw( year month day minute hour second hour_12 day_of_year )) { |
785
|
140
|
100
|
100
|
|
|
417
|
if ( defined $args->{$key} && $dt->$key != $args->{$key} ) { |
786
|
24
|
100
|
|
|
|
244
|
my $print_key |
|
|
100
|
|
|
|
|
|
787
|
|
|
|
|
|
|
= $key eq 'hour_12' ? 'hour (1-12)' |
788
|
|
|
|
|
|
|
: $key eq 'day_of_year' ? 'day of year' |
789
|
|
|
|
|
|
|
: $key; |
790
|
24
|
|
|
|
|
123
|
$self->_our_croak( |
791
|
|
|
|
|
|
|
"Parsed an input with epoch and $print_key values that do not match" |
792
|
|
|
|
|
|
|
. qq{ - "$args->{epoch}" versus "$args->{$key}"} ); |
793
|
8
|
|
|
|
|
81
|
return; |
794
|
|
|
|
|
|
|
} |
795
|
|
|
|
|
|
|
} |
796
|
|
|
|
|
|
|
} |
797
|
|
|
|
|
|
|
|
798
|
216
|
100
|
100
|
|
|
702
|
if ( defined $args->{month} && defined $args->{day_of_year} ) { |
799
|
4
|
100
|
|
|
|
13
|
unless ( $dt->month == $args->{month} ) { |
800
|
3
|
|
|
|
|
34
|
$self->_our_croak( |
801
|
|
|
|
|
|
|
'Parsed an input with month and day of year values that do not match' |
802
|
|
|
|
|
|
|
. qq{ - "$args->{month}" versus "$args->{day_of_year}"} ); |
803
|
1
|
|
|
|
|
11
|
return; |
804
|
|
|
|
|
|
|
} |
805
|
|
|
|
|
|
|
} |
806
|
|
|
|
|
|
|
|
807
|
213
|
100
|
|
|
|
487
|
if ( defined $args->{day_name} ) { |
808
|
44
|
|
|
|
|
124
|
my $dow = $self->_locale_days->{ lc $args->{day_name} }; |
809
|
44
|
50
|
|
|
|
118
|
defined $dow |
810
|
|
|
|
|
|
|
or die "We somehow parsed a day name ($args->{day_name})" |
811
|
|
|
|
|
|
|
. ' that does not correspond to any day in this locale!'; |
812
|
|
|
|
|
|
|
|
813
|
44
|
100
|
|
|
|
127
|
unless ( $dt->day_of_week_0 == $dow ) { |
814
|
3
|
|
|
|
|
27
|
$self->_our_croak( |
815
|
|
|
|
|
|
|
'Parsed an input where the day name does not match the date' |
816
|
|
|
|
|
|
|
. qq{ - "$args->{day_name}" versus "} |
817
|
|
|
|
|
|
|
. $dt->ymd |
818
|
|
|
|
|
|
|
. q{"} ); |
819
|
1
|
|
|
|
|
12
|
return; |
820
|
|
|
|
|
|
|
} |
821
|
|
|
|
|
|
|
} |
822
|
|
|
|
|
|
|
|
823
|
210
|
100
|
|
|
|
597
|
if ( defined $args->{day_of_week} ) { |
824
|
4
|
100
|
|
|
|
14
|
unless ( $dt->day_of_week == $args->{day_of_week} ) { |
825
|
3
|
|
|
|
|
26
|
$self->_our_croak( |
826
|
|
|
|
|
|
|
'Parsed an input where the day of week does not match the date' |
827
|
|
|
|
|
|
|
. qq{ - "$args->{day_of_week}" versus "} |
828
|
|
|
|
|
|
|
. $dt->ymd |
829
|
|
|
|
|
|
|
. q{"} ); |
830
|
1
|
|
|
|
|
11
|
return; |
831
|
|
|
|
|
|
|
} |
832
|
|
|
|
|
|
|
} |
833
|
|
|
|
|
|
|
|
834
|
207
|
100
|
|
|
|
451
|
if ( defined $args->{day_of_week_sun_0} ) { |
835
|
4
|
100
|
|
|
|
12
|
unless ( ( $dt->day_of_week % 7 ) == $args->{day_of_week_sun_0} ) { |
836
|
3
|
|
|
|
|
26
|
$self->_our_croak( |
837
|
|
|
|
|
|
|
'Parsed an input where the day of week (Sunday as 0) does not match the date' |
838
|
|
|
|
|
|
|
. qq{ - "$args->{day_of_week_sun_0}" versus "} |
839
|
|
|
|
|
|
|
. $dt->ymd |
840
|
|
|
|
|
|
|
. q{"} ); |
841
|
1
|
|
|
|
|
13
|
return; |
842
|
|
|
|
|
|
|
} |
843
|
|
|
|
|
|
|
} |
844
|
|
|
|
|
|
|
|
845
|
204
|
100
|
|
|
|
429
|
if ( defined $args->{iso_week_year} ) { |
846
|
4
|
100
|
|
|
|
17
|
unless ( $dt->week_year == $args->{iso_week_year} ) { |
847
|
3
|
|
|
|
|
108
|
$self->_our_croak( |
848
|
|
|
|
|
|
|
'Parsed an input where the ISO week year does not match the date' |
849
|
|
|
|
|
|
|
. qq{ - "$args->{iso_week_year}" versus "} |
850
|
|
|
|
|
|
|
. $dt->ymd |
851
|
|
|
|
|
|
|
. q{"} ); |
852
|
1
|
|
|
|
|
13
|
return; |
853
|
|
|
|
|
|
|
} |
854
|
|
|
|
|
|
|
} |
855
|
|
|
|
|
|
|
|
856
|
201
|
100
|
|
|
|
474
|
if ( defined $args->{iso_week_year_100} ) { |
857
|
4
|
100
|
|
|
|
14
|
unless ( ( 0 + substr( $dt->week_year, -2 ) ) |
858
|
|
|
|
|
|
|
== $args->{iso_week_year_100} ) { |
859
|
3
|
|
|
|
|
101
|
$self->_our_croak( |
860
|
|
|
|
|
|
|
'Parsed an input where the ISO week year (without century) does not match the date' |
861
|
|
|
|
|
|
|
. qq{ - "$args->{iso_week_year_100}" versus "} |
862
|
|
|
|
|
|
|
. $dt->ymd |
863
|
|
|
|
|
|
|
. q{"} ); |
864
|
1
|
|
|
|
|
13
|
return; |
865
|
|
|
|
|
|
|
} |
866
|
|
|
|
|
|
|
} |
867
|
|
|
|
|
|
|
|
868
|
198
|
100
|
|
|
|
451
|
if ( defined $args->{week_mon_1} ) { |
869
|
4
|
100
|
|
|
|
14
|
unless ( ( 0 + $dt->strftime('%W') ) == $args->{week_mon_1} ) { |
870
|
3
|
|
|
|
|
141
|
$self->_our_croak( |
871
|
|
|
|
|
|
|
'Parsed an input where the ISO week number (Monday starts week) does not match the date' |
872
|
|
|
|
|
|
|
. qq{ - "$args->{week_mon_1}" versus "} |
873
|
|
|
|
|
|
|
. $dt->ymd |
874
|
|
|
|
|
|
|
. q{"} ); |
875
|
1
|
|
|
|
|
12
|
return; |
876
|
|
|
|
|
|
|
} |
877
|
|
|
|
|
|
|
} |
878
|
|
|
|
|
|
|
|
879
|
195
|
100
|
|
|
|
600
|
if ( defined $args->{week_sun_0} ) { |
880
|
4
|
100
|
|
|
|
13
|
unless ( ( 0 + $dt->strftime('%U') ) == $args->{week_sun_0} ) { |
881
|
3
|
|
|
|
|
132
|
$self->_our_croak( |
882
|
|
|
|
|
|
|
'Parsed an input where the ISO week number (Sunday starts week) does not match the date' |
883
|
|
|
|
|
|
|
. qq{ - "$args->{week_sun_0}" versus "} |
884
|
|
|
|
|
|
|
. $dt->ymd |
885
|
|
|
|
|
|
|
. q{"} ); |
886
|
1
|
|
|
|
|
14
|
return; |
887
|
|
|
|
|
|
|
} |
888
|
|
|
|
|
|
|
} |
889
|
|
|
|
|
|
|
|
890
|
192
|
|
|
|
|
670
|
return 1; |
891
|
|
|
|
|
|
|
} |
892
|
|
|
|
|
|
|
## use critic |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
sub pattern { |
895
|
29
|
|
|
29
|
1
|
58
|
my $self = shift; |
896
|
29
|
|
|
|
|
78
|
return $self->{pattern}; |
897
|
|
|
|
|
|
|
} |
898
|
|
|
|
|
|
|
|
899
|
|
|
|
|
|
|
sub locale { |
900
|
29
|
|
|
29
|
1
|
375
|
my $self = shift; |
901
|
|
|
|
|
|
|
return $self->{locale}->can('code') |
902
|
|
|
|
|
|
|
? $self->{locale}->code |
903
|
29
|
50
|
|
|
|
205
|
: $self->{locale}->id; |
904
|
|
|
|
|
|
|
} |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
sub time_zone { |
907
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
908
|
0
|
|
|
|
|
0
|
return $self->{time_zone}->name; |
909
|
|
|
|
|
|
|
} |
910
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
sub parse_duration { |
912
|
0
|
|
|
0
|
0
|
0
|
croak q{DateTime::Format::Strptime doesn't do durations.}; |
913
|
|
|
|
|
|
|
} |
914
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
{ |
916
|
|
|
|
|
|
|
my $validator = validation_for( params => [ { type => t('DateTime') } ] ); |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
sub format_datetime { |
919
|
30
|
|
|
30
|
1
|
89741
|
my $self = shift; |
920
|
30
|
|
|
|
|
895
|
my ($dt) = $validator->(@_); |
921
|
|
|
|
|
|
|
|
922
|
29
|
|
|
|
|
471
|
my $pattern = $self->pattern; |
923
|
29
|
|
|
|
|
83
|
$pattern =~ s/%O/$dt->time_zone->name/eg; |
|
2
|
|
|
|
|
9
|
|
924
|
29
|
|
|
|
|
119
|
return $dt->clone->set_locale( $self->locale )->strftime($pattern); |
925
|
|
|
|
|
|
|
} |
926
|
|
|
|
|
|
|
|
927
|
|
|
|
|
|
|
} |
928
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
sub format_duration { |
930
|
0
|
|
|
0
|
0
|
0
|
croak q{DateTime::Format::Strptime doesn't do durations.}; |
931
|
|
|
|
|
|
|
} |
932
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
sub _our_croak { |
934
|
97
|
|
|
97
|
|
441
|
my $self = shift; |
935
|
97
|
|
|
|
|
154
|
my $error = shift; |
936
|
|
|
|
|
|
|
|
937
|
97
|
100
|
|
|
|
283
|
return $self->{on_error}->( $self, $error ) if ref $self->{on_error}; |
938
|
65
|
100
|
|
|
|
3130
|
croak $error if $self->{on_error} eq 'croak'; |
939
|
32
|
|
|
|
|
85
|
$self->{errmsg} = $error; |
940
|
32
|
|
|
|
|
66
|
return; |
941
|
|
|
|
|
|
|
} |
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
sub errmsg { |
944
|
32
|
|
|
32
|
1
|
179
|
$_[0]->{errmsg}; |
945
|
|
|
|
|
|
|
} |
946
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
# Exportable functions: |
948
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
sub strftime { |
950
|
1
|
|
|
1
|
1
|
1216
|
my ( $pattern, $dt ) = @_; |
951
|
1
|
|
|
|
|
5
|
return DateTime::Format::Strptime->new( |
952
|
|
|
|
|
|
|
pattern => $pattern, |
953
|
|
|
|
|
|
|
on_error => 'croak' |
954
|
|
|
|
|
|
|
)->format_datetime($dt); |
955
|
|
|
|
|
|
|
} |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
sub strptime { |
958
|
1
|
|
|
1
|
1
|
116
|
my ( $pattern, $time_string ) = @_; |
959
|
1
|
|
|
|
|
10
|
return DateTime::Format::Strptime->new( |
960
|
|
|
|
|
|
|
pattern => $pattern, |
961
|
|
|
|
|
|
|
on_error => 'croak' |
962
|
|
|
|
|
|
|
)->parse_datetime($time_string); |
963
|
|
|
|
|
|
|
} |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
1; |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
# ABSTRACT: Parse and format strp and strf time patterns |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
__END__ |
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
=pod |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
=encoding UTF-8 |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
=head1 NAME |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
DateTime::Format::Strptime - Parse and format strp and strf time patterns |
978
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
=head1 VERSION |
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
version 1.77 |
982
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
=head1 SYNOPSIS |
984
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
use DateTime::Format::Strptime; |
986
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
my $strp = DateTime::Format::Strptime->new( |
988
|
|
|
|
|
|
|
pattern => '%T', |
989
|
|
|
|
|
|
|
locale => 'en_AU', |
990
|
|
|
|
|
|
|
time_zone => 'Australia/Melbourne', |
991
|
|
|
|
|
|
|
); |
992
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
my $dt = $strp->parse_datetime('23:16:42'); |
994
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
$strp->format_datetime($dt); |
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
# 23:16:42 |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
# Croak when things go wrong: |
1000
|
|
|
|
|
|
|
my $strp = DateTime::Format::Strptime->new( |
1001
|
|
|
|
|
|
|
pattern => '%T', |
1002
|
|
|
|
|
|
|
locale => 'en_AU', |
1003
|
|
|
|
|
|
|
time_zone => 'Australia/Melbourne', |
1004
|
|
|
|
|
|
|
on_error => 'croak', |
1005
|
|
|
|
|
|
|
); |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
# Do something else when things go wrong: |
1008
|
|
|
|
|
|
|
my $strp = DateTime::Format::Strptime->new( |
1009
|
|
|
|
|
|
|
pattern => '%T', |
1010
|
|
|
|
|
|
|
locale => 'en_AU', |
1011
|
|
|
|
|
|
|
time_zone => 'Australia/Melbourne', |
1012
|
|
|
|
|
|
|
on_error => \&phone_police, |
1013
|
|
|
|
|
|
|
); |
1014
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
=head1 DESCRIPTION |
1016
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
This module implements most of C<strptime(3)>, the POSIX function that is the |
1018
|
|
|
|
|
|
|
reverse of C<strftime(3)>, for C<DateTime>. While C<strftime> takes a |
1019
|
|
|
|
|
|
|
C<DateTime> and a pattern and returns a string, C<strptime> takes a string and |
1020
|
|
|
|
|
|
|
a pattern and returns the C<DateTime> object associated. |
1021
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
=for Pod::Coverage parse_duration format_duration |
1023
|
|
|
|
|
|
|
|
1024
|
|
|
|
|
|
|
=head1 METHODS |
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
This class offers the following methods. |
1027
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
=head2 DateTime::Format::Strptime->new(%args) |
1029
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
This methods creates a new object. It accepts the following arguments: |
1031
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
=over 4 |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
=item * pattern |
1035
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
This is the pattern to use for parsing. This is required. |
1037
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
=item * strict |
1039
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
This is a boolean which disables or enables strict matching mode. |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
By default, this module turns your pattern into a regex that will match |
1043
|
|
|
|
|
|
|
anywhere in a string. So given the pattern C<%Y%m%d%H%M%S> it will match a |
1044
|
|
|
|
|
|
|
string like C<20161214233712>. However, this also means that a this pattern |
1045
|
|
|
|
|
|
|
will match B<any> string that contains 14 or more numbers! This behavior can |
1046
|
|
|
|
|
|
|
be very surprising. |
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
If you enable strict mode, then the generated regex is wrapped in boundary |
1049
|
|
|
|
|
|
|
checks of the form C</(?:\A|\b)...(?:\b|\z_/)>. These checks ensure that the |
1050
|
|
|
|
|
|
|
pattern will only match when at the beginning or end of a string, or when it |
1051
|
|
|
|
|
|
|
is separated by other text with a word boundary (C<\w> versus C<\W>). |
1052
|
|
|
|
|
|
|
|
1053
|
|
|
|
|
|
|
By default, strict mode is off. This is done for backwards |
1054
|
|
|
|
|
|
|
compatibility. Future releases may turn it on by default, as it produces less |
1055
|
|
|
|
|
|
|
surprising behavior in many cases. |
1056
|
|
|
|
|
|
|
|
1057
|
|
|
|
|
|
|
Because the default may change in the future, B<< you are strongly encouraged |
1058
|
|
|
|
|
|
|
to explicitly set this when constructing all C<DateTime::Format::Strptime> |
1059
|
|
|
|
|
|
|
objects >>. |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
=item * time_zone |
1062
|
|
|
|
|
|
|
|
1063
|
|
|
|
|
|
|
The default time zone to use for objects returned from parsing. |
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
=item * zone_map |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
Some time zone abbreviations are ambiguous (e.g. PST, EST, EDT). By default, |
1068
|
|
|
|
|
|
|
the parser will die when it parses an ambiguous abbreviation. You may specify |
1069
|
|
|
|
|
|
|
a C<zone_map> parameter as a hashref to map zone abbreviations however you like: |
1070
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
zone_map => { PST => '-0800', EST => '-0600' } |
1072
|
|
|
|
|
|
|
|
1073
|
|
|
|
|
|
|
Note that you can also override non-ambiguous mappings if you want to as well. |
1074
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
=item * locale |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
The locale to use for objects returned from parsing. |
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
=item * on_error |
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
This can be one of C<'undef'> (the string, not an C<undef>), 'croak', or a |
1082
|
|
|
|
|
|
|
subroutine reference. |
1083
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
=over 8 |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
=item * 'undef' |
1087
|
|
|
|
|
|
|
|
1088
|
|
|
|
|
|
|
This is the default behavior. The module will return C<undef> on errors. The |
1089
|
|
|
|
|
|
|
error can be accessed using the C<< $object->errmsg >> method. This is the |
1090
|
|
|
|
|
|
|
ideal behaviour for interactive use where a user might provide an illegal |
1091
|
|
|
|
|
|
|
pattern or a date that doesn't match the pattern. |
1092
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
=item * 'croak' |
1094
|
|
|
|
|
|
|
|
1095
|
|
|
|
|
|
|
The module will croak with an error message on errors. |
1096
|
|
|
|
|
|
|
|
1097
|
|
|
|
|
|
|
=item * sub{...} or \&subname |
1098
|
|
|
|
|
|
|
|
1099
|
|
|
|
|
|
|
When given a code ref, the module will call that sub on errors. The sub |
1100
|
|
|
|
|
|
|
receives two parameters: the object and the error message. |
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
If your sub does not die, then the formatter will continue on as if |
1103
|
|
|
|
|
|
|
C<on_error> was C<'undef'>. |
1104
|
|
|
|
|
|
|
|
1105
|
|
|
|
|
|
|
=back |
1106
|
|
|
|
|
|
|
|
1107
|
|
|
|
|
|
|
=back |
1108
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
=head2 $strptime->parse_datetime($string) |
1110
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
Given a string in the pattern specified in the constructor, this method |
1112
|
|
|
|
|
|
|
will return a new C<DateTime> object. |
1113
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
If given a string that doesn't match the pattern, the formatter will croak or |
1115
|
|
|
|
|
|
|
return undef, depending on the setting of C<on_error> in the constructor. |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
=head2 $strptime->format_datetime($datetime) |
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
Given a C<DateTime> object, this methods returns a string formatted in the |
1120
|
|
|
|
|
|
|
object's format. This method is synonymous with C<DateTime>'s strftime method. |
1121
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
=head2 $strptime->locale |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
This method returns the locale passed to the object's constructor. |
1125
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
=head2 $strptime->pattern |
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
This method returns the pattern passed to the object's constructor. |
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
=head2 $strptime->time_zone |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
This method returns the time zone passed to the object's constructor. |
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
=head2 $strptime->errmsg |
1135
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
If the on_error behavior of the object is 'undef', you can retrieve error |
1137
|
|
|
|
|
|
|
messages with this method so you can work out why things went wrong. |
1138
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
=head1 EXPORTS |
1140
|
|
|
|
|
|
|
|
1141
|
|
|
|
|
|
|
These subs are available as optional exports. |
1142
|
|
|
|
|
|
|
|
1143
|
|
|
|
|
|
|
=head2 strptime( $strptime_pattern, $string ) |
1144
|
|
|
|
|
|
|
|
1145
|
|
|
|
|
|
|
Given a pattern and a string this function will return a new C<DateTime> |
1146
|
|
|
|
|
|
|
object. |
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
=head2 strftime( $strftime_pattern, $datetime ) |
1149
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
Given a pattern and a C<DateTime> object this function will return a |
1151
|
|
|
|
|
|
|
formatted string. |
1152
|
|
|
|
|
|
|
|
1153
|
|
|
|
|
|
|
=head1 STRPTIME PATTERN TOKENS |
1154
|
|
|
|
|
|
|
|
1155
|
|
|
|
|
|
|
The following tokens are allowed in the pattern string for strptime |
1156
|
|
|
|
|
|
|
(parse_datetime): |
1157
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
=over 4 |
1159
|
|
|
|
|
|
|
|
1160
|
|
|
|
|
|
|
=item * %% |
1161
|
|
|
|
|
|
|
|
1162
|
|
|
|
|
|
|
The % character. |
1163
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
=item * %a or %A |
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
The weekday name according to the given locale, in abbreviated form or |
1167
|
|
|
|
|
|
|
the full name. |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
=item * %b or %B or %h |
1170
|
|
|
|
|
|
|
|
1171
|
|
|
|
|
|
|
The month name according to the given locale, in abbreviated form or |
1172
|
|
|
|
|
|
|
the full name. |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
=item * %c |
1175
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
The datetime format according to the given locale. |
1177
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
=item * %C |
1179
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
The century number (0-99). |
1181
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
=item * %d or %e |
1183
|
|
|
|
|
|
|
|
1184
|
|
|
|
|
|
|
The day of month (01-31). This will parse single digit numbers as well. |
1185
|
|
|
|
|
|
|
|
1186
|
|
|
|
|
|
|
=item * %D |
1187
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
Equivalent to %m/%d/%y. (This is the American style date, very confusing |
1189
|
|
|
|
|
|
|
to non-Americans, especially since %d/%m/%y is widely used in Europe. |
1190
|
|
|
|
|
|
|
The ISO 8601 standard pattern is %F.) |
1191
|
|
|
|
|
|
|
|
1192
|
|
|
|
|
|
|
=item * %F |
1193
|
|
|
|
|
|
|
|
1194
|
|
|
|
|
|
|
Equivalent to %Y-%m-%d. (This is the ISO style date) |
1195
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
=item * %g |
1197
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
The year corresponding to the ISO week number, but without the century |
1199
|
|
|
|
|
|
|
(0-99). |
1200
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
=item * %G |
1202
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
The 4-digit year corresponding to the ISO week number. |
1204
|
|
|
|
|
|
|
|
1205
|
|
|
|
|
|
|
=item * %H |
1206
|
|
|
|
|
|
|
|
1207
|
|
|
|
|
|
|
The hour (00-23). This will parse single digit numbers as well. |
1208
|
|
|
|
|
|
|
|
1209
|
|
|
|
|
|
|
=item * %I |
1210
|
|
|
|
|
|
|
|
1211
|
|
|
|
|
|
|
The hour on a 12-hour clock (1-12). |
1212
|
|
|
|
|
|
|
|
1213
|
|
|
|
|
|
|
=item * %j |
1214
|
|
|
|
|
|
|
|
1215
|
|
|
|
|
|
|
The day number in the year (1-366). |
1216
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
=item * %m |
1218
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
The month number (01-12). This will parse single digit numbers as well. |
1220
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
=item * %M |
1222
|
|
|
|
|
|
|
|
1223
|
|
|
|
|
|
|
The minute (00-59). This will parse single digit numbers as well. |
1224
|
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
=item * %n |
1226
|
|
|
|
|
|
|
|
1227
|
|
|
|
|
|
|
Arbitrary whitespace. |
1228
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
=item * %N |
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
Nanoseconds. For other sub-second values use C<%[number]N>. |
1232
|
|
|
|
|
|
|
|
1233
|
|
|
|
|
|
|
=item * %p or %P |
1234
|
|
|
|
|
|
|
|
1235
|
|
|
|
|
|
|
The equivalent of AM or PM according to the locale in use. See |
1236
|
|
|
|
|
|
|
L<DateTime::Locale>. |
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
=item * %r |
1239
|
|
|
|
|
|
|
|
1240
|
|
|
|
|
|
|
Equivalent to %I:%M:%S %p. |
1241
|
|
|
|
|
|
|
|
1242
|
|
|
|
|
|
|
=item * %R |
1243
|
|
|
|
|
|
|
|
1244
|
|
|
|
|
|
|
Equivalent to %H:%M. |
1245
|
|
|
|
|
|
|
|
1246
|
|
|
|
|
|
|
=item * %s |
1247
|
|
|
|
|
|
|
|
1248
|
|
|
|
|
|
|
Number of seconds since the Epoch. |
1249
|
|
|
|
|
|
|
|
1250
|
|
|
|
|
|
|
=item * %S |
1251
|
|
|
|
|
|
|
|
1252
|
|
|
|
|
|
|
The second (0-60; 60 may occur for leap seconds. See |
1253
|
|
|
|
|
|
|
L<DateTime::LeapSecond>). |
1254
|
|
|
|
|
|
|
|
1255
|
|
|
|
|
|
|
=item * %t |
1256
|
|
|
|
|
|
|
|
1257
|
|
|
|
|
|
|
Arbitrary whitespace. |
1258
|
|
|
|
|
|
|
|
1259
|
|
|
|
|
|
|
=item * %T |
1260
|
|
|
|
|
|
|
|
1261
|
|
|
|
|
|
|
Equivalent to %H:%M:%S. |
1262
|
|
|
|
|
|
|
|
1263
|
|
|
|
|
|
|
=item * %U |
1264
|
|
|
|
|
|
|
|
1265
|
|
|
|
|
|
|
The week number with Sunday the first day of the week (0-53). The first |
1266
|
|
|
|
|
|
|
Sunday of January is the first day of week 1. |
1267
|
|
|
|
|
|
|
|
1268
|
|
|
|
|
|
|
=item * %u |
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
The weekday number (1-7) with Monday = 1. This is the C<DateTime> standard. |
1271
|
|
|
|
|
|
|
|
1272
|
|
|
|
|
|
|
=item * %w |
1273
|
|
|
|
|
|
|
|
1274
|
|
|
|
|
|
|
The weekday number (0-6) with Sunday = 0. |
1275
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
=item * %W |
1277
|
|
|
|
|
|
|
|
1278
|
|
|
|
|
|
|
The week number with Monday the first day of the week (0-53). The first |
1279
|
|
|
|
|
|
|
Monday of January is the first day of week 1. |
1280
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
=item * %x |
1282
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
The date format according to the given locale. |
1284
|
|
|
|
|
|
|
|
1285
|
|
|
|
|
|
|
=item * %X |
1286
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
The time format according to the given locale. |
1288
|
|
|
|
|
|
|
|
1289
|
|
|
|
|
|
|
=item * %y |
1290
|
|
|
|
|
|
|
|
1291
|
|
|
|
|
|
|
The year within century (0-99). When a century is not otherwise specified |
1292
|
|
|
|
|
|
|
(with a value for %C), values in the range 69-99 refer to years in the |
1293
|
|
|
|
|
|
|
twentieth century (1969-1999); values in the range 00-68 refer to years in the |
1294
|
|
|
|
|
|
|
twenty-first century (2000-2068). |
1295
|
|
|
|
|
|
|
|
1296
|
|
|
|
|
|
|
=item * %Y |
1297
|
|
|
|
|
|
|
|
1298
|
|
|
|
|
|
|
A 4-digit year, including century (for example, 1991). |
1299
|
|
|
|
|
|
|
|
1300
|
|
|
|
|
|
|
=item * %z |
1301
|
|
|
|
|
|
|
|
1302
|
|
|
|
|
|
|
An RFC-822/ISO 8601 standard time zone specification. (For example |
1303
|
|
|
|
|
|
|
+1100) [See note below] |
1304
|
|
|
|
|
|
|
|
1305
|
|
|
|
|
|
|
=item * %Z |
1306
|
|
|
|
|
|
|
|
1307
|
|
|
|
|
|
|
The timezone name. (For example EST -- which is ambiguous) [See note |
1308
|
|
|
|
|
|
|
below] |
1309
|
|
|
|
|
|
|
|
1310
|
|
|
|
|
|
|
=item * %O |
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
This extended token allows the use of Olson Time Zone names to appear |
1313
|
|
|
|
|
|
|
in parsed strings. B<NOTE>: This pattern cannot be passed to C<DateTime>'s |
1314
|
|
|
|
|
|
|
C<strftime()> method, but can be passed to C<format_datetime()>. |
1315
|
|
|
|
|
|
|
|
1316
|
|
|
|
|
|
|
=back |
1317
|
|
|
|
|
|
|
|
1318
|
|
|
|
|
|
|
=head1 AUTHOR EMERITUS |
1319
|
|
|
|
|
|
|
|
1320
|
|
|
|
|
|
|
This module was created by Rick Measham. |
1321
|
|
|
|
|
|
|
|
1322
|
|
|
|
|
|
|
=head1 SEE ALSO |
1323
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
C<datetime@perl.org> mailing list. |
1325
|
|
|
|
|
|
|
|
1326
|
|
|
|
|
|
|
http://datetime.perl.org/ |
1327
|
|
|
|
|
|
|
|
1328
|
|
|
|
|
|
|
L<perl>, L<DateTime>, L<DateTime::TimeZone>, L<DateTime::Locale> |
1329
|
|
|
|
|
|
|
|
1330
|
|
|
|
|
|
|
=head1 BUGS |
1331
|
|
|
|
|
|
|
|
1332
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
1333
|
|
|
|
|
|
|
C<bug-datetime-format-strptime@rt.cpan.org>, or through the web interface at |
1334
|
|
|
|
|
|
|
L<http://rt.cpan.org>. I will be notified, and then you'll automatically be |
1335
|
|
|
|
|
|
|
notified of progress on your bug as I make changes. |
1336
|
|
|
|
|
|
|
|
1337
|
|
|
|
|
|
|
Bugs may be submitted at L<https://github.com/houseabsolute/DateTime-Format-Strptime/issues>. |
1338
|
|
|
|
|
|
|
|
1339
|
|
|
|
|
|
|
There is a mailing list available for users of this distribution, |
1340
|
|
|
|
|
|
|
L<mailto:datetime@perl.org>. |
1341
|
|
|
|
|
|
|
|
1342
|
|
|
|
|
|
|
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>. |
1343
|
|
|
|
|
|
|
|
1344
|
|
|
|
|
|
|
=head1 SOURCE |
1345
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
The source code repository for DateTime-Format-Strptime can be found at L<https://github.com/houseabsolute/DateTime-Format-Strptime>. |
1347
|
|
|
|
|
|
|
|
1348
|
|
|
|
|
|
|
=head1 DONATIONS |
1349
|
|
|
|
|
|
|
|
1350
|
|
|
|
|
|
|
If you'd like to thank me for the work I've done on this module, please |
1351
|
|
|
|
|
|
|
consider making a "donation" to me via PayPal. I spend a lot of free time |
1352
|
|
|
|
|
|
|
creating free software, and would appreciate any support you'd care to offer. |
1353
|
|
|
|
|
|
|
|
1354
|
|
|
|
|
|
|
Please note that B<I am not suggesting that you must do this> in order for me |
1355
|
|
|
|
|
|
|
to continue working on this particular software. I will continue to do so, |
1356
|
|
|
|
|
|
|
inasmuch as I have in the past, for as long as it interests me. |
1357
|
|
|
|
|
|
|
|
1358
|
|
|
|
|
|
|
Similarly, a donation made in this way will probably not make me work on this |
1359
|
|
|
|
|
|
|
software much more, unless I get so many donations that I can consider working |
1360
|
|
|
|
|
|
|
on free software full time (let's all have a chuckle at that together). |
1361
|
|
|
|
|
|
|
|
1362
|
|
|
|
|
|
|
To donate, log into PayPal and send money to autarch@urth.org, or use the |
1363
|
|
|
|
|
|
|
button at L<http://www.urth.org/~autarch/fs-donation.html>. |
1364
|
|
|
|
|
|
|
|
1365
|
|
|
|
|
|
|
=head1 AUTHORS |
1366
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
=over 4 |
1368
|
|
|
|
|
|
|
|
1369
|
|
|
|
|
|
|
=item * |
1370
|
|
|
|
|
|
|
|
1371
|
|
|
|
|
|
|
Dave Rolsky <autarch@urth.org> |
1372
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
=item * |
1374
|
|
|
|
|
|
|
|
1375
|
|
|
|
|
|
|
Rick Measham <rickm@cpan.org> |
1376
|
|
|
|
|
|
|
|
1377
|
|
|
|
|
|
|
=back |
1378
|
|
|
|
|
|
|
|
1379
|
|
|
|
|
|
|
=head1 CONTRIBUTORS |
1380
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
=for stopwords Christian Hansen D. Ilmari Mannsåker gregor herrmann key-amb Mohammad S Anwar |
1382
|
|
|
|
|
|
|
|
1383
|
|
|
|
|
|
|
=over 4 |
1384
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
=item * |
1386
|
|
|
|
|
|
|
|
1387
|
|
|
|
|
|
|
Christian Hansen <chansen@cpan.org> |
1388
|
|
|
|
|
|
|
|
1389
|
|
|
|
|
|
|
=item * |
1390
|
|
|
|
|
|
|
|
1391
|
|
|
|
|
|
|
D. Ilmari Mannsåker <ilmari.mannsaker@net-a-porter.com> |
1392
|
|
|
|
|
|
|
|
1393
|
|
|
|
|
|
|
=item * |
1394
|
|
|
|
|
|
|
|
1395
|
|
|
|
|
|
|
gregor herrmann <gregoa@debian.org> |
1396
|
|
|
|
|
|
|
|
1397
|
|
|
|
|
|
|
=item * |
1398
|
|
|
|
|
|
|
|
1399
|
|
|
|
|
|
|
key-amb <yasutake.kiyoshi@gmail.com> |
1400
|
|
|
|
|
|
|
|
1401
|
|
|
|
|
|
|
=item * |
1402
|
|
|
|
|
|
|
|
1403
|
|
|
|
|
|
|
Mohammad S Anwar <mohammad.anwar@yahoo.com> |
1404
|
|
|
|
|
|
|
|
1405
|
|
|
|
|
|
|
=back |
1406
|
|
|
|
|
|
|
|
1407
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
1408
|
|
|
|
|
|
|
|
1409
|
|
|
|
|
|
|
This software is Copyright (c) 2015 - 2020 by Dave Rolsky. |
1410
|
|
|
|
|
|
|
|
1411
|
|
|
|
|
|
|
This is free software, licensed under: |
1412
|
|
|
|
|
|
|
|
1413
|
|
|
|
|
|
|
The Artistic License 2.0 (GPL Compatible) |
1414
|
|
|
|
|
|
|
|
1415
|
|
|
|
|
|
|
The full text of the license can be found in the |
1416
|
|
|
|
|
|
|
F<LICENSE> file included with this distribution. |
1417
|
|
|
|
|
|
|
|
1418
|
|
|
|
|
|
|
=cut |