| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
=head1 NAME |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
DateTime::TimeZone::SystemV - System V and POSIX timezone strings |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use DateTime::TimeZone::SystemV; |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
$tz = DateTime::TimeZone::SystemV->new( |
|
10
|
|
|
|
|
|
|
name => "US Eastern", |
|
11
|
|
|
|
|
|
|
recipe => "EST5EDT,M3.2.0,M11.1.0"); |
|
12
|
|
|
|
|
|
|
$tz = DateTime::TimeZone::SystemV->new( |
|
13
|
|
|
|
|
|
|
"EST5EDT,M3.2.0,M11.1.0"); |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
if($tz->is_floating) { ... |
|
16
|
|
|
|
|
|
|
if($tz->is_utc) { ... |
|
17
|
|
|
|
|
|
|
if($tz->is_olson) { ... |
|
18
|
|
|
|
|
|
|
$category = $tz->category; |
|
19
|
|
|
|
|
|
|
$tz_string = $tz->name; |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
if($tz->has_dst_changes) { ... |
|
22
|
|
|
|
|
|
|
if($tz->is_dst_for_datetime($dt)) { ... |
|
23
|
|
|
|
|
|
|
$offset = $tz->offset_for_datetime($dt); |
|
24
|
|
|
|
|
|
|
$abbrev = $tz->short_name_for_datetime($dt); |
|
25
|
|
|
|
|
|
|
$offset = $tz->offset_for_local_datetime($dt); |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
An instance of this class represents a timezone that was specified by |
|
30
|
|
|
|
|
|
|
means of a System V timezone recipe or an extended form of the same syntax |
|
31
|
|
|
|
|
|
|
(such as that specified by POSIX). These can express a plain offset from |
|
32
|
|
|
|
|
|
|
Universal Time, or a system of two offsets (standard and daylight saving |
|
33
|
|
|
|
|
|
|
time) switching on a yearly cycle according to certain types of rule. |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
This class implements the L interface, so that its |
|
36
|
|
|
|
|
|
|
instances can be used with L objects. |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=head1 SYSTEM V TIMEZONE RECIPE SYSTEM |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
This module supports multiple versions of the timezone recipe syntax |
|
41
|
|
|
|
|
|
|
derived from System V. Specifically, it supports the version specified |
|
42
|
|
|
|
|
|
|
by POSIX.1, and the extension of the POSIX format that is used by version |
|
43
|
|
|
|
|
|
|
3 of the L file format. |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
A timezone may be specified that has a fixed offset by the |
|
46
|
|
|
|
|
|
|
syntax "II", or a timezone with DST by the syntax |
|
47
|
|
|
|
|
|
|
"III[I]B<,>IB<,>I". "I" specifies an |
|
48
|
|
|
|
|
|
|
abbreviation by which an offset is known, "I" specifies the offset, |
|
49
|
|
|
|
|
|
|
and "I" is a rule for when DST starts or ends. For backward |
|
50
|
|
|
|
|
|
|
compatibility, the rules part may also be omitted from a DST-using |
|
51
|
|
|
|
|
|
|
timezone, in which case some built-in default rules are used; don't rely |
|
52
|
|
|
|
|
|
|
on those rules being useful. |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
An abbreviation must be a string of three or more characters from ASCII |
|
55
|
|
|
|
|
|
|
alphanumerics, "B<+>", and "B<->". If it contains only ASCII alphabetic |
|
56
|
|
|
|
|
|
|
characters then the abbreviation specification "I" may be simply |
|
57
|
|
|
|
|
|
|
the abbreviation. Otherwise "I" must consist of the abbreviation |
|
58
|
|
|
|
|
|
|
wrapped in angle brackets ("B<< < >>...B<< > >>"). The angle bracket |
|
59
|
|
|
|
|
|
|
form is always allowed. POSIX allows an implementation to set an upper |
|
60
|
|
|
|
|
|
|
limit on the length of timezone abbreviations. The limit is known as |
|
61
|
|
|
|
|
|
|
C, and is required to be no less than 6 (characters/bytes). |
|
62
|
|
|
|
|
|
|
Abbreviations longer than 6 characters are therefore not portable. |
|
63
|
|
|
|
|
|
|
This class imposes no such limit. |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
An offset (from Universal Time), "I", is given in hours, or |
|
66
|
|
|
|
|
|
|
hours and minutes, or hours and minutes and seconds, with an optional |
|
67
|
|
|
|
|
|
|
preceding sign. Hours, minutes, and seconds must be separated by colons. |
|
68
|
|
|
|
|
|
|
The hours may be one or two digits, and the minutes and seconds must be |
|
69
|
|
|
|
|
|
|
two digits each. The maximum magnitude permitted is 24:59:59. The sign |
|
70
|
|
|
|
|
|
|
in the specification is the opposite of the sign of the actual offset. |
|
71
|
|
|
|
|
|
|
If no sign is given then the default is "B<+>", meaning a timezone that |
|
72
|
|
|
|
|
|
|
is behind UT (or equal to UT if the offset is zero). If no DST offset |
|
73
|
|
|
|
|
|
|
is specified, it defaults to one hour ahead of the standard offset. |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
A DST-using timezone has one transition to DST and one transition to |
|
76
|
|
|
|
|
|
|
standard time in each Gregorian year. The transitions may be in either |
|
77
|
|
|
|
|
|
|
order within the year. If the transitions are in different orders from |
|
78
|
|
|
|
|
|
|
year to year then the behaviour is undefined; don't rely on it remaining |
|
79
|
|
|
|
|
|
|
the same in future versions. Likewise, the behaviour is generally |
|
80
|
|
|
|
|
|
|
undefined if transitions coincide. However, in the L variant, |
|
81
|
|
|
|
|
|
|
if the rules specify a transition to DST at 00:00 standard time on 1 |
|
82
|
|
|
|
|
|
|
January and a transition to standard time at 24:00 standard time on 31 |
|
83
|
|
|
|
|
|
|
December, which makes the transitions coincide with those of adjacent |
|
84
|
|
|
|
|
|
|
years, then the timezone is treated as observing DST all year. |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
A transition rule "I" takes the form "I[B>I]", where |
|
87
|
|
|
|
|
|
|
"I" is the rule giving the day on which the transition notionally |
|
88
|
|
|
|
|
|
|
takes place and "I" is the time of day at which the transition |
|
89
|
|
|
|
|
|
|
takes place. (A time of day outside the usual 24-hour range can make |
|
90
|
|
|
|
|
|
|
the transition actually take place on a different day.) The time may be |
|
91
|
|
|
|
|
|
|
given in hours, or hours and minutes, or hours and minutes and seconds. |
|
92
|
|
|
|
|
|
|
Hours, minutes, and seconds must be separated by colons. The minutes |
|
93
|
|
|
|
|
|
|
and seconds must be two digits each. In the POSIX variant, the hours |
|
94
|
|
|
|
|
|
|
may be one or two digits, with no preceding sign, and the time stated may |
|
95
|
|
|
|
|
|
|
range from 00:00:00 to 24:59:59 (almost an hour into the following day). |
|
96
|
|
|
|
|
|
|
In the L variant, the hours may be one to three digits, with |
|
97
|
|
|
|
|
|
|
optional preceding sign, and the time stated may range from -167:59:59 |
|
98
|
|
|
|
|
|
|
to +167:59:59 (a span of a little over two weeks). If the time is not |
|
99
|
|
|
|
|
|
|
stated then it defaults to 02:00:00. The time for the transition to DST |
|
100
|
|
|
|
|
|
|
is interpreted according to the standard offset, and the time for the |
|
101
|
|
|
|
|
|
|
transition to standard time is interpreted according to the DST offset. |
|
102
|
|
|
|
|
|
|
(Thus normally the transition time is interpreted according to the offset |
|
103
|
|
|
|
|
|
|
that prevailed immediately before the transition.) |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
A day rule "I" may take three forms. Firstly, "BI" means the |
|
106
|
|
|
|
|
|
|
month-day date that is the Ith day of a non-leap year. Thus "B" |
|
107
|
|
|
|
|
|
|
means the February 28 and "B" means March 1 (even in a leap year). |
|
108
|
|
|
|
|
|
|
February 29 cannot be specified this way. |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
Secondly, if "I" is just a decimal number, it means the (1+I)th |
|
111
|
|
|
|
|
|
|
day of the year. February 29 counts in this case, and it is not possible |
|
112
|
|
|
|
|
|
|
to specify December 31 of a leap year. |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
Thirdly, "I" may have the form "BIB<.>IB<.>I" means day |
|
115
|
|
|
|
|
|
|
I of the Ith week of the Ith month. The day is given as a single |
|
116
|
|
|
|
|
|
|
digit, with "B<0>" meaning Sunday and "B<6>" meaning Saturday. The first |
|
117
|
|
|
|
|
|
|
week contains days 1 to 7 of the month, the second week contains days 8 |
|
118
|
|
|
|
|
|
|
to 14, and so on. If "I" is "B<5>" then the last week of the month |
|
119
|
|
|
|
|
|
|
(containing its last seven days) is used, rather than the fifth week |
|
120
|
|
|
|
|
|
|
(which is incomplete). |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
Examples: |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=over |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=item MUT-4 |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
Mauritius time, since 1907: 4 hours ahead of UT all year. |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=item EST5EDT,M3.2.0,M11.1.0 |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
US Eastern timezone with DST, from 2007 onwards. 5 hours behind UT in |
|
133
|
|
|
|
|
|
|
winter and 4 hours behind in summer. Changes on the second Sunday in |
|
134
|
|
|
|
|
|
|
March and the first Sunday in November, in each case at 02:00 local time. |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=item NST3:30NDT,M3.2.0/0:01,M11.1.0/0:01 |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
Newfoundland timezone with DST, from 2007 onwards. 3.5 hours behind UT |
|
139
|
|
|
|
|
|
|
in winter and 2.5 hours behind in summer. Changes on the second Sunday in |
|
140
|
|
|
|
|
|
|
March and the first Sunday in November, in each case at 00:01 local time. |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=item GMT0BST,M3.5.0/1,M10.5.0 |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
UK civil time, from 1996 onwards. On UT during the winter, calling |
|
145
|
|
|
|
|
|
|
it "GMT", and 1 hour ahead of UT during the summer, called "BST". |
|
146
|
|
|
|
|
|
|
Changes on the last Sunday in March and the last Sunday in October, |
|
147
|
|
|
|
|
|
|
in each case at 01:00 UT. |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=item EST-10EST,M10.5.0,M3.5.0/3 |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
Australian Eastern timezone, from 2007 onwards. 10 hours ahead of UT in |
|
152
|
|
|
|
|
|
|
the southern winter (the middle of the calendar year), and 11 hours ahead |
|
153
|
|
|
|
|
|
|
in the southern summer. Changes to DST on the last Sunday in October, |
|
154
|
|
|
|
|
|
|
and back on the last Sunday in March, in each case at 02:00 standard time |
|
155
|
|
|
|
|
|
|
(16:00 UT of the preceding day). |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=item EET-2EEST,M3.5.4/24,M9.3.6/145 |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
Palestinian civil time, from 2012 onwards. 2 hours ahead of UT in winter |
|
160
|
|
|
|
|
|
|
and 3 hours ahead in summer. Changes at the end (24:00 local time) of |
|
161
|
|
|
|
|
|
|
the last Thursday in March and 01:00 local time on the Friday following |
|
162
|
|
|
|
|
|
|
the third Saturday in September (that is, the Friday falling between |
|
163
|
|
|
|
|
|
|
September 21 and September 27 inclusive). The extended time-of-day "145", |
|
164
|
|
|
|
|
|
|
meaning 01:00 of the day six days after the nominal day, is only valid |
|
165
|
|
|
|
|
|
|
in the L variant of the System V syntax. The time-of-day |
|
166
|
|
|
|
|
|
|
"24" is not so restricted, being permitted by POSIX. |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=back |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=cut |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
package DateTime::TimeZone::SystemV; |
|
173
|
|
|
|
|
|
|
|
|
174
|
4
|
|
|
4
|
|
3015
|
{ use 5.006; } |
|
|
4
|
|
|
|
|
14
|
|
|
175
|
4
|
|
|
4
|
|
23
|
use warnings; |
|
|
4
|
|
|
|
|
9
|
|
|
|
4
|
|
|
|
|
130
|
|
|
176
|
4
|
|
|
4
|
|
23
|
use strict; |
|
|
4
|
|
|
|
|
7
|
|
|
|
4
|
|
|
|
|
101
|
|
|
177
|
|
|
|
|
|
|
|
|
178
|
4
|
|
|
4
|
|
20
|
use Carp qw(croak); |
|
|
4
|
|
|
|
|
15
|
|
|
|
4
|
|
|
|
|
290
|
|
|
179
|
|
|
|
|
|
|
use Date::ISO8601 0.000 |
|
180
|
4
|
|
|
4
|
|
881
|
qw(month_days ymd_to_cjdn present_ymd year_days cjdn_to_yd cjdn_to_ywd); |
|
|
4
|
|
|
|
|
6252
|
|
|
|
4
|
|
|
|
|
368
|
|
|
181
|
4
|
|
|
4
|
|
2149
|
use Params::Classify 0.000 qw(is_undef is_string); |
|
|
4
|
|
|
|
|
9274
|
|
|
|
4
|
|
|
|
|
9257
|
|
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
our $VERSION = "0.010"; |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
my $rdn_epoch_cjdn = 1721425; |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
my $abbrev_rx = qr#[A-Za-z]{3,}|\<[-+0-9A-Za-z]{3,}\>#; |
|
188
|
|
|
|
|
|
|
my $offset_rx = qr#[-+]?(?:2[0-4]|[01]?[0-9])(?::[0-5][0-9](?::[0-5][0-9])?)?#; |
|
189
|
|
|
|
|
|
|
my $rule_date_rx = qr#J0*(?:3(?:[0-5][0-9]|6[0-5])|[12]?[0-9][0-9]|[1-9]) |
|
190
|
|
|
|
|
|
|
|0*(?:3(?:[0-5][0-9]|6[0-4])|[12]?[0-9][0-9]|[0-9]) |
|
191
|
|
|
|
|
|
|
|M0*(?:1[0-2]|[1-9])\.0*[1-5]\.0*[0-6]#x; |
|
192
|
|
|
|
|
|
|
my $posix_rule_time_rx = |
|
193
|
|
|
|
|
|
|
qr#(?:2[0-4]|[01]?[0-9])(?::[0-5][0-9](?::[0-5][0-9])?)?#; |
|
194
|
|
|
|
|
|
|
my $tzfile3_rule_time_rx = |
|
195
|
|
|
|
|
|
|
qr#[-+]?(?:16[0-7]|1[0-5][0-9]|0[0-9][0-9]|[0-9]{1,2}) |
|
196
|
|
|
|
|
|
|
(?::[0-5][0-9](?::[0-5][0-9])?)?#x; |
|
197
|
|
|
|
|
|
|
my $posix_rule_dt_rx = qr#${rule_date_rx}(?:/${posix_rule_time_rx})?#o; |
|
198
|
|
|
|
|
|
|
my $tzfile3_rule_dt_rx = qr#${rule_date_rx}(?:/${tzfile3_rule_time_rx})?#o; |
|
199
|
|
|
|
|
|
|
my $posix_tz_rx = qr#${abbrev_rx}${offset_rx} |
|
200
|
|
|
|
|
|
|
(?:${abbrev_rx}(?:${offset_rx})? |
|
201
|
|
|
|
|
|
|
(?:,${posix_rule_dt_rx},${posix_rule_dt_rx})?)?#xo; |
|
202
|
|
|
|
|
|
|
my $tzfile3_tz_rx = qr#${abbrev_rx}${offset_rx} |
|
203
|
|
|
|
|
|
|
(?:${abbrev_rx}(?:${offset_rx})? |
|
204
|
|
|
|
|
|
|
(?:,${tzfile3_rule_dt_rx},${tzfile3_rule_dt_rx})?)?#xo; |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
my %tz_rx = ( |
|
207
|
|
|
|
|
|
|
posix => $posix_tz_rx, |
|
208
|
|
|
|
|
|
|
tzfile3 => $tzfile3_tz_rx, |
|
209
|
|
|
|
|
|
|
); |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub _parse_abbrev($) { |
|
212
|
58
|
|
|
58
|
|
166
|
my($spec) = @_; |
|
213
|
58
|
100
|
|
|
|
264
|
return $spec =~ /\A\<(.*)\>\z/s ? $1 : $spec; |
|
214
|
|
|
|
|
|
|
} |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
sub _parse_offset($) { |
|
217
|
64
|
|
|
64
|
|
149
|
my($spec) = @_; |
|
218
|
64
|
|
|
|
|
376
|
my($sign, $h, $m, $s) = |
|
219
|
|
|
|
|
|
|
($spec =~ /\A([-+]?)([0-9]+)(?::([0-9]+)(?::([0-9]+))?)?\z/); |
|
220
|
64
|
|
100
|
|
|
514
|
return ($sign eq "-" ? 1 : -1) * |
|
221
|
|
|
|
|
|
|
($h*3600 + (defined($m) ? $m*60 + (defined($s) ? $s : 0) : 0)) |
|
222
|
|
|
|
|
|
|
|| 0; |
|
223
|
|
|
|
|
|
|
} |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub _parse_rule($$) { |
|
226
|
52
|
|
|
52
|
|
130
|
my($spec, $offset) = @_; |
|
227
|
52
|
|
|
|
|
188
|
my($drule, $tod) = split(m#/#, $spec); |
|
228
|
|
|
|
|
|
|
return { |
|
229
|
52
|
100
|
|
|
|
227
|
drule => $drule, |
|
230
|
|
|
|
|
|
|
sod => -$offset + |
|
231
|
|
|
|
|
|
|
(defined($tod) ? -_parse_offset($tod) : 7200), |
|
232
|
|
|
|
|
|
|
}; |
|
233
|
|
|
|
|
|
|
} |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=head1 CONSTRUCTOR |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=over |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
=item DateTime::TimeZone::SystemV->new(ATTR => VALUE, ...) |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
Constructs and returns a L-compatible timezone object that |
|
242
|
|
|
|
|
|
|
implements the timezone described by the recipe given in the arguments. |
|
243
|
|
|
|
|
|
|
The following attributes may be given: |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=over |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=item B |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
Name for the timezone object. This will be returned by the C |
|
250
|
|
|
|
|
|
|
method described below, and will be included in certain error messages. |
|
251
|
|
|
|
|
|
|
If not given, then the recipe is used as the timezone name. |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=item B |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
The short textual timezone recipe, as described in L
|
|
256
|
|
|
|
|
|
|
RECIPE SYSTEM>. Must be given. |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=item B |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
Keyword identifying the particular variant of the recipe system according |
|
261
|
|
|
|
|
|
|
to which the recipe is to be interpreted. It may be: |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=over |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=item B (default) |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
As specified by POSIX.1. |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=item B |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
As specified by version 3 of the L file format. |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=back |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=back |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=item DateTime::TimeZone::SystemV->new(RECIPE) |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
Simpler way to invoke the above constructor in the usual case. Only the |
|
280
|
|
|
|
|
|
|
recipe is given; it will be interpreted according to POSIX system, |
|
281
|
|
|
|
|
|
|
and the recipe will also be used as the timezone name. |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=cut |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
sub new { |
|
286
|
56
|
|
|
56
|
1
|
37267
|
my $class = shift; |
|
287
|
56
|
100
|
|
|
|
255
|
unshift @_, "recipe" if @_ == 1; |
|
288
|
56
|
|
|
|
|
224
|
my $self = bless({}, $class); |
|
289
|
56
|
|
|
|
|
134
|
my $recipe; |
|
290
|
|
|
|
|
|
|
my $system; |
|
291
|
56
|
|
|
|
|
173
|
while(@_) { |
|
292
|
70
|
|
|
|
|
169
|
my $attr = shift; |
|
293
|
70
|
|
|
|
|
145
|
my $value = shift; |
|
294
|
70
|
100
|
|
|
|
326
|
if($attr eq "name") { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
croak "timezone name specified redundantly" |
|
296
|
10
|
100
|
|
|
|
139
|
if exists $self->{name}; |
|
297
|
9
|
100
|
|
|
|
390
|
croak "timezone name must be a string" |
|
298
|
|
|
|
|
|
|
unless is_string($value); |
|
299
|
5
|
|
|
|
|
16
|
$self->{name} = $value; |
|
300
|
|
|
|
|
|
|
} elsif($attr eq "recipe") { |
|
301
|
43
|
100
|
|
|
|
248
|
croak "recipe specified redundantly" |
|
302
|
|
|
|
|
|
|
if defined $recipe; |
|
303
|
42
|
100
|
|
|
|
554
|
croak "recipe must be a string" |
|
304
|
|
|
|
|
|
|
unless is_string($value); |
|
305
|
38
|
|
|
|
|
135
|
$recipe = $value; |
|
306
|
|
|
|
|
|
|
} elsif($attr eq "system") { |
|
307
|
16
|
100
|
|
|
|
176
|
croak "system identifier specified redundantly" |
|
308
|
|
|
|
|
|
|
if defined $system; |
|
309
|
15
|
100
|
|
|
|
460
|
croak "system identifier must be a string" |
|
310
|
|
|
|
|
|
|
unless is_string($value); |
|
311
|
|
|
|
|
|
|
croak "system identifier not recognised" |
|
312
|
11
|
100
|
|
|
|
172
|
unless exists $tz_rx{$value}; |
|
313
|
10
|
|
|
|
|
41
|
$system = $value; |
|
314
|
|
|
|
|
|
|
} else { |
|
315
|
1
|
|
|
|
|
120
|
croak "unrecognised attribute `$attr'"; |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
} |
|
318
|
39
|
100
|
|
|
|
372
|
croak "recipe not specified" unless defined $recipe; |
|
319
|
37
|
100
|
|
|
|
180
|
$self->{name} = $recipe unless exists $self->{name}; |
|
320
|
37
|
100
|
|
|
|
125
|
$system = "posix" unless defined $system; |
|
321
|
37
|
100
|
|
|
|
4553
|
croak "not a valid SysV-style timezone recipe" |
|
322
|
|
|
|
|
|
|
unless $recipe =~ /\A$tz_rx{$system}\z/; |
|
323
|
32
|
|
|
|
|
398
|
$recipe =~ /\A($abbrev_rx)($offset_rx)/og; |
|
324
|
32
|
|
|
|
|
168
|
my($std_abbrev, $std_offset) = ($1, $2); |
|
325
|
32
|
|
|
|
|
116
|
$self->{std_abbrev} = _parse_abbrev($std_abbrev); |
|
326
|
32
|
|
|
|
|
109
|
$self->{std_offset} = _parse_offset($std_offset); |
|
327
|
32
|
100
|
|
|
|
183
|
return $self if $recipe =~ /\G\z/gc; |
|
328
|
26
|
|
|
|
|
467
|
$recipe =~ /\G($abbrev_rx)($offset_rx)?/g; |
|
329
|
26
|
|
|
|
|
110
|
my($dst_abbrev, $dst_offset) = ($1, $2); |
|
330
|
26
|
|
|
|
|
79
|
$self->{dst_abbrev} = _parse_abbrev($dst_abbrev); |
|
331
|
|
|
|
|
|
|
$self->{dst_offset} = defined($dst_offset) ? |
|
332
|
26
|
100
|
|
|
|
120
|
_parse_offset($dst_offset) : $self->{std_offset} + 3600; |
|
333
|
26
|
|
|
|
|
69
|
my($start_rule, $end_rule); |
|
334
|
26
|
100
|
|
|
|
137
|
if($recipe =~ /\G,(.*),(.*)/g) { |
|
335
|
16
|
|
|
|
|
76
|
($start_rule, $end_rule) = ($1, $2); |
|
336
|
|
|
|
|
|
|
} else { |
|
337
|
|
|
|
|
|
|
# default to US 1976 rules, which is what the ruleless |
|
338
|
|
|
|
|
|
|
# old SysV style specs were expected to do |
|
339
|
10
|
|
|
|
|
24
|
($start_rule, $end_rule) = ("M4.5.0", "M10.5.0"); |
|
340
|
|
|
|
|
|
|
} |
|
341
|
26
|
|
|
|
|
94
|
$self->{start_rule} = _parse_rule($start_rule, $self->{std_offset}); |
|
342
|
26
|
|
|
|
|
81
|
$self->{end_rule} = _parse_rule($end_rule, $self->{dst_offset}); |
|
343
|
26
|
50
|
100
|
|
|
187
|
if($system eq "tzfile3" && |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
344
|
|
|
|
|
|
|
$self->{start_rule}->{drule} =~ /\A(?:J0*1|0+)\z/ && |
|
345
|
|
|
|
|
|
|
$self->{start_rule}->{sod} == -$self->{std_offset} && |
|
346
|
|
|
|
|
|
|
$self->{end_rule}->{drule} =~ /\AJ0*365\z/ && |
|
347
|
|
|
|
|
|
|
$self->{end_rule}->{sod} == 86400-$self->{std_offset}) { |
|
348
|
|
|
|
|
|
|
delete $self->{$_} |
|
349
|
2
|
|
|
|
|
21
|
foreach qw(std_abbrev std_offset start_rule end_rule); |
|
350
|
|
|
|
|
|
|
} |
|
351
|
26
|
|
|
|
|
205
|
return $self; |
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=back |
|
355
|
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
=head1 METHODS |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
These methods are all part of the L interface. |
|
359
|
|
|
|
|
|
|
See that class for the general meaning of these methods; the documentation |
|
360
|
|
|
|
|
|
|
below only comments on the specific behaviour of this class. |
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=head2 Identification |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
=over |
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
=item $tz->is_floating |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
Returns false. |
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
=cut |
|
371
|
|
|
|
|
|
|
|
|
372
|
2
|
|
|
2
|
1
|
741
|
sub is_floating { 0 } |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
=item $tz->is_utc |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
Returns false. |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
=cut |
|
379
|
|
|
|
|
|
|
|
|
380
|
2
|
|
|
2
|
1
|
11
|
sub is_utc { 0 } |
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=item $tz->is_olson |
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
Returns false. |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
=cut |
|
387
|
|
|
|
|
|
|
|
|
388
|
2
|
|
|
2
|
1
|
10
|
sub is_olson { 0 } |
|
389
|
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=item $tz->category |
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
Returns C, because the category concept doesn't properly apply |
|
393
|
|
|
|
|
|
|
to these timezones. |
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=cut |
|
396
|
|
|
|
|
|
|
|
|
397
|
2
|
|
|
2
|
1
|
15
|
sub category { undef } |
|
398
|
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=item $tz->name |
|
400
|
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
Returns the timezone name. Usually this is the recipe that was supplied |
|
402
|
|
|
|
|
|
|
to the constructor, but it can be overridden by the constructor's B |
|
403
|
|
|
|
|
|
|
attribute. |
|
404
|
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
=cut |
|
406
|
|
|
|
|
|
|
|
|
407
|
6
|
|
|
6
|
1
|
1576
|
sub name { $_[0]->{name} } |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
=back |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
=head2 Offsets |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=over |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=item $tz->has_dst_changes |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
Returns a truth value indicating whether the timezone includes a DST offset. |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
=cut |
|
420
|
|
|
|
|
|
|
|
|
421
|
2
|
|
|
2
|
1
|
11
|
sub has_dst_changes { exists $_[0]->{dst_abbrev} } |
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
=item $tz->is_dst_for_datetime(DT) |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
I must be a L-compatible object (specifically, it must |
|
426
|
|
|
|
|
|
|
implement the C method). Returns a truth value indicating |
|
427
|
|
|
|
|
|
|
whether the timezone is on DST at the instant represented by I. |
|
428
|
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
=cut |
|
430
|
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
sub _rule_doy($$) { |
|
432
|
4483
|
|
|
4483
|
|
9695
|
my($drule, $year) = @_; |
|
433
|
4483
|
100
|
|
|
|
25140
|
if($drule =~ /\AJ([0-9]+)\z/) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
434
|
1497
|
|
|
|
|
3884
|
my $j = $1; |
|
435
|
1497
|
100
|
|
|
|
3758
|
if($j < 60) { |
|
436
|
390
|
|
|
|
|
1159
|
return $j; |
|
437
|
|
|
|
|
|
|
} else { |
|
438
|
1107
|
|
|
|
|
2623
|
return year_days($year) - 365 + $j; |
|
439
|
|
|
|
|
|
|
} |
|
440
|
|
|
|
|
|
|
} elsif($drule =~ /\A([0-9]+)\z/) { |
|
441
|
384
|
|
|
|
|
1280
|
return 1 + $1; |
|
442
|
|
|
|
|
|
|
} elsif($drule =~ /\AM([0-9]+)\.([0-9]+)\.([0-9]+)\z/) { |
|
443
|
2602
|
|
|
|
|
10715
|
my($m, $w, $dow) = ($1, $2, $3); |
|
444
|
2602
|
100
|
|
|
|
8352
|
my $fdom = ($w == 5 ? month_days($year, $m) : $w*7) - 6; |
|
445
|
2602
|
|
|
|
|
21357
|
my(undef, undef, $fdow) = |
|
446
|
|
|
|
|
|
|
cjdn_to_ywd(ymd_to_cjdn($year, $m, $fdom)); |
|
447
|
2602
|
|
|
|
|
553977
|
my $dom = $fdom + ($dow + 7 - $fdow) % 7; |
|
448
|
2602
|
|
|
|
|
6866
|
my(undef, $doy) = cjdn_to_yd(ymd_to_cjdn($year, $m, $dom)); |
|
449
|
2602
|
|
|
|
|
264444
|
return $doy; |
|
450
|
|
|
|
|
|
|
} else { |
|
451
|
0
|
|
|
|
|
0
|
die "internal error: unrecognised day rule"; |
|
452
|
|
|
|
|
|
|
} |
|
453
|
|
|
|
|
|
|
} |
|
454
|
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
sub _is_dst_for_utc_rdn_sod { |
|
456
|
907
|
|
|
907
|
|
2173
|
my($self, $rdn, $sod) = @_; |
|
457
|
907
|
|
|
|
|
2790
|
my($year, $doy) = cjdn_to_yd($rdn + $rdn_epoch_cjdn); |
|
458
|
907
|
|
|
|
|
39050
|
my $soy = $doy * 86400 + $sod; |
|
459
|
907
|
|
|
|
|
1651
|
my @latest_change; |
|
460
|
907
|
|
|
|
|
2148
|
foreach my $change_type (qw(end_rule start_rule)) { |
|
461
|
1814
|
|
|
|
|
4804
|
for(my $y = $year+1, my $doff = year_days($year); ; |
|
462
|
|
|
|
|
|
|
$doff -= year_days(--$y)) { |
|
463
|
|
|
|
|
|
|
my $change_soy = |
|
464
|
|
|
|
|
|
|
($doff + _rule_doy($self->{$change_type} |
|
465
|
|
|
|
|
|
|
->{drule}, $y)) |
|
466
|
4483
|
|
|
|
|
65583
|
* 86400 + $self->{$change_type}->{sod}; |
|
467
|
4483
|
100
|
|
|
|
29245
|
if($change_soy <= $soy) { |
|
468
|
1814
|
|
|
|
|
3682
|
push @latest_change, $change_soy; |
|
469
|
1814
|
|
|
|
|
4440
|
last; |
|
470
|
|
|
|
|
|
|
} |
|
471
|
|
|
|
|
|
|
} |
|
472
|
|
|
|
|
|
|
} |
|
473
|
907
|
|
|
|
|
6978
|
return $latest_change[1] > $latest_change[0]; |
|
474
|
|
|
|
|
|
|
} |
|
475
|
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
sub is_dst_for_datetime { |
|
477
|
816
|
|
|
816
|
1
|
242349
|
my($self, $dt) = @_; |
|
478
|
816
|
100
|
|
|
|
2779
|
return 0 unless exists $self->{dst_abbrev}; |
|
479
|
789
|
100
|
|
|
|
2581
|
return 1 unless exists $self->{std_abbrev}; |
|
480
|
735
|
|
|
|
|
2468
|
my($utc_rdn, $utc_sod) = $dt->utc_rd_values; |
|
481
|
735
|
100
|
|
|
|
4884
|
$utc_sod = 86399 if $utc_sod >= 86400; |
|
482
|
735
|
|
|
|
|
2118
|
return $self->_is_dst_for_utc_rdn_sod($utc_rdn, $utc_sod); |
|
483
|
|
|
|
|
|
|
} |
|
484
|
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
=item $tz->offset_for_datetime(DT) |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
I must be a L-compatible object (specifically, it must |
|
488
|
|
|
|
|
|
|
implement the C method). Returns the offset from UT that |
|
489
|
|
|
|
|
|
|
is in effect at the instant represented by I, in seconds. |
|
490
|
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
=cut |
|
492
|
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
sub offset_for_datetime { |
|
494
|
272
|
|
|
272
|
1
|
871
|
my($self, $dt) = @_; |
|
495
|
272
|
100
|
|
|
|
1082
|
return $self->{$self->is_dst_for_datetime($dt) ? |
|
496
|
|
|
|
|
|
|
"dst_offset" : "std_offset"}; |
|
497
|
|
|
|
|
|
|
} |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
=item $tz->short_name_for_datetime(DT) |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
I must be a L-compatible object (specifically, it |
|
502
|
|
|
|
|
|
|
must implement the C method). Returns the time scale |
|
503
|
|
|
|
|
|
|
abbreviation for the offset that is in effect at the instant represented |
|
504
|
|
|
|
|
|
|
by I. |
|
505
|
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
=cut |
|
507
|
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
sub short_name_for_datetime { |
|
509
|
272
|
|
|
272
|
1
|
986
|
my($self, $dt) = @_; |
|
510
|
272
|
100
|
|
|
|
975
|
return $self->{$self->is_dst_for_datetime($dt) ? |
|
511
|
|
|
|
|
|
|
"dst_abbrev" : "std_abbrev"}; |
|
512
|
|
|
|
|
|
|
} |
|
513
|
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=item $tz->offset_for_local_datetime(DT) |
|
515
|
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
I must be a L-compatible object (specifically, it |
|
517
|
|
|
|
|
|
|
must implement the C method). Takes the local |
|
518
|
|
|
|
|
|
|
time represented by I (regardless of what absolute time it also |
|
519
|
|
|
|
|
|
|
represents), and interprets that as a local time in the timezone of the |
|
520
|
|
|
|
|
|
|
timezone object (not the timezone used in I). Returns the offset |
|
521
|
|
|
|
|
|
|
from UT that is in effect at that local time, in seconds. |
|
522
|
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
If the local time given is ambiguous due to a nearby offset change, the |
|
524
|
|
|
|
|
|
|
numerically lower offset (usually the standard one) is returned with no |
|
525
|
|
|
|
|
|
|
warning of the situation. If the local time given does not exist due |
|
526
|
|
|
|
|
|
|
to a nearby offset change, the method Cs saying so. |
|
527
|
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
=cut |
|
529
|
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
sub _local_to_utc_rdn_sod($$$) { |
|
531
|
172
|
|
|
172
|
|
338
|
my($rdn, $sod, $offset) = @_; |
|
532
|
172
|
|
|
|
|
274
|
$sod -= $offset; |
|
533
|
172
|
|
|
|
|
425
|
while($sod < 0) { |
|
534
|
0
|
|
|
|
|
0
|
$rdn--; |
|
535
|
0
|
|
|
|
|
0
|
$sod += 86400; |
|
536
|
|
|
|
|
|
|
} |
|
537
|
172
|
|
|
|
|
338
|
while($sod >= 86400) { |
|
538
|
36
|
|
|
|
|
69
|
$rdn++; |
|
539
|
36
|
|
|
|
|
81
|
$sod -= 86400; |
|
540
|
|
|
|
|
|
|
} |
|
541
|
172
|
|
|
|
|
385
|
return ($rdn, $sod); |
|
542
|
|
|
|
|
|
|
} |
|
543
|
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
sub _is_dst_for_local_datetime { |
|
545
|
96
|
|
|
96
|
|
195
|
my($self, $dt) = @_; |
|
546
|
96
|
100
|
|
|
|
309
|
return 0 unless exists $self->{dst_abbrev}; |
|
547
|
90
|
100
|
|
|
|
234
|
return 1 unless exists $self->{std_abbrev}; |
|
548
|
86
|
|
|
|
|
236
|
my($lcl_rdn, $lcl_sod) = $dt->local_rd_values; |
|
549
|
86
|
50
|
|
|
|
477
|
$lcl_sod = 86399 if $lcl_sod >= 86400; |
|
550
|
|
|
|
|
|
|
my($std_rdn, $std_sod) = |
|
551
|
86
|
|
|
|
|
255
|
_local_to_utc_rdn_sod($lcl_rdn, $lcl_sod, $self->{std_offset}); |
|
552
|
|
|
|
|
|
|
my($dst_rdn, $dst_sod) = |
|
553
|
86
|
|
|
|
|
230
|
_local_to_utc_rdn_sod($lcl_rdn, $lcl_sod, $self->{dst_offset}); |
|
554
|
86
|
|
|
|
|
232
|
my $std_ok = !$self->_is_dst_for_utc_rdn_sod($std_rdn, $std_sod); |
|
555
|
86
|
|
|
|
|
282
|
my $dst_ok = $self->_is_dst_for_utc_rdn_sod($dst_rdn, $dst_sod); |
|
556
|
86
|
100
|
|
|
|
216
|
if($std_ok) { |
|
557
|
43
|
100
|
|
|
|
96
|
if($dst_ok) { |
|
558
|
4
|
|
|
|
|
39
|
return $self->{std_offset} > $self->{dst_offset}; |
|
559
|
|
|
|
|
|
|
} else { |
|
560
|
39
|
|
|
|
|
224
|
return 0; |
|
561
|
|
|
|
|
|
|
} |
|
562
|
|
|
|
|
|
|
} else { |
|
563
|
43
|
100
|
|
|
|
128
|
if($dst_ok) { |
|
564
|
39
|
|
|
|
|
294
|
return 1; |
|
565
|
|
|
|
|
|
|
} else { |
|
566
|
4
|
|
|
|
|
8
|
croak "local time @{[ |
|
567
|
4
|
|
|
|
|
11
|
present_ymd($lcl_rdn + $rdn_epoch_cjdn) |
|
568
|
|
|
|
|
|
|
]}T@{[ |
|
569
|
4
|
|
|
|
|
322
|
sprintf(q(%02d:%02d:%02d), |
|
570
|
|
|
|
|
|
|
int($lcl_sod/3600), |
|
571
|
|
|
|
|
|
|
int($lcl_sod/60)%60, |
|
572
|
|
|
|
|
|
|
$lcl_sod%60) |
|
573
|
4
|
|
|
|
|
479
|
]} does not exist in the @{[$self->{name}]} timezone ". |
|
574
|
|
|
|
|
|
|
"due to offset change"; |
|
575
|
|
|
|
|
|
|
} |
|
576
|
|
|
|
|
|
|
} |
|
577
|
|
|
|
|
|
|
} |
|
578
|
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
sub offset_for_local_datetime { |
|
580
|
96
|
|
|
96
|
1
|
7604
|
my($self, $dt) = @_; |
|
581
|
96
|
100
|
|
|
|
261
|
return $self->{$self->_is_dst_for_local_datetime($dt) ? |
|
582
|
|
|
|
|
|
|
"dst_offset" : "std_offset"}; |
|
583
|
|
|
|
|
|
|
} |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
=back |
|
586
|
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
588
|
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
L, |
|
590
|
|
|
|
|
|
|
L, |
|
591
|
|
|
|
|
|
|
L, |
|
592
|
|
|
|
|
|
|
L |
|
593
|
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
=head1 AUTHOR |
|
595
|
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
Andrew Main (Zefram) |
|
597
|
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
599
|
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
Copyright (C) 2007, 2009, 2010, 2011, 2012, 2013, 2017 |
|
601
|
|
|
|
|
|
|
Andrew Main (Zefram) |
|
602
|
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
=head1 LICENSE |
|
604
|
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
This module is free software; you can redistribute it and/or modify it |
|
606
|
|
|
|
|
|
|
under the same terms as Perl itself. |
|
607
|
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
=cut |
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
1; |