DateTime-TimeZone-SystemV

 view release on metacpan or  search on metacpan

lib/DateTime/TimeZone/SystemV.pm  view on Meta::CPAN

Hours, minutes, and seconds must be separated by colons.  The minutes
and seconds must be two digits each.  In the POSIX variant, the hours
may be one or two digits, with no preceding sign, and the time stated may
range from 00:00:00 to 24:59:59 (almost an hour into the following day).
In the L<tzfile(5)> variant, the hours may be one to three digits, with
optional preceding sign, and the time stated may range from -167:59:59
to +167:59:59 (a span of a little over two weeks).  If the time is not
stated then it defaults to 02:00:00.  The time for the transition to DST
is interpreted according to the standard offset, and the time for the
transition to standard time is interpreted according to the DST offset.
(Thus normally the transition time is interpreted according to the offset
that prevailed immediately before the transition.)

A day rule "I<ddd>" may take three forms.  Firstly, "B<J>I<nnn>" means the
month-day date that is the I<nnn>th day of a non-leap year.  Thus "B<J59>"
means the February 28 and "B<J60>" means March 1 (even in a leap year).
February 29 cannot be specified this way.

Secondly, if "I<ddd>" is just a decimal number, it means the (1+I<ddd>)th
day of the year.  February 29 counts in this case, and it is not possible
to specify December 31 of a leap year.

Thirdly, "I<ddd>" may have the form "B<M>I<m>B<.>I<w>B<.>I<d>" means day
I<d> of the I<w>th week of the I<m>th month.  The day is given as a single
digit, with "B<0>" meaning Sunday and "B<6>" meaning Saturday.  The first
week contains days 1 to 7 of the month, the second week contains days 8
to 14, and so on.  If "I<w>" is "B<5>" then the last week of the month
(containing its last seven days) is used, rather than the fifth week
(which is incomplete).

Examples:

=over

=item MUT-4

Mauritius time, since 1907: 4 hours ahead of UT all year.

=item EST5EDT,M3.2.0,M11.1.0

US Eastern timezone with DST, from 2007 onwards.  5 hours behind UT in
winter and 4 hours behind in summer.  Changes on the second Sunday in
March and the first Sunday in November, in each case at 02:00 local time.

=item NST3:30NDT,M3.2.0/0:01,M11.1.0/0:01

Newfoundland timezone with DST, from 2007 onwards.  3.5 hours behind UT
in winter and 2.5 hours behind in summer.  Changes on the second Sunday in
March and the first Sunday in November, in each case at 00:01 local time.

=item GMT0BST,M3.5.0/1,M10.5.0

UK civil time, from 1996 onwards.  On UT during the winter, calling
it "GMT", and 1 hour ahead of UT during the summer, called "BST".
Changes on the last Sunday in March and the last Sunday in October,
in each case at 01:00 UT.

=item EST-10EST,M10.5.0,M3.5.0/3

Australian Eastern timezone, from 2007 onwards.  10 hours ahead of UT in
the southern winter (the middle of the calendar year), and 11 hours ahead
in the southern summer.  Changes to DST on the last Sunday in October,
and back on the last Sunday in March, in each case at 02:00 standard time
(16:00 UT of the preceding day).

=item EET-2EEST,M3.5.4/24,M9.3.6/145

Palestinian civil time, from 2012 onwards.  2 hours ahead of UT in winter
and 3 hours ahead in summer.  Changes at the end (24:00 local time) of
the last Thursday in March and 01:00 local time on the Friday following
the third Saturday in September (that is, the Friday falling between
September 21 and September 27 inclusive).  The extended time-of-day "145",
meaning 01:00 of the day six days after the nominal day, is only valid
in the L<tzfile(5)> variant of the System V syntax.  The time-of-day
"24" is not so restricted, being permitted by POSIX.

=back

=cut

package DateTime::TimeZone::SystemV;

{ use 5.006; }
use warnings;
use strict;

use Carp qw(croak);
use Date::ISO8601 0.000
	qw(month_days ymd_to_cjdn present_ymd year_days cjdn_to_yd cjdn_to_ywd);
use Params::Classify 0.000 qw(is_undef is_string);

our $VERSION = "0.010";

my $rdn_epoch_cjdn = 1721425;

my $abbrev_rx = qr#[A-Za-z]{3,}|\<[-+0-9A-Za-z]{3,}\>#;
my $offset_rx = qr#[-+]?(?:2[0-4]|[01]?[0-9])(?::[0-5][0-9](?::[0-5][0-9])?)?#;
my $rule_date_rx = qr#J0*(?:3(?:[0-5][0-9]|6[0-5])|[12]?[0-9][0-9]|[1-9])
		     |0*(?:3(?:[0-5][0-9]|6[0-4])|[12]?[0-9][0-9]|[0-9])
		     |M0*(?:1[0-2]|[1-9])\.0*[1-5]\.0*[0-6]#x;
my $posix_rule_time_rx =
	qr#(?:2[0-4]|[01]?[0-9])(?::[0-5][0-9](?::[0-5][0-9])?)?#;
my $tzfile3_rule_time_rx =
	qr#[-+]?(?:16[0-7]|1[0-5][0-9]|0[0-9][0-9]|[0-9]{1,2})
	   (?::[0-5][0-9](?::[0-5][0-9])?)?#x;
my $posix_rule_dt_rx = qr#${rule_date_rx}(?:/${posix_rule_time_rx})?#o;
my $tzfile3_rule_dt_rx = qr#${rule_date_rx}(?:/${tzfile3_rule_time_rx})?#o;
my $posix_tz_rx = qr#${abbrev_rx}${offset_rx}
		    (?:${abbrev_rx}(?:${offset_rx})?
		       (?:,${posix_rule_dt_rx},${posix_rule_dt_rx})?)?#xo;
my $tzfile3_tz_rx = qr#${abbrev_rx}${offset_rx}
		    (?:${abbrev_rx}(?:${offset_rx})?
		       (?:,${tzfile3_rule_dt_rx},${tzfile3_rule_dt_rx})?)?#xo;

my %tz_rx = (
	posix => $posix_tz_rx,
	tzfile3 => $tzfile3_tz_rx,
);

sub _parse_abbrev($) {
	my($spec) = @_;



( run in 0.847 second using v1.01-cache-2.11-cpan-39bf76dae61 )