line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package DateTime::Format::DateManip; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
15251
|
use strict; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
63
|
|
4
|
|
|
|
|
|
|
|
5
|
2
|
|
|
2
|
|
7
|
use vars qw ($VERSION); |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
131
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
$VERSION = '0.04'; |
8
|
|
|
|
|
|
|
|
9
|
2
|
|
|
2
|
|
15
|
use Carp; |
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
105
|
|
10
|
|
|
|
|
|
|
|
11
|
2
|
|
|
2
|
|
1133
|
use DateTime; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
use DateTime::Duration; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
use Date::Manip; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# All formats are in the ASCII range so we can safely turn off UTF8 support |
18
|
|
|
|
|
|
|
use bytes; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# This takes a Date::Manip string and converts it to a DateTime object |
21
|
|
|
|
|
|
|
# Note that the Date::Manip string just needs to be something that |
22
|
|
|
|
|
|
|
# Date::Manip::ParseDate() can format. |
23
|
|
|
|
|
|
|
# undef is returned if the string can not be converted. |
24
|
|
|
|
|
|
|
sub parse_datetime { |
25
|
|
|
|
|
|
|
my ($class, $dm_date) = @_; |
26
|
|
|
|
|
|
|
croak "Missing DateManip parseable string" unless defined $dm_date; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# Get the timezone name and the date information and zome offset from |
29
|
|
|
|
|
|
|
# the Date::Manip string. |
30
|
|
|
|
|
|
|
my ($dm_tz, @bits) = UnixDate($dm_date, qw( %Z %Y %m %d %H %M %S %z )); |
31
|
|
|
|
|
|
|
return undef unless @bits; |
32
|
|
|
|
|
|
|
my @args = merge_lists([qw( year month day hour minute second time_zone )], |
33
|
|
|
|
|
|
|
\@bits); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Construct the DateTime object and use the offset timezone |
36
|
|
|
|
|
|
|
my $dt = DateTime->new(@args); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# See if there is a better timezone to use |
39
|
|
|
|
|
|
|
my $dt_tz = $class->get_dt_timezone($dm_tz); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# Apply the final time zone |
42
|
|
|
|
|
|
|
if (defined $dt_tz) { |
43
|
|
|
|
|
|
|
$dt->set_time_zone($dt_tz); |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
return $dt; |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# Takes a DateTime object and returns the corresponding Date::Manip string (in |
50
|
|
|
|
|
|
|
# the format returned by ParseDate) |
51
|
|
|
|
|
|
|
sub format_datetime { |
52
|
|
|
|
|
|
|
my ($class, $dt) = @_; |
53
|
|
|
|
|
|
|
croak "Missing DateTime object" unless defined $dt; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# Note that we just use the TZ offset since Date::Manip doesn't |
56
|
|
|
|
|
|
|
# store time zone information with the dates but sets it system wide |
57
|
|
|
|
|
|
|
return ParseDate( $dt->strftime("%Y%m%dT%H%M%S %z") ); |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# Takes a Date::Manip Delta string and returns the corresponding |
61
|
|
|
|
|
|
|
# DateTime::Duration object or undef |
62
|
|
|
|
|
|
|
sub parse_duration { |
63
|
|
|
|
|
|
|
my ($class, $dm_delta) = @_; |
64
|
|
|
|
|
|
|
croak "Missing DateManip parseable delta string" unless defined $dm_delta; |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
my @bits = Delta_Format($dm_delta, 0, qw( %yv %Mv %wv %dv %hv %mv %sv )); |
67
|
|
|
|
|
|
|
return undef unless @bits; |
68
|
|
|
|
|
|
|
my @args = merge_lists([qw( years months weeks days hours minutes seconds )], |
69
|
|
|
|
|
|
|
\@bits); |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# We have to do this in two phases since Date::Manip handles the sign |
72
|
|
|
|
|
|
|
# for years and months separately from the sign for the rest. |
73
|
|
|
|
|
|
|
# DateTime::Duration assumes that the sign is the same across all |
74
|
|
|
|
|
|
|
# items so we make the inital duration with years and months and add |
75
|
|
|
|
|
|
|
# the second duration (which may be negative) to finish the duration |
76
|
|
|
|
|
|
|
my $dt_dur = DateTime::Duration->new(@args[0..3]); # Year and month |
77
|
|
|
|
|
|
|
$dt_dur->add(@args[4..13]); # The rest |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
return $dt_dur; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
# Takes a DateTime::Duration object and returns the corresponding |
83
|
|
|
|
|
|
|
# Date::Manip Delta string (in the format returned by ParseDateDelta) |
84
|
|
|
|
|
|
|
sub format_duration { |
85
|
|
|
|
|
|
|
my ($class, $dt_dur) = @_; |
86
|
|
|
|
|
|
|
croak "Missing DateTime::Duration object" unless defined $dt_dur; |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# Not all elements are defined (if they can be derived from smaller elements) |
89
|
|
|
|
|
|
|
my %bits = $dt_dur->deltas(); |
90
|
|
|
|
|
|
|
my $str = join(":", |
91
|
|
|
|
|
|
|
0, # Years |
92
|
|
|
|
|
|
|
$bits{months}, |
93
|
|
|
|
|
|
|
0, # Weeks |
94
|
|
|
|
|
|
|
$bits{days}, |
95
|
|
|
|
|
|
|
0, # Hours |
96
|
|
|
|
|
|
|
$bits{minutes}, |
97
|
|
|
|
|
|
|
$bits{seconds}, |
98
|
|
|
|
|
|
|
); |
99
|
|
|
|
|
|
|
my $dm_dur = ParseDateDelta($str); |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
return $dm_dur; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
BEGIN { |
106
|
|
|
|
|
|
|
# Date::Manip to DateTime timezone mapping (where possible) |
107
|
|
|
|
|
|
|
my %TZ_MAP = |
108
|
|
|
|
|
|
|
( |
109
|
|
|
|
|
|
|
# Abbreviations (see http://www.worldtimezone.com/wtz-names/timezonenames.html) |
110
|
|
|
|
|
|
|
# [1] - YST matches worldtimezone.com but not Canada/Yukon |
111
|
|
|
|
|
|
|
# [2] - AT matches worldtimezone.com but not Atlantic/Azores |
112
|
|
|
|
|
|
|
# [3] - City chosen at random from similar matches |
113
|
|
|
|
|
|
|
idlw => "-1200", # International Date Line West (-1200) |
114
|
|
|
|
|
|
|
nt => "-1100", # Nome (-1100) (obs. -1967) |
115
|
|
|
|
|
|
|
hst => "US/Hawaii", # Hawaii Standard (-1000) |
116
|
|
|
|
|
|
|
cat => "-1000", # Central Alaska (-1000) (obs. -1967) |
117
|
|
|
|
|
|
|
ahst => "-1000", # Alaska-Hawaii Standard (-1000) (obs. 1967-1983) |
118
|
|
|
|
|
|
|
akst => "US/Alaska", # Alaska Standard (-0900) |
119
|
|
|
|
|
|
|
yst => "-0900", # Yukon Standard (-0900) [1] |
120
|
|
|
|
|
|
|
hdt => "-0900", # Hawaii Daylight (-0900) (until 1947?) |
121
|
|
|
|
|
|
|
akdt => "US/Alaska", # Alaska Daylight (-0800) |
122
|
|
|
|
|
|
|
ydt => "-0800", # Yukon Daylight (-0900) [1] |
123
|
|
|
|
|
|
|
pst => "US/Pacific", # Pacific Standard (-0800) |
124
|
|
|
|
|
|
|
pdt => "US/Pacific", # Pacific Daylight (-0700) |
125
|
|
|
|
|
|
|
mst => "US/Mountain", # Mountain Standard (-0700) |
126
|
|
|
|
|
|
|
mdt => "US/Mountain", # Mountain Daylight (-0600) |
127
|
|
|
|
|
|
|
cst => "US/Central", # Central Standard (-0600) |
128
|
|
|
|
|
|
|
cdt => "US/Central", # Central Daylight (-0500) |
129
|
|
|
|
|
|
|
est => "US/Eastern", # Eastern Standard (-0500) |
130
|
|
|
|
|
|
|
sat => "-0400", # Chile (-0400) |
131
|
|
|
|
|
|
|
edt => "US/Eastern", # Eastern Daylight (-0400) |
132
|
|
|
|
|
|
|
ast => "Canada/Atlantic", # Atlantic Standard (-0400) |
133
|
|
|
|
|
|
|
#nst => "Canada/Newfoundland", # Newfoundland Standard (-0300) nst=North Sumatra +0630 |
134
|
|
|
|
|
|
|
nft => "Canada/Newfoundland", # Newfoundland (-0330) |
135
|
|
|
|
|
|
|
#gst => "-0300", # Greenland Standard (-0300) gst=Guam Standard +1000 |
136
|
|
|
|
|
|
|
#bst => "Brazil/East", # Brazil Standard (-0300) bst=British Summer +0100 |
137
|
|
|
|
|
|
|
adt => "Canada/Atlantic", # Atlantic Daylight (-0300) |
138
|
|
|
|
|
|
|
ndt => "Canada/Newfoundland", # Newfoundland Daylight (-0230) |
139
|
|
|
|
|
|
|
at => "-0200", # Azores (-0200) [2] |
140
|
|
|
|
|
|
|
wat => "Africa/Bangui", # West Africa (-0100) [3] |
141
|
|
|
|
|
|
|
gmt => "Europe/London", # Greenwich Mean (+0000) |
142
|
|
|
|
|
|
|
ut => "Etc/Universal", # Universal (+0000) |
143
|
|
|
|
|
|
|
utc => "UTC", # Universal (Coordinated) (+0000) |
144
|
|
|
|
|
|
|
wet => "Europe/Lisbon", # Western European (+0000) [3] |
145
|
|
|
|
|
|
|
west => "Europe/Lisbon", # Alias for Western European (+0000) [3] |
146
|
|
|
|
|
|
|
cet => "Europe/Madrid", # Central European (+0100) |
147
|
|
|
|
|
|
|
fwt => "Europe/Paris", # French Winter (+0100) |
148
|
|
|
|
|
|
|
met => "Europe/Brussels", # Middle European (+0100) |
149
|
|
|
|
|
|
|
mez => "Europe/Berlin", # Middle European (+0100) |
150
|
|
|
|
|
|
|
mewt => "Europe/Brussels", # Middle European Winter (+0100) |
151
|
|
|
|
|
|
|
swt => "Europe/Stockholm", # Swedish Winter (+0100) |
152
|
|
|
|
|
|
|
bst => "Europe/London", # British Summer (+0100) bst=Brazil standard -0300 |
153
|
|
|
|
|
|
|
gb => "Europe/London", # GMT with daylight savings (+0100) |
154
|
|
|
|
|
|
|
eet => "Europe/Bucharest", # Eastern Europe, USSR Zone 1 (+0200) |
155
|
|
|
|
|
|
|
cest => "Europe/Madrid", # Central European Summer (+0200) |
156
|
|
|
|
|
|
|
fst => "Europe/Paris", # French Summer (+0200) |
157
|
|
|
|
|
|
|
# ist => "Asia/Jerusalem", # Israel standard (+0200) (duplicate of Indian) |
158
|
|
|
|
|
|
|
mest => "Europe/Brussels", # Middle European Summer (+0200) |
159
|
|
|
|
|
|
|
mesz => "Europe/Berlin", # Middle European Summer (+0200) |
160
|
|
|
|
|
|
|
metdst => "Europe/Brussels", # An alias for mest used by HP-UX (+0200) |
161
|
|
|
|
|
|
|
sast => "Africa/Johannesburg", # South African Standard (+0200) |
162
|
|
|
|
|
|
|
sst => "Europe/Stockholm", # Swedish Summer (+0200) sst=South Sumatra +0700 |
163
|
|
|
|
|
|
|
bt => "+0300", # Baghdad, USSR Zone 2 (+0300) |
164
|
|
|
|
|
|
|
eest => "Europe/Bucharest", # Eastern Europe Summer (+0300) |
165
|
|
|
|
|
|
|
eetedt => "Europe/Bucharest", # Eastern Europe, USSR Zone 1 (+0300) |
166
|
|
|
|
|
|
|
# idt => "Asia/Jerusalem", # Israel Daylight (+0300) [Jerusalem doesn't honor DST) |
167
|
|
|
|
|
|
|
msk => "Europe/Moscow", # Moscow (+0300) |
168
|
|
|
|
|
|
|
it => "Asia/Tehran", # Iran (+0330) |
169
|
|
|
|
|
|
|
zp4 => "+0400", # USSR Zone 3 (+0400) |
170
|
|
|
|
|
|
|
msd => "Europe/Moscow", # Moscow Daylight (+0400) |
171
|
|
|
|
|
|
|
zp5 => "+0500", # USSR Zone 4 (+0500) |
172
|
|
|
|
|
|
|
ist => "Asia/Calcutta", # Indian Standard (+0530) |
173
|
|
|
|
|
|
|
zp6 => "+0600", # USSR Zone 5 (+0600) |
174
|
|
|
|
|
|
|
nst => "+0630", # North Sumatra (+0630) nst=Newfoundland Std -0330 |
175
|
|
|
|
|
|
|
#sst => "+0700", # South Sumatra, USSR Zone 6 sst=Swedish Summer +0200 |
176
|
|
|
|
|
|
|
hkt => "Asia/Hong_Kong", # Hong Kong (+0800) |
177
|
|
|
|
|
|
|
sgt => "Asia/Singapore", # Singapore (+0800) |
178
|
|
|
|
|
|
|
cct => "Asia/Shanghai", # China Coast, USSR Zone 7 (+0800) |
179
|
|
|
|
|
|
|
awst => "Australia/West", # West Australian Standard (+0800) |
180
|
|
|
|
|
|
|
wst => "Australia/West", # West Australian Standard (+0800) |
181
|
|
|
|
|
|
|
pht => "Asia/Manila", # Asia Manila (+0800) |
182
|
|
|
|
|
|
|
kst => "Asia/Seoul", # Republic of Korea (+0900) |
183
|
|
|
|
|
|
|
jst => "Asia/Tokyo", # Japan Standard, USSR Zone 8 (+0900) |
184
|
|
|
|
|
|
|
rok => "ROK", # Republic of Korea (+0900) |
185
|
|
|
|
|
|
|
cast => "Australia/South", # Central Australian Standard (+0930) |
186
|
|
|
|
|
|
|
east => "Australia/Victoria", # Eastern Australian Standard (+1000) |
187
|
|
|
|
|
|
|
gst => "Pacific/Guam", # Guam Standard, USSR Zone 9 gst=Greenland Std -0300 |
188
|
|
|
|
|
|
|
cadt => "Australia/South", # Central Australian Daylight (+1030) |
189
|
|
|
|
|
|
|
eadt => "Australia/Victoria", # Eastern Australian Daylight (+1100) |
190
|
|
|
|
|
|
|
idle => "+1200", # International Date Line East |
191
|
|
|
|
|
|
|
nzst => "Pacific/Auckland", # New Zealand Standard |
192
|
|
|
|
|
|
|
nzt => "Pacific/Auckland", # New Zealand |
193
|
|
|
|
|
|
|
nzdt => "Pacific/Auckland", # New Zealand Daylight |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# US Military Zones |
196
|
|
|
|
|
|
|
z => "+0000", |
197
|
|
|
|
|
|
|
a => "+0100", |
198
|
|
|
|
|
|
|
b => "+0200", |
199
|
|
|
|
|
|
|
c => "+0300", |
200
|
|
|
|
|
|
|
d => "+0400", |
201
|
|
|
|
|
|
|
e => "+0500", |
202
|
|
|
|
|
|
|
f => "+0600", |
203
|
|
|
|
|
|
|
g => "+0700", |
204
|
|
|
|
|
|
|
h => "+0800", |
205
|
|
|
|
|
|
|
i => "+0900", |
206
|
|
|
|
|
|
|
k => "+1000", |
207
|
|
|
|
|
|
|
l => "+1100", |
208
|
|
|
|
|
|
|
m => "+1200", |
209
|
|
|
|
|
|
|
n => "-0100", |
210
|
|
|
|
|
|
|
o => "-0200", |
211
|
|
|
|
|
|
|
p => "-0300", |
212
|
|
|
|
|
|
|
q => "-0400", |
213
|
|
|
|
|
|
|
r => "-0500", |
214
|
|
|
|
|
|
|
s => "-0600", |
215
|
|
|
|
|
|
|
t => "-0700", |
216
|
|
|
|
|
|
|
u => "-0800", |
217
|
|
|
|
|
|
|
v => "-0900", |
218
|
|
|
|
|
|
|
w => "-1000", |
219
|
|
|
|
|
|
|
x => "-1100", |
220
|
|
|
|
|
|
|
y => "-1200", |
221
|
|
|
|
|
|
|
); |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# Return the DateTime timezone corresponding to the given Date::Manip timezone or |
224
|
|
|
|
|
|
|
# return undef if there is no match. |
225
|
|
|
|
|
|
|
sub get_dt_timezone { |
226
|
|
|
|
|
|
|
my ($class, $dm_tz) = @_; |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# Work out the time zone that Date::Manip was using and try to reproduce it |
229
|
|
|
|
|
|
|
# in DateTime |
230
|
|
|
|
|
|
|
my $dt_tz = $dm_tz; |
231
|
|
|
|
|
|
|
if ($dm_tz =~ m{/}) { |
232
|
|
|
|
|
|
|
# Don't change it since it is in the complete form already |
233
|
|
|
|
|
|
|
# (e.g. America/New_York) |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
elsif ($dm_tz =~ m/^[-+]\d+$/) { |
236
|
|
|
|
|
|
|
# It is an offset, leave it alone (e.g. -0500) |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
else { |
239
|
|
|
|
|
|
|
# Look it up |
240
|
|
|
|
|
|
|
my $lc_tz = lc $dm_tz; |
241
|
|
|
|
|
|
|
$dt_tz = $TZ_MAP{$lc_tz}; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
return $dt_tz; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# Take a list of keys and a list of values and insersperse them and |
249
|
|
|
|
|
|
|
# return the result |
250
|
|
|
|
|
|
|
sub merge_lists { |
251
|
|
|
|
|
|
|
my ($keys, $values) = @_; |
252
|
|
|
|
|
|
|
die "Length mismatch" unless @$keys == @$values; |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# Add the argument names to the values |
255
|
|
|
|
|
|
|
my @result; |
256
|
|
|
|
|
|
|
for (my $i = 0; $i < @$keys; $i++) { |
257
|
|
|
|
|
|
|
push @result, $keys->[$i] => $values->[$i]; |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
return @result; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
1; |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
__END__ |