DateTime-TimeZone-Tzfile-0.010000755001750001750 012217165452 16131 5ustar00zeframzefram000000000000DateTime-TimeZone-Tzfile-0.010/.gitignore000444001750001750 20112217165443 20227 0ustar00zeframzefram000000000000/Build /Makefile /_build /blib /META.json /META.yml /MYMETA.json /MYMETA.yml /Makefile.PL /SIGNATURE /DateTime-TimeZone-Tzfile-* DateTime-TimeZone-Tzfile-0.010/MANIFEST000444001750001750 46112217165443 17400 0ustar00zeframzefram000000000000.gitignore Build.PL Changes MANIFEST META.json META.yml Makefile.PL README lib/DateTime/TimeZone/Tzfile.pm t/Davis.tz t/Hebron.tz t/Kaliningrad.tz t/London.tz t/Loyston.tz t/San_Luis.tz t/construct.t t/crlf.t t/ident.t t/local.t t/offset.t t/pod_cvg.t t/pod_syn.t SIGNATURE Added here by Module::Build DateTime-TimeZone-Tzfile-0.010/Makefile.PL000444001750001750 230212217165443 20235 0ustar00zeframzefram000000000000# Note: this file was auto-generated by Module::Build::Compat version 0.4007 require 5.006; unless (eval "use Module::Build::Compat 0.02; 1" ) { print "This module requires Module::Build to install itself.\n"; require ExtUtils::MakeMaker; my $yn = ExtUtils::MakeMaker::prompt (' Install Module::Build now from CPAN?', 'y'); unless ($yn =~ /^y/i) { die " *** Cannot install without Module::Build. Exiting ...\n"; } require Cwd; require File::Spec; require CPAN; # Save this 'cause CPAN will chdir all over the place. my $cwd = Cwd::cwd(); CPAN::Shell->install('Module::Build::Compat'); CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate or die "Couldn't install Module::Build, giving up.\n"; chdir $cwd or die "Cannot chdir() back to $cwd: $!"; } eval "use Module::Build::Compat 0.02; 1" or die $@; Module::Build::Compat->run_build_pl(args => \@ARGV); my $build_script = 'Build'; $build_script .= '.com' if $^O eq 'VMS'; exit(0) unless(-e $build_script); # cpantesters convention require Module::Build; Module::Build::Compat->write_makefile(build_class => 'Module::Build'); DateTime-TimeZone-Tzfile-0.010/META.json000444001750001750 330612217165443 17711 0ustar00zeframzefram000000000000{ "abstract" : "tzfile (zoneinfo) timezone files", "author" : [ "Andrew Main (Zefram) " ], "dynamic_config" : 0, "generated_by" : "Module::Build version 0.4007, CPAN::Meta::Converter version 2.131560", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "DateTime-TimeZone-Tzfile", "prereqs" : { "build" : { "requires" : { "Date::ISO8601" : "0", "IO::File" : "1.13", "Module::Build" : "0", "Test::More" : "0", "perl" : "5.006", "strict" : "0", "warnings" : "0" } }, "configure" : { "requires" : { "Module::Build" : "0", "perl" : "5.006", "strict" : "0", "warnings" : "0" } }, "runtime" : { "requires" : { "Carp" : "0", "Date::ISO8601" : "0", "DateTime::TimeZone::SystemV" : "0.009", "IO::File" : "1.13", "IO::Handle" : "1.08", "Params::Classify" : "0", "integer" : "0", "perl" : "5.006", "strict" : "0", "warnings" : "0" } } }, "provides" : { "DateTime::TimeZone::Tzfile" : { "file" : "lib/DateTime/TimeZone/Tzfile.pm", "version" : "0.010" } }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "git://git.fysh.org/zefram/DateTime-TimeZone-Tzfile.git" } }, "version" : "0.010" } DateTime-TimeZone-Tzfile-0.010/Build.PL000444001750001750 170112217165443 17561 0ustar00zeframzefram000000000000{ use 5.006; } use warnings; use strict; use Module::Build; Module::Build->new( module_name => "DateTime::TimeZone::Tzfile", license => "perl", configure_requires => { "Module::Build" => 0, "perl" => "5.006", "strict" => 0, "warnings" => 0, }, build_requires => { "Date::ISO8601" => 0, "IO::File" => "1.13", "Module::Build" => 0, "Test::More" => 0, "perl" => "5.006", "strict" => 0, "warnings" => 0, }, requires => { "Carp" => 0, "Date::ISO8601" => 0, "DateTime::TimeZone::SystemV" => "0.009", "IO::File" => "1.13", "IO::Handle" => "1.08", "Params::Classify" => 0, "integer" => 0, "perl" => "5.006", "strict" => 0, "warnings" => 0, }, dynamic_config => 0, meta_add => { distribution_type => "module" }, meta_merge => { resources => { repository => "git://git.fysh.org/zefram/". "DateTime-TimeZone-Tzfile.git", }, }, create_makefile_pl => "passthrough", sign => 1, )->create_build_script; 1; DateTime-TimeZone-Tzfile-0.010/META.yml000444001750001750 171112217165443 17537 0ustar00zeframzefram000000000000--- abstract: 'tzfile (zoneinfo) timezone files' author: - 'Andrew Main (Zefram) ' build_requires: Date::ISO8601: 0 IO::File: 1.13 Module::Build: 0 Test::More: 0 perl: 5.006 strict: 0 warnings: 0 configure_requires: Module::Build: 0 perl: 5.006 strict: 0 warnings: 0 dynamic_config: 0 generated_by: 'Module::Build version 0.4007, CPAN::Meta::Converter version 2.131560' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: DateTime-TimeZone-Tzfile provides: DateTime::TimeZone::Tzfile: file: lib/DateTime/TimeZone/Tzfile.pm version: 0.010 requires: Carp: 0 Date::ISO8601: 0 DateTime::TimeZone::SystemV: 0.009 IO::File: 1.13 IO::Handle: 1.08 Params::Classify: 0 integer: 0 perl: 5.006 strict: 0 warnings: 0 resources: license: http://dev.perl.org/licenses/ repository: git://git.fysh.org/zefram/DateTime-TimeZone-Tzfile.git version: 0.010 DateTime-TimeZone-Tzfile-0.010/README000444001750001750 142712217165443 17152 0ustar00zeframzefram000000000000NAME DateTime::TimeZone::Tzfile - tzfile (zoneinfo) timezone files DESCRIPTION An instance of this class represents a timezone that was encoded in a file in the tzfile(5) format. These can express arbitrary patterns of offsets from Universal Time, changing over time. Offsets and change times are limited to a resolution of one second. This class implements the DateTime::TimeZone interface, so that its instances can be used with DateTime objects. INSTALLATION perl Build.PL ./Build ./Build test ./Build install AUTHOR Andrew Main (Zefram) COPYRIGHT Copyright (C) 2007, 2009, 2010, 2011, 2012, 2013 Andrew Main (Zefram) LICENSE This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. DateTime-TimeZone-Tzfile-0.010/Changes000444001750001750 1043212217165443 17601 0ustar00zeframzefram000000000000version 0.010; 2013-09-21 * bugfix: require bugfixed version of DateTime::TimeZone::SystemV to handle ->offset_for_local_datetime with perpetual-DST ruleset that can arise with a version-3 tzfile version 0.009; 2013-09-20 * support version 3 of the tzfile format version 0.008; 2013-07-14 * bugfix: require bugfixed version of DateTime::TimeZone::SystemV to handle POSIX-TZ field showing transitions occurring at 24:00 * in META.{yml,json}, point to public git repository version 0.007; 2012-03-10 * bugfix: recognise zone disuse indicator if it comes in the form of the POSIX-TZ extension rule * distinguish between zone disuse and missing data * eliminate use of Date::JD, because it's too heavy to justify the minimal convenience gained from it * eliminate use of constant.pm, for stylistic consistency * test more error cases * test behaviour around leap seconds * factor out date/time presentation code used for error messages * for CRLF test, use a smaller tzfile that tickles the same potential bug * give test tzfiles appropriately capitalised names * convert .cvsignore to .gitignore version 0.006; 2011-09-27 * include the time and zone name in error messages about non-existent local time and unrepresented time * check argument types in constructor * make test suite work even if DateTime is not available version 0.005; 2011-04-05 * bugfix: read tzfiles in binary mode * include META.json in distribution * add MYMETA.json to .cvsignore version 0.004; 2010-08-31 * for the Olson "Factory" timezone, which has a pseudo-abbreviation containing spaces, don't process the TZ value that it contains, because it's invalid and DateTime::TimeZone::SystemV objects to it * tighten the criteria for recognising the special observance that indicates that local time is not defined (abbreviation "zzz" was previously the sole criterion, now also require zero offset and not DST) * allow the ->is_olson and ->category values to be specified to the constructor, instead of having fixed values * when a local time is non-existent due to an undefined observance, give an error message that says so, rather than conflating it with local time being non-existent due to an offset change * add DateTime::TimeZone::Olson, Time::OlsonTZ::Data, and Time::OlsonTZ::Download to the "see also" list * test the error message that is given when a local time does not exist due to an offset change version 0.003; 2010-07-30 * in documentation, correct one use of "filename" to "filehandle" * in documentation, use the term "truth value" instead of the less precise "boolean" * abandon use of the "fields" module * check for required Perl version at runtime * use full stricture in test suite * in Build.PL, explicitly declare configure-time requirements * remove bogus "exit 0" from Build.PL * add MYMETA.yml to .cvsignore version 0.002; 2009-03-22 * with a version-1 tzfile, treat the last observance as continuing indefinitely, rather than as having no rule for the future * test POD syntax and coverage, and rename some internal functions to satisfy the coverage test * drop prototypes from method subs (where the prototypes have no effect) * in tests, avoid unreliable "\d" regexp element * typo fix in documentation * really complete dependency list (was missing "integer", and build_requires was missing "IO::File") * include "distribution_type" entry in META.yml to satisfy CPANTS * in documentation, separate "license" section from "copyright" section * use full stricture in Build.PL * remove from .cvsignore items that don't occur with Module::Build version 0.001; 2007-09-12 * bugfix: override any ambient $SIG{__DIE__} handler when using eval { } * bugfix: require bugfixed version of DateTime::TimeZone::SystemV (for $SIG{__DIE__} handling) * new key/value constructor parameter style * constructor option to set timezone name independently from filename * constructor option to supply an open filehandle * use "fields" module to structure object * build with Module::Build instead of ExtUtils::MakeMaker * complete dependency list * include signature in distribution version 0.000; 2007-02-10 * initial released version DateTime-TimeZone-Tzfile-0.010/SIGNATURE000644001750001750 373012217165452 17557 0ustar00zeframzefram000000000000This file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.73. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 SHA1 39b83fb4caa81801a2a6f26e1f96241c958dafac .gitignore SHA1 460b8ab4cc43b228d4c6acb21d49d618283272ea Build.PL SHA1 d87cfa48504b069386b6cc2d2e300aec05ea6b0e Changes SHA1 736e052ea5be9d51b8ef33bc3386e934f1a8fbb7 MANIFEST SHA1 2be8960f2d8f5f9e62bb67cb88c5cbf555077030 META.json SHA1 bfcd35c9c73e1d387c5f8bff8a825e2f60cff469 META.yml SHA1 0bfa106a64fc680e40507c47cbf461cea3a8b374 Makefile.PL SHA1 f7bcb6666d4aec3bc580cacd1ee8d90bc7e0f8f5 README SHA1 3d6abc7ba38378b945dcc59012175d9eccc713b0 lib/DateTime/TimeZone/Tzfile.pm SHA1 aee65210dec1a21938a8f9e26eae8e74a06849c3 t/Davis.tz SHA1 b5265afc509c8577dfa867469e83bea9cf8c549a t/Hebron.tz SHA1 d297f080067251860bb860aadb42540757ccb5c1 t/Kaliningrad.tz SHA1 e203aaf15eecc56c069b59f482f8ae3655c249a9 t/London.tz SHA1 ddf6da1833c704e86c8704551224abe0d2a16923 t/Loyston.tz SHA1 e1933b958c714f339fecf887b43e866a51621674 t/San_Luis.tz SHA1 ff4fdb3434f36b3f43dbd50d62bcc706aee3145b t/construct.t SHA1 56ea63a619f1f383e5b0dd70bced7e4af55a7560 t/crlf.t SHA1 b6c8696b5675418ce8ebe5056211bbcfd504d25c t/ident.t SHA1 1ac7443846004c2197546ee14ed4a7fc5e37a54c t/local.t SHA1 60d41ae3a72e33e0f99b580130d62173d31071a9 t/offset.t SHA1 904d9a4f76525e2303e4b0c168c68230f223c8de t/pod_cvg.t SHA1 65c75abdef6f01a5d1588a307f2ddfe2333dc961 t/pod_syn.t -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iEYEARECAAYFAlI86yMACgkQOV9mt2VyAVG2FwCgk2CFBxl8vDJsgAYlzUZmR8ld jf4An32If0KsAVH3tNAW/P4YoP7CiREz =4Vux -----END PGP SIGNATURE----- DateTime-TimeZone-Tzfile-0.010/lib000755001750001750 012217165443 16677 5ustar00zeframzefram000000000000DateTime-TimeZone-Tzfile-0.010/lib/DateTime000755001750001750 012217165443 20373 5ustar00zeframzefram000000000000DateTime-TimeZone-Tzfile-0.010/lib/DateTime/TimeZone000755001750001750 012217165443 22125 5ustar00zeframzefram000000000000DateTime-TimeZone-Tzfile-0.010/lib/DateTime/TimeZone/Tzfile.pm000444001750001750 4010112217165443 24071 0ustar00zeframzefram000000000000=head1 NAME DateTime::TimeZone::Tzfile - tzfile (zoneinfo) timezone files =head1 SYNOPSIS use DateTime::TimeZone::Tzfile; $tz = DateTime::TimeZone::Tzfile->new( name => "local timezone", filename => "/etc/localtime"); $tz = DateTime::TimeZone::Tzfile->new("/etc/localtime"); if($tz->is_floating) { ... if($tz->is_utc) { ... if($tz->is_olson) { ... $category = $tz->category; $tz_string = $tz->name; if($tz->has_dst_changes) { ... if($tz->is_dst_for_datetime($dt)) { ... $offset = $tz->offset_for_datetime($dt); $abbrev = $tz->short_name_for_datetime($dt); $offset = $tz->offset_for_local_datetime($dt); =head1 DESCRIPTION An instance of this class represents a timezone that was encoded in a file in the L format. These can express arbitrary patterns of offsets from Universal Time, changing over time. Offsets and change times are limited to a resolution of one second. This class implements the L interface, so that its instances can be used with L objects. =cut package DateTime::TimeZone::Tzfile; { use 5.006; } use warnings; use strict; use Carp qw(croak); use Date::ISO8601 0.000 qw(present_ymd); use IO::File 1.13; use IO::Handle 1.08; use Params::Classify 0.000 qw(is_undef is_string is_ref); our $VERSION = "0.010"; my $rdn_epoch_cjdn = 1721425; # _fdiv(A, B), _fmod(A, B): divide A by B, flooring remainder # # B must be a positive Perl integer. A must be a Perl integer. sub _fdiv($$) { my($a, $b) = @_; if($a < 0) { use integer; return -(($b - 1 - $a) / $b); } else { use integer; return $a / $b; } } sub _fmod($$) { $_[0] % $_[1] } =head1 CONSTRUCTOR =over =item DateTime::TimeZone::Tzfile->new(ATTR => VALUE, ...) Reads and parses a L format file, then constructs and returns a L-compatible timezone object that implements the timezone encoded in the file. The following attributes may be given: =over =item B Name for the timezone object. This will be returned by the C method described below, and will be included in certain error messages. =item B The string or C that will be returned by the C method described below. Default C. =item B The truth value that will be returned by the C method described below. Default false. =item B Name of the file from which to read the timezone data. The filename must be understood by L. =item B An L object from which the timezone data can be read. This does not need to be a regular seekable file; it is read sequentially. After the constructor has finished, the handle can still be used to read any data that follows the timezone data. =back Either a filename or filehandle must be given. If a timezone name is not given, then the filename is used instead if supplied; a timezone name must be given explicitly if no filename is given. =item DateTime::TimeZone::Tzfile->new(FILENAME) Simpler way to invoke the above constructor in the usual case. Only the filename is given; this will also be used as the timezone name. =cut sub _saferead($$) { my($fh, $len) = @_; my $data; my $rlen = $fh->read($data, $len); croak "can't read tzfile: $!" unless defined($rlen); croak "bad tzfile: premature EOF" unless $rlen == $len; return $data; } sub _read_u32($) { unpack("N", _saferead($_[0], 4)) } sub _read_s32($) { my $uval = _read_u32($_[0]); return ($uval & 0x80000000) ? ($uval & 0x7fffffff) - 0x80000000 : $uval; } sub _read_u8($) { ord(_saferead($_[0], 1)) } my $unix_epoch_rdn = 719163; sub _read_tm32($) { my $t = _read_s32($_[0]); return [ $unix_epoch_rdn + _fdiv($t, 86400), _fmod($t, 86400) ]; } sub _read_tm64($) { my($fh) = @_; my $th = _read_s32($fh); my $tl = _read_u32($fh); my $dh = _fdiv($th, 86400); $th = (_fmod($th, 86400) << 10) | ($tl >> 22); my $d2 = _fdiv($th, 86400); $th = (_fmod($th, 86400) << 10) | (($tl >> 12) & 0x3ff); my $d3 = _fdiv($th, 86400); $th = (_fmod($th, 86400) << 12) | ($tl & 0xfff); my $d4 = _fdiv($th, 86400); $th = _fmod($th, 86400); my $d = $dh * 4294967296 + $d2 * 4194304 + (($d3 << 12) + $d4); return [ $unix_epoch_rdn + $d, $th ]; } my $factory_abbr = "Local time zone must be set--see zic manual page"; sub new { my $class = shift; unshift @_, "filename" if @_ == 1; my $self = bless({}, $class); my($filename, $fh); while(@_) { my $attr = shift; my $value = shift; if($attr eq "name") { croak "timezone name specified redundantly" if exists $self->{name}; croak "timezone name must be a string" unless is_string($value); $self->{name} = $value; } elsif($attr eq "category") { croak "category value specified redundantly" if exists $self->{category}; croak "category value must be a string or undef" unless is_undef($value) || is_string($value); $self->{category} = $value; } elsif($attr eq "is_olson") { croak "is_olson flag specified redundantly" if exists $self->{is_olson}; $self->{is_olson} = !!$value; } elsif($attr eq "filename") { croak "filename specified redundantly" if defined($filename) || defined($fh); croak "filename must be a string" unless is_string($value); $filename = $value; } elsif($attr eq "filehandle") { croak "filehandle specified redundantly" if defined($filename) || defined($fh); $fh = $value; } else { croak "unrecognised attribute `$attr'"; } } croak "file not specified" unless defined($filename) || defined($fh); unless(exists $self->{name}) { croak "timezone name not specified" unless defined $filename; $self->{name} = $filename; } unless(exists $self->{category}) { $self->{category} = undef; } unless(exists $self->{is_olson}) { $self->{is_olson} = !!0; } if(defined $filename) { ($fh = IO::File->new($filename, "r")) && $fh->binmode or croak "can't read $filename: $!"; } croak "bad tzfile: wrong magic number" unless _saferead($fh, 4) eq "TZif"; my $fmtversion = _saferead($fh, 1); croak "bad tzfile: malformed version number" unless $fmtversion =~ /\A[2-9\0]\z/; _saferead($fh, 15); my($ttisgmtcnt, $ttisstdcnt, $leapcnt, $timecnt, $typecnt, $charcnt) = map { _read_u32($fh) } 1 .. 6; croak "bad tzfile: no local time types" if $typecnt == 0; my @trn_times = map { _read_tm32($fh) } 1 .. $timecnt; my @obs_types = map { _read_u8($fh) } 1 .. $timecnt; my @types = map { [ _read_s32($fh), !!_read_u8($fh), _read_u8($fh) ] } 1 .. $typecnt; my $chars = _saferead($fh, $charcnt); for(my $i = $leapcnt; $i--; ) { _saferead($fh, 8); } for(my $i = $ttisstdcnt; $i--; ) { _saferead($fh, 1); } for(my $i = $ttisgmtcnt; $i--; ) { _saferead($fh, 1); } my $late_rule; if($fmtversion ge "2") { croak "bad tzfile: wrong magic number" unless _saferead($fh, 4) eq "TZif"; _saferead($fh, 16); ($ttisgmtcnt, $ttisstdcnt, $leapcnt, $timecnt, $typecnt, $charcnt) = map { _read_u32($fh) } 1 .. 6; croak "bad tzfile: no local time types" if $typecnt == 0; @trn_times = map { _read_tm64($fh) } 1 .. $timecnt; @obs_types = map { _read_u8($fh) } 1 .. $timecnt; @types = map { [ _read_s32($fh), !!_read_u8($fh), _read_u8($fh) ] } 1 .. $typecnt; $chars = _saferead($fh, $charcnt); for(my $i = $leapcnt; $i--; ) { _saferead($fh, 12); } for(my $i = $ttisstdcnt; $i--; ) { _saferead($fh, 1); } for(my $i = $ttisgmtcnt; $i--; ) { _saferead($fh, 1); } croak "bad tzfile: missing newline" unless _saferead($fh, 1) eq "\x0a"; $late_rule = ""; while(1) { my $c = _saferead($fh, 1); last if $c eq "\x0a"; $late_rule .= $c; } } $fh = undef; for(my $i = @trn_times - 1; $i-- > 0; ) { unless(($trn_times[$i]->[0] <=> $trn_times[$i+1]->[0] || $trn_times[$i]->[1] <=> $trn_times[$i+1]->[1]) == -1) { croak "bad tzfile: unsorted change times"; } } my $first_std_type_index; my %offsets; for(my $i = 0; $i != $typecnt; $i++) { my $abbrind = $types[$i]->[2]; croak "bad tzfile: invalid abbreviation index" if $abbrind > $charcnt; pos($chars) = $abbrind; $chars =~ /\G([^\0]*)/g; $types[$i]->[2] = $1; $first_std_type_index = $i if !defined($first_std_type_index) && !$types[$i]->[1]; $self->{has_dst} = 1 if $types[$i]->[1]; if($types[$i]->[0] == 0 && !$types[$i]->[1] && $types[$i]->[2] eq "zzz") { # "zzz" means the zone is not defined at this time, # due for example to the location being uninhabited $types[$i] = "zone disuse"; } else { $offsets{$types[$i]->[0]} = undef; } } unshift @obs_types, defined($first_std_type_index) ? $first_std_type_index : 0; foreach my $obs_type (@obs_types) { croak "bad tzfile: invalid local time type index" if $obs_type >= $typecnt; $obs_type = $types[$obs_type]; } if(defined($late_rule) && $late_rule eq "<$factory_abbr>0" && defined($obs_types[-1]) && $obs_types[-1]->[0] == 0 && !$obs_types[-1]->[1] && $obs_types[-1]->[2] eq $factory_abbr) { # This bizarre timezone abbreviation is used in the Factory # timezone in the Olson database. It's not valid in a # SysV-style TZ value, because it contains spaces, but zic # puts it into one anyway because the file format demands # it. DT:TZ:SystemV would object, so as a special # exception we ignore the TZ value in this case. $late_rule = undef; } if(defined $late_rule) { if($late_rule eq "") { $obs_types[-1] = "missing data"; } elsif($late_rule =~ /\A(?:zzz|)[-+]?00?(?::00(?::00)?)?\z/) { $obs_types[-1] = "zone disuse"; } else { require DateTime::TimeZone::SystemV; DateTime::TimeZone::SystemV->VERSION("0.009"); $obs_types[-1] = DateTime::TimeZone::SystemV->new( system => $fmtversion ge "3" ? "tzfile3" : "posix", recipe => $late_rule); } } $self->{trn_times} = \@trn_times; $self->{obs_types} = \@obs_types; $self->{offsets} = [ sort { $a <=> $b } keys %offsets ]; return $self; } sub _present_rdn_sod($$) { my($rdn, $sod) = @_; return sprintf("%sT%02d:%02d:%02d", present_ymd($rdn + $rdn_epoch_cjdn), int($sod/3600), int($sod/60)%60, $sod%60); } =back =head1 METHODS These methods are all part of the L interface. See that class for the general meaning of these methods; the documentation below only comments on the specific behaviour of this class. =head2 Identification =over =item $tz->is_floating Returns false. =cut sub is_floating { 0 } =item $tz->is_utc Returns false. =cut sub is_utc { 0 } =item $tz->is_olson Returns the truth value that was provided to the constructor for this purpose, default false. This nominally indicates whether the timezone data is from the Olson database. The files interpreted by this class are very likely to be from the Olson database, but there is no explicit indicator for this in the file, so this information must be supplied to the constructor if required. =cut sub is_olson { $_[0]->{is_olson} } =item $tz->category Returns the value that was provided to the constructor for this purpose, default C. This is intended to indicate the general region (continent or ocean) in which a geographical timezone is used, when the timezone is named according to the hierarchical scheme of the Olson timezone database. =cut sub category { $_[0]->{category} } =item $tz->name Returns the timezone name. Usually this is the filename that was supplied to the constructor, but it can be overridden by the constructor's B attribute. =cut sub name { $_[0]->{name} } =back =head2 Offsets =over =item $tz->has_dst_changes Returns a truth value indicating whether any of the observances in the file are marked as DST. These DST flags are potentially arbitrary, and don't affect any of the zone's behaviour. =cut sub has_dst_changes { $_[0]->{has_dst} } # # observance lookup # sub _type_for_rdn_sod { my($self, $utc_rdn, $utc_sod) = @_; my $lo = 0; my $hi = @{$self->{trn_times}}; while($lo != $hi) { my $try = do { use integer; ($lo + $hi) / 2 }; if(($utc_rdn <=> $self->{trn_times}->[$try]->[0] || $utc_sod <=> $self->{trn_times}->[$try]->[1]) == -1) { $hi = $try; } else { $lo = $try + 1; } } return $self->{obs_types}->[$lo]; } sub _type_for_datetime { my($self, $dt) = @_; my($utc_rdn, $utc_sod) = $dt->utc_rd_values; $utc_sod = 86399 if $utc_sod >= 86400; my $type = $self->_type_for_rdn_sod($utc_rdn, $utc_sod); if(is_string($type)) { croak "time @{[_present_rdn_sod($utc_rdn, $utc_sod)]}Z ". "is not represented ". "in the @{[$self->{name}]} timezone ". "due to $type"; } return $type; } =item $tz->offset_for_datetime(DT) I
must be a L-compatible object (specifically, it must implement the C method). Returns the offset from UT that is in effect at the instant represented by I
, in seconds. =cut sub offset_for_datetime { my($self, $dt) = @_; my $type = $self->_type_for_datetime($dt); return is_ref($type, "ARRAY") ? $type->[0] : $type->offset_for_datetime($dt); } =item $tz->is_dst_for_datetime(DT) I
must be a L-compatible object (specifically, it must implement the C method). Returns a truth value indicating whether the timezone's observance at the instant represented by I
is marked as DST. This DST flag is potentially arbitrary, and doesn't affect anything else. =cut sub is_dst_for_datetime { my($self, $dt) = @_; my $type = $self->_type_for_datetime($dt); return is_ref($type, "ARRAY") ? $type->[1] : $type->is_dst_for_datetime($dt); } =item $tz->short_name_for_datetime(DT) I
must be a L-compatible object (specifically, it must implement the C method). Returns the abbreviation used to label the time scale at the instant represented by I
. This abbreviation is potentially arbitrary, and does not uniquely identify either the timezone or the offset. =cut sub short_name_for_datetime { my($self, $dt) = @_; my $type = $self->_type_for_datetime($dt); return is_ref($type, "ARRAY") ? $type->[2] : $type->short_name_for_datetime($dt); } =item $tz->offset_for_local_datetime(DT) I
must be a L-compatible object (specifically, it must implement the C method). Takes the local time represented by I
(regardless of what absolute time it also represents), and interprets that as a local time in the timezone of the timezone object (not the timezone used in I
). Returns the offset from UT that is in effect at that local time, in seconds. If the local time given is ambiguous due to a nearby offset change, the numerically lowest offset (usually the standard one) is returned with no warning of the situation. (Equivalently: the latest possible absolute time is indicated.) If the local time given does not exist due to a nearby offset change, the method Cs saying so. =cut sub _local_to_utc_rdn_sod($$$) { my($rdn, $sod, $offset) = @_; $sod -= $offset; while($sod < 0) { $rdn--; $sod += 86400; } while($sod >= 86400) { $rdn++; $sod -= 86400; } return ($rdn, $sod); } sub offset_for_local_datetime { my($self, $dt) = @_; my($lcl_rdn, $lcl_sod) = $dt->local_rd_values; $lcl_sod = 86399 if $lcl_sod >= 86400; my %seen_error; foreach my $offset (@{$self->{offsets}}) { my($utc_rdn, $utc_sod) = _local_to_utc_rdn_sod($lcl_rdn, $lcl_sod, $offset); my $ttype = $self->_type_for_rdn_sod($utc_rdn, $utc_sod); if(is_string($ttype)) { $seen_error{$ttype} = undef; next; } my $local_offset = is_ref($ttype, "ARRAY") ? $ttype->[0] : eval { local $SIG{__DIE__}; $ttype->offset_for_local_datetime($dt); }; return $offset if defined($local_offset) && $local_offset == $offset; } my $error; foreach("zone disuse", "missing data") { if(exists $seen_error{$_}) { $error = $_; last; } } $error ||= "offset change"; croak "local time @{[_present_rdn_sod($lcl_rdn, $lcl_sod)]} ". "does not exist in the @{[$self->{name}]} timezone ". "due to $error"; } =back =head1 SEE ALSO L, L, L, L, L, L =head1 AUTHOR Andrew Main (Zefram) =head1 COPYRIGHT Copyright (C) 2007, 2009, 2010, 2011, 2012, 2013 Andrew Main (Zefram) =head1 LICENSE This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; DateTime-TimeZone-Tzfile-0.010/t000755001750001750 012217165443 16374 5ustar00zeframzefram000000000000DateTime-TimeZone-Tzfile-0.010/t/pod_syn.t000444001750001750 23612217165443 20352 0ustar00zeframzefram000000000000use warnings; use strict; use Test::More; plan skip_all => "Test::Pod not available" unless eval "use Test::Pod 1.00; 1"; Test::Pod::all_pod_files_ok(); 1; DateTime-TimeZone-Tzfile-0.010/t/construct.t000444001750001750 556412217165443 20754 0ustar00zeframzefram000000000000use warnings; use strict; use IO::File 1.13; use Test::More tests => 36; require_ok "DateTime::TimeZone::Tzfile"; my $tz; sub new_fh() { my $fh; ($fh = IO::File->new("t/London.tz")) && $fh->binmode or die $!; return $fh; } $tz = DateTime::TimeZone::Tzfile->new("t/London.tz"); ok $tz; is $tz->name, "t/London.tz"; $tz = DateTime::TimeZone::Tzfile->new(filename => "t/London.tz"); ok $tz; is $tz->name, "t/London.tz"; $tz = DateTime::TimeZone::Tzfile->new(filename => "t/London.tz", name => "foobar"); ok $tz; is $tz->name, "foobar"; $tz = DateTime::TimeZone::Tzfile->new(name => "foobar", filename => "t/London.tz"); ok $tz; is $tz->name, "foobar"; my $fh = new_fh(); $tz = DateTime::TimeZone::Tzfile->new(name => "foobar", filehandle => $fh); ok $tz; is $tz->name, "foobar"; ok $fh->eof; $fh = new_fh(); { local $/ = \1; defined $fh->getline or die "read error: $!"; } eval { DateTime::TimeZone::Tzfile->new(name => "foobar", filehandle => $fh); }; like $@, qr/\Abad tzfile: wrong magic number\b/; eval { DateTime::TimeZone::Tzfile->new(); }; like $@, qr/\Afile not specified\b/; eval { DateTime::TimeZone::Tzfile->new(name => "foobar"); }; like $@, qr/\Afile not specified\b/; eval { DateTime::TimeZone::Tzfile->new(quux => "foobar"); }; like $@, qr/\Aunrecognised attribute\b/; eval { DateTime::TimeZone::Tzfile->new(name => "foobar", name => "quux"); }; like $@, qr/\Atimezone name specified redundantly\b/; eval { DateTime::TimeZone::Tzfile->new(category => "foobar", category => "quux"); }; like $@, qr/\Acategory value specified redundantly\b/; eval { DateTime::TimeZone::Tzfile->new(is_olson => 1, is_olson => 1); }; like $@, qr/\Ais_olson flag specified redundantly\b/; eval { DateTime::TimeZone::Tzfile->new(filehandle => new_fh()); }; like $@, qr/\Atimezone name not specified\b/; eval { DateTime::TimeZone::Tzfile->new(filename => "t/London.tz", filename => "t/London.tz"); }; like $@, qr/\Afilename specified redundantly\b/; eval { DateTime::TimeZone::Tzfile->new(filehandle => new_fh(), filename => "t/London.tz"); }; like $@, qr/\Afilename specified redundantly\b/; eval { DateTime::TimeZone::Tzfile->new(filename => "t/London.tz", filehandle => new_fh()); }; like $@, qr/\Afilehandle specified redundantly\b/; eval { DateTime::TimeZone::Tzfile->new(filehandle => new_fh(), filehandle => new_fh()); }; like $@, qr/\Afilehandle specified redundantly\b/; foreach( undef, [], *STDOUT, bless({}), ) { eval { DateTime::TimeZone::Tzfile->new(name => $_) }; like $@, qr/\Atimezone name must be a string\b/; if(defined $_) { eval { DateTime::TimeZone::Tzfile->new(category => $_) }; like $@, qr/\Acategory value must be a string or undef\b/; } eval { DateTime::TimeZone::Tzfile->new(filename => $_) }; like $@, qr/\Afilename must be a string\b/; } eval { DateTime::TimeZone::Tzfile->new(filename => "t/notexist.tz"); }; like $@, qr#\Acan't read t/notexist\.tz: #; 1; DateTime-TimeZone-Tzfile-0.010/t/ident.t000444001750001750 147412217165443 20027 0ustar00zeframzefram000000000000use warnings; use strict; use Test::More tests => 22; require_ok "DateTime::TimeZone::Tzfile"; my $tz; $tz = DateTime::TimeZone::Tzfile->new("t/London.tz"); ok $tz; ok !$tz->is_floating; ok !$tz->is_utc; ok !$tz->is_olson; is $tz->category, undef; is $tz->name, "t/London.tz"; ok $tz->has_dst_changes; $tz = DateTime::TimeZone::Tzfile->new( name => "foo", category => "bar", is_olson => 1, filename => "t/London.tz", ); ok $tz; ok !$tz->is_floating; ok !$tz->is_utc; ok $tz->is_olson; is $tz->category, "bar"; is $tz->name, "foo"; ok $tz->has_dst_changes; $tz = DateTime::TimeZone::Tzfile->new( name => "foo", category => undef, is_olson => 1, filename => "t/London.tz", ); ok $tz; ok !$tz->is_floating; ok !$tz->is_utc; ok $tz->is_olson; is $tz->category, undef; is $tz->name, "foo"; ok $tz->has_dst_changes; 1; DateTime-TimeZone-Tzfile-0.010/t/Hebron.tz000444001750001750 441312217165443 20327 0ustar00zeframzefram000000000000TZif3YPͬϏfЩyф`Ҋpek6c`-P ``mﰳpy%ZYsp;Up6Ep9'BP| ` 3``P `!I"]M`# $Z0`%?P& &'(P)`*+e,-G._P/{)0H01dF`2A`3D(`4!`5$ `6`67a`8DP8}9`:_;B#?@A\B^CAD-`EPFFopGHPIJ<`KLaMN5PN\ NPOt`P[QT`RD`S4`T$`U`Vr`VWT`XY6`Za[`\C]4^}%_m`]aLbF$`c,d&`e f`f`g`hջ`iŬ`j`k`l`mnua`onpUC`qNnr>_s.PtAu2u#vO`wx1`yz`{|`}`~v`f`*0 *0*0   EETEESTIDTISTTZif3}JYPͬϏfЩyф`Ҋpek6c`-P ``mﰳpy%ZYsp;Up6Ep9'BP| ` 3``P `!I"]M`# $Z0`%?P& &'(P)`*+e,-G._P/{)0H01dF`2A`3D(`4!`5$ `6`67a`8DP8}9`:_;B#?@A\B^CAD-`EPFFopGHPIJ<`KLaMN5PN\ NPOt`P[QT`RD`S4`T$`U`Vr`VWT`XY6`Za[`\C]4^}%_m`]aLbF$`c,d&`e f`f`g`hջ`iŬ`j`k`l`mnua`onpUC`qNnr>_s.PtAu2u#vO`wx1`yz`{|`}`~v`f` *0 *0*0   LMTEETEESTIDTIST EET-2EEST,M3.5.4/24,M9.3.6/145 DateTime-TimeZone-Tzfile-0.010/t/pod_cvg.t000444001750001750 27312217165443 20321 0ustar00zeframzefram000000000000use warnings; use strict; use Test::More; plan skip_all => "Test::Pod::Coverage not available" unless eval "use Test::Pod::Coverage; 1"; Test::Pod::Coverage::all_pod_coverage_ok(); 1; DateTime-TimeZone-Tzfile-0.010/t/Kaliningrad.tz000444001750001750 272612217165443 21342 0ustar00zeframzefram000000000000TZif2M `ٮ qKͩ΢Cϒ4Ђ%pѕ`ҊP&'@PC@̓s|d lU!\F"L7#<($,% & ''p'p()P*@+,ۀ-̀./t0d1]2r3=4R562j6q88S9h:5;J3?@fA+BECd D%ـECFG#GIIκJKḺM~         *0 8@ *0 *0 8@ *0 *0 *0CESTCETMSDMSKEESTEETFETTZif2N"o[H `ٮ qKͩ΢Cϒ4Ђ%pѕ`ҊP&'@PC@̓s|d lU!\F"L7#<($,% & ''p'p()P*@+,ۀ-̀./t0d1]2r3=4R562j6q88S9h:5;J3?@fA+BECd D%ـECFG#GIIκJKḺM~  8    *0 8@ *0*08@ *0 *0 *0LMTCESTCETMSDMSKEESTEETFET FET-3 DateTime-TimeZone-Tzfile-0.010/t/San_Luis.tz000444001750001750 214512217165443 20627 0ustar00zeframzefram000000000000TZif2=0{R@ɰ@p0}@0x @Z@;0~`@*0A70ȁ@MM0ΰ)5Cd=0l02@柰C0w@65S0R@504@J$o#$%7%'4@'ð(G7ư8*@A0@Gw GGRHv@I4JX@ CMTARTARSTWARTWARSTTZif2>r0{R@ɰ@p0}@0x @Z@;0~`@*0A70ȁ@MM0ΰ)5Cd=0l02@柰C0w@65S0R@504@J$o#$%7%'4@'ð(G7ư8*@A0@Gw GGRHv@I4JX@  LMTCMTARTARSTWARTWARST DateTime-TimeZone-Tzfile-0.010/t/local.t000444001750001750 1163212217165443 20033 0ustar00zeframzefram000000000000use warnings; use strict; use Test::More tests => 113; { package FakeLocalDateTime; use Date::ISO8601 0.000 qw(ymd_to_cjdn); my $rdn_epoch_cjdn = 1721425; sub new { my($class, $y, $mo, $d, $h, $mi, $s) = @_; return bless({ rdn => ymd_to_cjdn($y, $mo, $d) - $rdn_epoch_cjdn, sod => 3600*$h + 60*$mi + $s, }, $class); } sub local_rd_values { ($_[0]->{rdn}, $_[0]->{sod}, 0) } } require_ok "DateTime::TimeZone::Tzfile"; my $tz; sub try($$) { my($timespec, $offset) = @_; $timespec =~ /\A([0-9]{4})-([0-9]{2})-([0-9]{2})T ([0-9]{2}):([0-9]{2}):([0-9]{2})\z/x or die; my $dt = FakeLocalDateTime->new("$1", "$2", "$3", "$4", "$5", "$6"); my $errcond; unless($offset =~ /\A[-+]?[0-9]+\z/) { $errcond = $offset; $offset = undef; } is eval { $tz->offset_for_local_datetime($dt) }, $offset, "offset for $timespec"; unless(defined $offset) { like $@, qr#\A local\ time\ \Q$timespec\E\ does\ not\ exist \ in\ the\ [!-~]+\ timezone\ due\ to\ \Q$errcond\E \b#x, "error message for $timespec"; } } $tz = DateTime::TimeZone::Tzfile->new("t/London.tz"); try "1800-01-01T00:00:00", -75; try "1920-03-28T01:59:59", +0; try "1920-03-28T02:00:00", "offset change"; try "1920-03-28T02:59:59", "offset change"; try "1920-03-28T03:00:00", +3600; try "1920-10-25T01:59:59", +3600; try "1920-10-25T02:00:00", +0; try "1920-10-25T02:59:59", +0; try "1920-10-25T03:00:00", +0; try "1942-04-05T01:59:59", +3600; try "1942-04-05T02:00:00", "offset change"; try "1942-04-05T02:59:59", "offset change"; try "1942-04-05T03:00:00", +7200; try "2039-03-27T00:59:59", +0; try "2039-03-27T01:00:00", "offset change"; try "2039-03-27T01:59:59", "offset change"; try "2039-03-27T02:00:00", +3600; try "2039-10-30T00:59:59", +3600; try "2039-10-30T01:00:00", +0; try "2039-10-30T01:59:59", +0; try "2039-10-30T02:00:00", +0; # The Davis base in Antarctica has been uninhabited at times. $tz = DateTime::TimeZone::Tzfile->new("t/Davis.tz"); try "1953-07-01T12:00:00", "zone disuse"; try "1957-01-13T06:59:59", "zone disuse"; try "1957-01-13T07:00:00", +25200; try "1960-01-01T12:00:00", +25200; try "1964-10-31T23:59:59", +25200; try "1964-11-01T00:00:00", "zone disuse"; try "1967-01-01T12:00:00", "zone disuse"; try "1969-02-01T06:59:59", "zone disuse"; try "1969-02-01T07:00:00", +25200; try "1980-01-01T12:00:00", +25200; try "2009-10-17T23:59:59", +25200; try "2009-10-18T00:00:00", +18000; try "2010-01-01T12:00:00", +18000; try "2010-03-11T00:59:59", +18000; try "2010-03-11T01:00:00", "offset change"; try "2010-03-11T02:59:59", "offset change"; try "2010-03-11T03:00:00", +25200; try "2011-01-01T12:00:00", +25200; # This version of San_Luis.tz has no POSIX-TZ extension rule, because # the source data ends with an indefinite-future observance that is on # DST, and that can't be expressed in a POSIX-TZ recipe. The correct # interpretation of the tzfile is that the zone behaviour is unknown # after the final transition time. $tz = DateTime::TimeZone::Tzfile->new("t/San_Luis.tz"); try "2008-01-01T12:00:00", -7200; try "2008-01-20T22:59:59", -7200; try "2008-01-20T23:00:00", -10800; try "2008-02-01T12:00:00", -10800; try "2008-03-08T22:59:59", -10800; try "2008-03-08T23:00:00", -14400; try "2008-06-01T12:00:00", -14400; try "2008-10-11T23:59:59", -14400; try "2008-10-12T00:00:00", "offset change"; try "2008-10-12T00:59:59", "offset change"; try "2008-10-12T01:00:00", -10800; try "2009-01-01T12:00:00", -10800; try "2009-03-07T22:59:59", -10800; try "2009-03-07T23:00:00", -14400; try "2009-06-01T12:00:00", -14400; try "2009-10-10T23:59:59", -14400; try "2009-10-11T00:00:00", "missing data"; try "2010-01-01T12:00:00", "missing data"; # Loyston was settled in the early 19th century and ultimately abandoned # in 1936 to make way for the Norris Lake. This tzfile is not from the # Olson database. It's here to test the handling of a presently-disused # zone. $tz = DateTime::TimeZone::Tzfile->new("t/Loyston.tz"); try "1799-01-01T12:00:00", "zone disuse"; try "1799-12-31T18:24:15", "zone disuse"; try "1799-12-31T18:24:16", -20144; try "1840-01-01T12:00:00", -20144; try "1883-11-18T11:24:15", -20144; try "1883-11-18T11:24:16", "offset change"; try "1883-11-18T11:59:59", "offset change"; try "1883-11-18T12:00:00", -18000; try "1900-01-01T12:00:00", -18000; try "1918-03-31T01:59:59", -18000; try "1918-03-31T02:00:00", "offset change"; try "1918-03-31T02:59:59", "offset change"; try "1918-03-31T03:00:00", -14400; try "1918-07-01T12:00:00", -14400; try "1918-10-27T00:59:59", -14400; try "1918-10-27T01:00:00", -18000; try "1919-01-01T12:00:00", -18000; try "1919-03-30T01:59:59", -18000; try "1919-03-30T02:00:00", "offset change"; try "1919-03-30T02:59:59", "offset change"; try "1919-03-30T03:00:00", -14400; try "1919-07-01T12:00:00", -14400; try "1919-10-26T00:59:59", -14400; try "1919-10-26T01:00:00", -18000; try "1930-01-01T12:00:00", -18000; try "1936-03-03T23:59:59", -18000; try "1936-03-04T00:00:00", "zone disuse"; try "1937-01-01T12:00:00", "zone disuse"; 1; DateTime-TimeZone-Tzfile-0.010/t/Davis.tz000444001750001750 42412217165443 20136 0ustar00zeframzefram000000000000TZif2 @GGJ0K@N0OCbpFPbpzzzDAVTTZif2 @GGJ0K@N0OCbpFPbpzzzDAVT DAVT-7 DateTime-TimeZone-Tzfile-0.010/t/crlf.t000444001750001750 67312217165443 17632 0ustar00zeframzefram000000000000use warnings; use strict; use Test::More tests => 2; require_ok "DateTime::TimeZone::Tzfile"; # This tests for proper binary mode handling of tzfiles. Specifically, # if a tzfile is read in text mode then it may get mangled by translation # of CRLF to LF. This Kaliningrad.tz file happens to contain a byte # sequence that would be interpreted as CRLF in text mode. my $tz = DateTime::TimeZone::Tzfile->new("t/Kaliningrad.tz"); ok 1; 1; DateTime-TimeZone-Tzfile-0.010/t/London.tz000444001750001750 711512217165443 20345 0ustar00zeframzefram000000000000TZif2 & 0à ve {ȠN? %` ' *, Ӡ l N y0 РpLrP.IZ 02vXԠ W  x z Xy Q8[ : X֠ &ʗYw;ͱ`Xϐn^r2i c)I !BN . p  ޴߮ ̠rHkt R*T2 = ) T q S  g} aI_ Jf _A ! ?#  Ѡ {ǻpp )X P  : 0  l N  0  qޠ.Qy1X#8Ɛ͐㯐Ñk lr!M"LT#a/$,6%JK& '*-'4) )*+,Ӑ-ڐ./t00$1]2r3=4R562x688a9v:C;X<_=:>A?@f#A9BFCdD%ECFɐG#GIIJKL̿MNOnnPQWRleS7lTLGUNV,)V0XFXY(Z[ \]^_`_a}b?c]̐de=fgg藐hriyjTk[lqm=nSohp5qQ<rfs1tEuv/vxxyِz{λ|}~y BSTGMTBDSTTZif2] & 0à ve {ȠN? %` ' *, Ӡ l N y0 РpLrP.IZ 02vXԠ W  x z Xy Q8[ : X֠ &ʗYw;ͱ`Xϐn^r2i c)I !BN . p  ޴߮ ̠rHkt R*T2 = ) T q S  g} aI_ Jf _A ! ?#  Ѡ {ǻpp )X P  : 0  l N  0  qޠ.Qy1X#8Ɛ͐㯐Ñk lr!M"LT#a/$,6%JK& '*-'4) )*+,Ӑ-ڐ./t00$1]2r3=4R562x688a9v:C;X<_=:>A?@f#A9BFCdD%ECFɐG#GIIJKL̿MNOnnPQWRleS7lTLGUNV,)V0XFXY(Z[ \]^_`_a}b?c]̐de=fgg藐hriyjTk[lqm=nSohp5qQ<rfs1tEuv/vxxyِz{λ|}~y  LMTBSTGMTBDST GMT0BST,M3.5.0/1,M10.5.0 DateTime-TimeZone-Tzfile-0.010/t/Loyston.tz000444001750001750 43212217165443 20536 0ustar00zeframzefram000000000000TZif2 p`p`^PzzzEDTESTTZif2=^p`p`^PP zzzLMTEDTEST zzz0 DateTime-TimeZone-Tzfile-0.010/t/offset.t000444001750001750 7125612217165443 20237 0ustar00zeframzefram000000000000use warnings; use strict; use Test::More tests => 1753; { package FakeUtcDateTime; use Date::ISO8601 0.000 qw(ymd_to_cjdn); my $rdn_epoch_cjdn = 1721425; sub new { my($class, $y, $mo, $d, $h, $mi, $s) = @_; return bless({ rdn => ymd_to_cjdn($y, $mo, $d) - $rdn_epoch_cjdn, sod => 3600*$h + 60*$mi + $s, }, $class); } sub utc_rd_values { ($_[0]->{rdn}, $_[0]->{sod}, 0) } } require_ok "DateTime::TimeZone::Tzfile"; my $tz; sub try($$;$$) { my($timespec, $is_dst, $offset, $abbrev) = @_; $timespec =~ /\A([0-9]{4})-([0-9]{2})-([0-9]{2})T ([0-9]{2}):([0-9]{2}):([0-9]{2})Z\z/x or die; my $dt = FakeUtcDateTime->new("$1", "$2", "$3", "$4", "$5", "$6"); my $errcond; unless($is_dst =~ /\A[01]\z/) { $errcond = $is_dst; $is_dst = undef; } if(defined $is_dst) { is !!$tz->is_dst_for_datetime($dt), !!$is_dst, "is DST for $timespec"; is $tz->offset_for_datetime($dt), $offset, "offset for $timespec"; is $tz->short_name_for_datetime($dt), $abbrev, "abbrev for $timespec"; } else { foreach my $method (qw( is_dst_for_datetime offset_for_datetime short_name_for_datetime )) { eval { $tz->$method($dt) }; like $@, qr#\A time\ \Q$timespec\E\ is\ not\ represented \ in\ the\ [!-~]+\ timezone \ due\ to\ \Q$errcond\E \b#x, "$method error message for $timespec"; } } } $tz = DateTime::TimeZone::Tzfile->new("t/London.tz"); try "1800-01-01T00:00:00Z", 0, -75, "LMT"; try "1847-12-01T00:01:14Z", 0, -75, "LMT"; try "1847-12-01T00:01:15Z", 0, +0, "GMT"; try "1916-05-21T01:59:59Z", 0, +0, "GMT"; try "1916-05-21T02:00:00Z", 1, +3600, "BST"; try "1916-10-01T01:59:59Z", 1, +3600, "BST"; try "1916-10-01T02:00:00Z", 0, +0, "GMT"; try "1917-04-08T01:59:59Z", 0, +0, "GMT"; try "1917-04-08T02:00:00Z", 1, +3600, "BST"; try "1917-09-17T01:59:59Z", 1, +3600, "BST"; try "1917-09-17T02:00:00Z", 0, +0, "GMT"; try "1918-03-24T01:59:59Z", 0, +0, "GMT"; try "1918-03-24T02:00:00Z", 1, +3600, "BST"; try "1918-09-30T01:59:59Z", 1, +3600, "BST"; try "1918-09-30T02:00:00Z", 0, +0, "GMT"; try "1919-03-30T01:59:59Z", 0, +0, "GMT"; try "1919-03-30T02:00:00Z", 1, +3600, "BST"; try "1919-09-29T01:59:59Z", 1, +3600, "BST"; try "1919-09-29T02:00:00Z", 0, +0, "GMT"; try "1920-03-28T01:59:59Z", 0, +0, "GMT"; try "1920-03-28T02:00:00Z", 1, +3600, "BST"; try "1920-10-25T01:59:59Z", 1, +3600, "BST"; try "1920-10-25T02:00:00Z", 0, +0, "GMT"; try "1921-04-03T01:59:59Z", 0, +0, "GMT"; try "1921-04-03T02:00:00Z", 1, +3600, "BST"; try "1921-10-03T01:59:59Z", 1, +3600, "BST"; try "1921-10-03T02:00:00Z", 0, +0, "GMT"; try "1922-03-26T01:59:59Z", 0, +0, "GMT"; try "1922-03-26T02:00:00Z", 1, +3600, "BST"; try "1922-10-08T01:59:59Z", 1, +3600, "BST"; try "1922-10-08T02:00:00Z", 0, +0, "GMT"; try "1923-04-22T01:59:59Z", 0, +0, "GMT"; try "1923-04-22T02:00:00Z", 1, +3600, "BST"; try "1923-09-16T01:59:59Z", 1, +3600, "BST"; try "1923-09-16T02:00:00Z", 0, +0, "GMT"; try "1924-04-13T01:59:59Z", 0, +0, "GMT"; try "1924-04-13T02:00:00Z", 1, +3600, "BST"; try "1924-09-21T01:59:59Z", 1, +3600, "BST"; try "1924-09-21T02:00:00Z", 0, +0, "GMT"; try "1925-04-19T01:59:59Z", 0, +0, "GMT"; try "1925-04-19T02:00:00Z", 1, +3600, "BST"; try "1925-10-04T01:59:59Z", 1, +3600, "BST"; try "1925-10-04T02:00:00Z", 0, +0, "GMT"; try "1926-04-18T01:59:59Z", 0, +0, "GMT"; try "1926-04-18T02:00:00Z", 1, +3600, "BST"; try "1926-10-03T01:59:59Z", 1, +3600, "BST"; try "1926-10-03T02:00:00Z", 0, +0, "GMT"; try "1927-04-10T01:59:59Z", 0, +0, "GMT"; try "1927-04-10T02:00:00Z", 1, +3600, "BST"; try "1927-10-02T01:59:59Z", 1, +3600, "BST"; try "1927-10-02T02:00:00Z", 0, +0, "GMT"; try "1928-04-22T01:59:59Z", 0, +0, "GMT"; try "1928-04-22T02:00:00Z", 1, +3600, "BST"; try "1928-10-07T01:59:59Z", 1, +3600, "BST"; try "1928-10-07T02:00:00Z", 0, +0, "GMT"; try "1929-04-21T01:59:59Z", 0, +0, "GMT"; try "1929-04-21T02:00:00Z", 1, +3600, "BST"; try "1929-10-06T01:59:59Z", 1, +3600, "BST"; try "1929-10-06T02:00:00Z", 0, +0, "GMT"; try "1930-04-13T01:59:59Z", 0, +0, "GMT"; try "1930-04-13T02:00:00Z", 1, +3600, "BST"; try "1930-10-05T01:59:59Z", 1, +3600, "BST"; try "1930-10-05T02:00:00Z", 0, +0, "GMT"; try "1931-04-19T01:59:59Z", 0, +0, "GMT"; try "1931-04-19T02:00:00Z", 1, +3600, "BST"; try "1931-10-04T01:59:59Z", 1, +3600, "BST"; try "1931-10-04T02:00:00Z", 0, +0, "GMT"; try "1932-04-17T01:59:59Z", 0, +0, "GMT"; try "1932-04-17T02:00:00Z", 1, +3600, "BST"; try "1932-10-02T01:59:59Z", 1, +3600, "BST"; try "1932-10-02T02:00:00Z", 0, +0, "GMT"; try "1933-04-09T01:59:59Z", 0, +0, "GMT"; try "1933-04-09T02:00:00Z", 1, +3600, "BST"; try "1933-10-08T01:59:59Z", 1, +3600, "BST"; try "1933-10-08T02:00:00Z", 0, +0, "GMT"; try "1934-04-22T01:59:59Z", 0, +0, "GMT"; try "1934-04-22T02:00:00Z", 1, +3600, "BST"; try "1934-10-07T01:59:59Z", 1, +3600, "BST"; try "1934-10-07T02:00:00Z", 0, +0, "GMT"; try "1935-04-14T01:59:59Z", 0, +0, "GMT"; try "1935-04-14T02:00:00Z", 1, +3600, "BST"; try "1935-10-06T01:59:59Z", 1, +3600, "BST"; try "1935-10-06T02:00:00Z", 0, +0, "GMT"; try "1936-04-19T01:59:59Z", 0, +0, "GMT"; try "1936-04-19T02:00:00Z", 1, +3600, "BST"; try "1936-10-04T01:59:59Z", 1, +3600, "BST"; try "1936-10-04T02:00:00Z", 0, +0, "GMT"; try "1937-04-18T01:59:59Z", 0, +0, "GMT"; try "1937-04-18T02:00:00Z", 1, +3600, "BST"; try "1937-10-03T01:59:59Z", 1, +3600, "BST"; try "1937-10-03T02:00:00Z", 0, +0, "GMT"; try "1938-04-10T01:59:59Z", 0, +0, "GMT"; try "1938-04-10T02:00:00Z", 1, +3600, "BST"; try "1938-10-02T01:59:59Z", 1, +3600, "BST"; try "1938-10-02T02:00:00Z", 0, +0, "GMT"; try "1939-04-16T01:59:59Z", 0, +0, "GMT"; try "1939-04-16T02:00:00Z", 1, +3600, "BST"; try "1939-11-19T01:59:59Z", 1, +3600, "BST"; try "1939-11-19T02:00:00Z", 0, +0, "GMT"; try "1940-02-25T01:59:59Z", 0, +0, "GMT"; try "1940-02-25T02:00:00Z", 1, +3600, "BST"; try "1941-05-04T00:59:59Z", 1, +3600, "BST"; try "1941-05-04T01:00:00Z", 1, +7200, "BDST"; try "1941-08-10T00:59:59Z", 1, +7200, "BDST"; try "1941-08-10T01:00:00Z", 1, +3600, "BST"; try "1942-04-05T00:59:59Z", 1, +3600, "BST"; try "1942-04-05T01:00:00Z", 1, +7200, "BDST"; try "1942-08-09T00:59:59Z", 1, +7200, "BDST"; try "1942-08-09T01:00:00Z", 1, +3600, "BST"; try "1943-04-04T00:59:59Z", 1, +3600, "BST"; try "1943-04-04T01:00:00Z", 1, +7200, "BDST"; try "1943-08-15T00:59:59Z", 1, +7200, "BDST"; try "1943-08-15T01:00:00Z", 1, +3600, "BST"; try "1944-04-02T00:59:59Z", 1, +3600, "BST"; try "1944-04-02T01:00:00Z", 1, +7200, "BDST"; try "1944-09-17T00:59:59Z", 1, +7200, "BDST"; try "1944-09-17T01:00:00Z", 1, +3600, "BST"; try "1945-04-02T00:59:59Z", 1, +3600, "BST"; try "1945-04-02T01:00:00Z", 1, +7200, "BDST"; try "1945-07-15T00:59:59Z", 1, +7200, "BDST"; try "1945-07-15T01:00:00Z", 1, +3600, "BST"; try "1945-10-07T01:59:59Z", 1, +3600, "BST"; try "1945-10-07T02:00:00Z", 0, +0, "GMT"; try "1946-04-14T01:59:59Z", 0, +0, "GMT"; try "1946-04-14T02:00:00Z", 1, +3600, "BST"; try "1946-10-06T01:59:59Z", 1, +3600, "BST"; try "1946-10-06T02:00:00Z", 0, +0, "GMT"; try "1947-03-16T01:59:59Z", 0, +0, "GMT"; try "1947-03-16T02:00:00Z", 1, +3600, "BST"; try "1947-04-13T00:59:59Z", 1, +3600, "BST"; try "1947-04-13T01:00:00Z", 1, +7200, "BDST"; try "1947-08-10T00:59:59Z", 1, +7200, "BDST"; try "1947-08-10T01:00:00Z", 1, +3600, "BST"; try "1947-11-02T01:59:59Z", 1, +3600, "BST"; try "1947-11-02T02:00:00Z", 0, +0, "GMT"; try "1948-03-14T01:59:59Z", 0, +0, "GMT"; try "1948-03-14T02:00:00Z", 1, +3600, "BST"; try "1948-10-31T01:59:59Z", 1, +3600, "BST"; try "1948-10-31T02:00:00Z", 0, +0, "GMT"; try "1949-04-03T01:59:59Z", 0, +0, "GMT"; try "1949-04-03T02:00:00Z", 1, +3600, "BST"; try "1949-10-30T01:59:59Z", 1, +3600, "BST"; try "1949-10-30T02:00:00Z", 0, +0, "GMT"; try "1950-04-16T01:59:59Z", 0, +0, "GMT"; try "1950-04-16T02:00:00Z", 1, +3600, "BST"; try "1950-10-22T01:59:59Z", 1, +3600, "BST"; try "1950-10-22T02:00:00Z", 0, +0, "GMT"; try "1951-04-15T01:59:59Z", 0, +0, "GMT"; try "1951-04-15T02:00:00Z", 1, +3600, "BST"; try "1951-10-21T01:59:59Z", 1, +3600, "BST"; try "1951-10-21T02:00:00Z", 0, +0, "GMT"; try "1952-04-20T01:59:59Z", 0, +0, "GMT"; try "1952-04-20T02:00:00Z", 1, +3600, "BST"; try "1952-10-26T01:59:59Z", 1, +3600, "BST"; try "1952-10-26T02:00:00Z", 0, +0, "GMT"; try "1953-04-19T01:59:59Z", 0, +0, "GMT"; try "1953-04-19T02:00:00Z", 1, +3600, "BST"; try "1953-10-04T01:59:59Z", 1, +3600, "BST"; try "1953-10-04T02:00:00Z", 0, +0, "GMT"; try "1954-04-11T01:59:59Z", 0, +0, "GMT"; try "1954-04-11T02:00:00Z", 1, +3600, "BST"; try "1954-10-03T01:59:59Z", 1, +3600, "BST"; try "1954-10-03T02:00:00Z", 0, +0, "GMT"; try "1955-04-17T01:59:59Z", 0, +0, "GMT"; try "1955-04-17T02:00:00Z", 1, +3600, "BST"; try "1955-10-02T01:59:59Z", 1, +3600, "BST"; try "1955-10-02T02:00:00Z", 0, +0, "GMT"; try "1956-04-22T01:59:59Z", 0, +0, "GMT"; try "1956-04-22T02:00:00Z", 1, +3600, "BST"; try "1956-10-07T01:59:59Z", 1, +3600, "BST"; try "1956-10-07T02:00:00Z", 0, +0, "GMT"; try "1957-04-14T01:59:59Z", 0, +0, "GMT"; try "1957-04-14T02:00:00Z", 1, +3600, "BST"; try "1957-10-06T01:59:59Z", 1, +3600, "BST"; try "1957-10-06T02:00:00Z", 0, +0, "GMT"; try "1958-04-20T01:59:59Z", 0, +0, "GMT"; try "1958-04-20T02:00:00Z", 1, +3600, "BST"; try "1958-10-05T01:59:59Z", 1, +3600, "BST"; try "1958-10-05T02:00:00Z", 0, +0, "GMT"; try "1959-04-19T01:59:59Z", 0, +0, "GMT"; try "1959-04-19T02:00:00Z", 1, +3600, "BST"; try "1959-10-04T01:59:59Z", 1, +3600, "BST"; try "1959-10-04T02:00:00Z", 0, +0, "GMT"; try "1960-04-10T01:59:59Z", 0, +0, "GMT"; try "1960-04-10T02:00:00Z", 1, +3600, "BST"; try "1960-10-02T01:59:59Z", 1, +3600, "BST"; try "1960-10-02T02:00:00Z", 0, +0, "GMT"; try "1961-03-26T01:59:59Z", 0, +0, "GMT"; try "1961-03-26T02:00:00Z", 1, +3600, "BST"; try "1961-10-29T01:59:59Z", 1, +3600, "BST"; try "1961-10-29T02:00:00Z", 0, +0, "GMT"; try "1962-03-25T01:59:59Z", 0, +0, "GMT"; try "1962-03-25T02:00:00Z", 1, +3600, "BST"; try "1962-10-28T01:59:59Z", 1, +3600, "BST"; try "1962-10-28T02:00:00Z", 0, +0, "GMT"; try "1963-03-31T01:59:59Z", 0, +0, "GMT"; try "1963-03-31T02:00:00Z", 1, +3600, "BST"; try "1963-10-27T01:59:59Z", 1, +3600, "BST"; try "1963-10-27T02:00:00Z", 0, +0, "GMT"; try "1964-03-22T01:59:59Z", 0, +0, "GMT"; try "1964-03-22T02:00:00Z", 1, +3600, "BST"; try "1964-10-25T01:59:59Z", 1, +3600, "BST"; try "1964-10-25T02:00:00Z", 0, +0, "GMT"; try "1965-03-21T01:59:59Z", 0, +0, "GMT"; try "1965-03-21T02:00:00Z", 1, +3600, "BST"; try "1965-10-24T01:59:59Z", 1, +3600, "BST"; try "1965-10-24T02:00:00Z", 0, +0, "GMT"; try "1966-03-20T01:59:59Z", 0, +0, "GMT"; try "1966-03-20T02:00:00Z", 1, +3600, "BST"; try "1966-10-23T01:59:59Z", 1, +3600, "BST"; try "1966-10-23T02:00:00Z", 0, +0, "GMT"; try "1967-03-19T01:59:59Z", 0, +0, "GMT"; try "1967-03-19T02:00:00Z", 1, +3600, "BST"; try "1967-10-29T01:59:59Z", 1, +3600, "BST"; try "1967-10-29T02:00:00Z", 0, +0, "GMT"; try "1968-02-18T01:59:59Z", 0, +0, "GMT"; try "1968-02-18T02:00:00Z", 1, +3600, "BST"; try "1968-10-26T22:59:59Z", 1, +3600, "BST"; try "1968-10-26T23:00:00Z", 0, +3600, "BST"; try "1971-10-31T01:59:59Z", 0, +3600, "BST"; try "1971-10-31T02:00:00Z", 0, +0, "GMT"; try "1972-03-19T01:59:59Z", 0, +0, "GMT"; try "1972-03-19T02:00:00Z", 1, +3600, "BST"; try "1972-10-29T01:59:59Z", 1, +3600, "BST"; try "1972-10-29T02:00:00Z", 0, +0, "GMT"; try "1973-03-18T01:59:59Z", 0, +0, "GMT"; try "1973-03-18T02:00:00Z", 1, +3600, "BST"; try "1973-10-28T01:59:59Z", 1, +3600, "BST"; try "1973-10-28T02:00:00Z", 0, +0, "GMT"; try "1974-03-17T01:59:59Z", 0, +0, "GMT"; try "1974-03-17T02:00:00Z", 1, +3600, "BST"; try "1974-10-27T01:59:59Z", 1, +3600, "BST"; try "1974-10-27T02:00:00Z", 0, +0, "GMT"; try "1975-03-16T01:59:59Z", 0, +0, "GMT"; try "1975-03-16T02:00:00Z", 1, +3600, "BST"; try "1975-10-26T01:59:59Z", 1, +3600, "BST"; try "1975-10-26T02:00:00Z", 0, +0, "GMT"; try "1976-03-21T01:59:59Z", 0, +0, "GMT"; try "1976-03-21T02:00:00Z", 1, +3600, "BST"; try "1976-10-24T01:59:59Z", 1, +3600, "BST"; try "1976-10-24T02:00:00Z", 0, +0, "GMT"; try "1977-03-20T01:59:59Z", 0, +0, "GMT"; try "1977-03-20T02:00:00Z", 1, +3600, "BST"; try "1977-10-23T01:59:59Z", 1, +3600, "BST"; try "1977-10-23T02:00:00Z", 0, +0, "GMT"; try "1978-03-19T01:59:59Z", 0, +0, "GMT"; try "1978-03-19T02:00:00Z", 1, +3600, "BST"; try "1978-10-29T01:59:59Z", 1, +3600, "BST"; try "1978-10-29T02:00:00Z", 0, +0, "GMT"; try "1979-03-18T01:59:59Z", 0, +0, "GMT"; try "1979-03-18T02:00:00Z", 1, +3600, "BST"; try "1979-10-28T01:59:59Z", 1, +3600, "BST"; try "1979-10-28T02:00:00Z", 0, +0, "GMT"; try "1980-03-16T01:59:59Z", 0, +0, "GMT"; try "1980-03-16T02:00:00Z", 1, +3600, "BST"; try "1980-10-26T01:59:59Z", 1, +3600, "BST"; try "1980-10-26T02:00:00Z", 0, +0, "GMT"; try "1981-03-29T00:59:59Z", 0, +0, "GMT"; try "1981-03-29T01:00:00Z", 1, +3600, "BST"; try "1981-10-25T00:59:59Z", 1, +3600, "BST"; try "1981-10-25T01:00:00Z", 0, +0, "GMT"; try "1982-03-28T00:59:59Z", 0, +0, "GMT"; try "1982-03-28T01:00:00Z", 1, +3600, "BST"; try "1982-10-24T00:59:59Z", 1, +3600, "BST"; try "1982-10-24T01:00:00Z", 0, +0, "GMT"; try "1983-03-27T00:59:59Z", 0, +0, "GMT"; try "1983-03-27T01:00:00Z", 1, +3600, "BST"; try "1983-10-23T00:59:59Z", 1, +3600, "BST"; try "1983-10-23T01:00:00Z", 0, +0, "GMT"; try "1984-03-25T00:59:59Z", 0, +0, "GMT"; try "1984-03-25T01:00:00Z", 1, +3600, "BST"; try "1984-10-28T00:59:59Z", 1, +3600, "BST"; try "1984-10-28T01:00:00Z", 0, +0, "GMT"; try "1985-03-31T00:59:59Z", 0, +0, "GMT"; try "1985-03-31T01:00:00Z", 1, +3600, "BST"; try "1985-10-27T00:59:59Z", 1, +3600, "BST"; try "1985-10-27T01:00:00Z", 0, +0, "GMT"; try "1986-03-30T00:59:59Z", 0, +0, "GMT"; try "1986-03-30T01:00:00Z", 1, +3600, "BST"; try "1986-10-26T00:59:59Z", 1, +3600, "BST"; try "1986-10-26T01:00:00Z", 0, +0, "GMT"; try "1987-03-29T00:59:59Z", 0, +0, "GMT"; try "1987-03-29T01:00:00Z", 1, +3600, "BST"; try "1987-10-25T00:59:59Z", 1, +3600, "BST"; try "1987-10-25T01:00:00Z", 0, +0, "GMT"; try "1988-03-27T00:59:59Z", 0, +0, "GMT"; try "1988-03-27T01:00:00Z", 1, +3600, "BST"; try "1988-10-23T00:59:59Z", 1, +3600, "BST"; try "1988-10-23T01:00:00Z", 0, +0, "GMT"; try "1989-03-26T00:59:59Z", 0, +0, "GMT"; try "1989-03-26T01:00:00Z", 1, +3600, "BST"; try "1989-10-29T00:59:59Z", 1, +3600, "BST"; try "1989-10-29T01:00:00Z", 0, +0, "GMT"; try "1990-03-25T00:59:59Z", 0, +0, "GMT"; try "1990-03-25T01:00:00Z", 1, +3600, "BST"; try "1990-10-28T00:59:59Z", 1, +3600, "BST"; try "1990-10-28T01:00:00Z", 0, +0, "GMT"; try "1991-03-31T00:59:59Z", 0, +0, "GMT"; try "1991-03-31T01:00:00Z", 1, +3600, "BST"; try "1991-10-27T00:59:59Z", 1, +3600, "BST"; try "1991-10-27T01:00:00Z", 0, +0, "GMT"; try "1992-03-29T00:59:59Z", 0, +0, "GMT"; try "1992-03-29T01:00:00Z", 1, +3600, "BST"; try "1992-10-25T00:59:59Z", 1, +3600, "BST"; try "1992-10-25T01:00:00Z", 0, +0, "GMT"; try "1993-03-28T00:59:59Z", 0, +0, "GMT"; try "1993-03-28T01:00:00Z", 1, +3600, "BST"; try "1993-10-24T00:59:59Z", 1, +3600, "BST"; try "1993-10-24T01:00:00Z", 0, +0, "GMT"; try "1994-03-27T00:59:59Z", 0, +0, "GMT"; try "1994-03-27T01:00:00Z", 1, +3600, "BST"; try "1994-10-23T00:59:59Z", 1, +3600, "BST"; try "1994-10-23T01:00:00Z", 0, +0, "GMT"; try "1995-03-26T00:59:59Z", 0, +0, "GMT"; try "1995-03-26T01:00:00Z", 1, +3600, "BST"; try "1995-10-22T00:59:59Z", 1, +3600, "BST"; try "1995-10-22T01:00:00Z", 0, +0, "GMT"; try "1995-12-31T23:59:59Z", 0, +0, "GMT"; try "1996-01-01T00:00:00Z", 0, +0, "GMT"; try "1996-03-31T00:59:59Z", 0, +0, "GMT"; try "1996-03-31T01:00:00Z", 1, +3600, "BST"; try "1996-10-27T00:59:59Z", 1, +3600, "BST"; try "1996-10-27T01:00:00Z", 0, +0, "GMT"; try "1997-03-30T00:59:59Z", 0, +0, "GMT"; try "1997-03-30T01:00:00Z", 1, +3600, "BST"; try "1997-10-26T00:59:59Z", 1, +3600, "BST"; try "1997-10-26T01:00:00Z", 0, +0, "GMT"; try "1998-03-29T00:59:59Z", 0, +0, "GMT"; try "1998-03-29T01:00:00Z", 1, +3600, "BST"; try "1998-10-25T00:59:59Z", 1, +3600, "BST"; try "1998-10-25T01:00:00Z", 0, +0, "GMT"; try "1999-03-28T00:59:59Z", 0, +0, "GMT"; try "1999-03-28T01:00:00Z", 1, +3600, "BST"; try "1999-10-31T00:59:59Z", 1, +3600, "BST"; try "1999-10-31T01:00:00Z", 0, +0, "GMT"; try "2000-03-26T00:59:59Z", 0, +0, "GMT"; try "2000-03-26T01:00:00Z", 1, +3600, "BST"; try "2000-10-29T00:59:59Z", 1, +3600, "BST"; try "2000-10-29T01:00:00Z", 0, +0, "GMT"; try "2001-03-25T00:59:59Z", 0, +0, "GMT"; try "2001-03-25T01:00:00Z", 1, +3600, "BST"; try "2001-10-28T00:59:59Z", 1, +3600, "BST"; try "2001-10-28T01:00:00Z", 0, +0, "GMT"; try "2002-03-31T00:59:59Z", 0, +0, "GMT"; try "2002-03-31T01:00:00Z", 1, +3600, "BST"; try "2002-10-27T00:59:59Z", 1, +3600, "BST"; try "2002-10-27T01:00:00Z", 0, +0, "GMT"; try "2003-03-30T00:59:59Z", 0, +0, "GMT"; try "2003-03-30T01:00:00Z", 1, +3600, "BST"; try "2003-10-26T00:59:59Z", 1, +3600, "BST"; try "2003-10-26T01:00:00Z", 0, +0, "GMT"; try "2004-03-28T00:59:59Z", 0, +0, "GMT"; try "2004-03-28T01:00:00Z", 1, +3600, "BST"; try "2004-10-31T00:59:59Z", 1, +3600, "BST"; try "2004-10-31T01:00:00Z", 0, +0, "GMT"; try "2005-03-27T00:59:59Z", 0, +0, "GMT"; try "2005-03-27T01:00:00Z", 1, +3600, "BST"; try "2005-10-30T00:59:59Z", 1, +3600, "BST"; try "2005-10-30T01:00:00Z", 0, +0, "GMT"; try "2006-03-26T00:59:59Z", 0, +0, "GMT"; try "2006-03-26T01:00:00Z", 1, +3600, "BST"; try "2006-10-29T00:59:59Z", 1, +3600, "BST"; try "2006-10-29T01:00:00Z", 0, +0, "GMT"; try "2007-03-25T00:59:59Z", 0, +0, "GMT"; try "2007-03-25T01:00:00Z", 1, +3600, "BST"; try "2007-10-28T00:59:59Z", 1, +3600, "BST"; try "2007-10-28T01:00:00Z", 0, +0, "GMT"; try "2008-03-30T00:59:59Z", 0, +0, "GMT"; try "2008-03-30T01:00:00Z", 1, +3600, "BST"; try "2008-10-26T00:59:59Z", 1, +3600, "BST"; try "2008-10-26T01:00:00Z", 0, +0, "GMT"; try "2009-03-29T00:59:59Z", 0, +0, "GMT"; try "2009-03-29T01:00:00Z", 1, +3600, "BST"; try "2009-10-25T00:59:59Z", 1, +3600, "BST"; try "2009-10-25T01:00:00Z", 0, +0, "GMT"; try "2010-03-28T00:59:59Z", 0, +0, "GMT"; try "2010-03-28T01:00:00Z", 1, +3600, "BST"; try "2010-10-31T00:59:59Z", 1, +3600, "BST"; try "2010-10-31T01:00:00Z", 0, +0, "GMT"; try "2011-03-27T00:59:59Z", 0, +0, "GMT"; try "2011-03-27T01:00:00Z", 1, +3600, "BST"; try "2011-10-30T00:59:59Z", 1, +3600, "BST"; try "2011-10-30T01:00:00Z", 0, +0, "GMT"; try "2012-03-25T00:59:59Z", 0, +0, "GMT"; try "2012-03-25T01:00:00Z", 1, +3600, "BST"; try "2012-10-28T00:59:59Z", 1, +3600, "BST"; try "2012-10-28T01:00:00Z", 0, +0, "GMT"; try "2013-03-31T00:59:59Z", 0, +0, "GMT"; try "2013-03-31T01:00:00Z", 1, +3600, "BST"; try "2013-10-27T00:59:59Z", 1, +3600, "BST"; try "2013-10-27T01:00:00Z", 0, +0, "GMT"; try "2014-03-30T00:59:59Z", 0, +0, "GMT"; try "2014-03-30T01:00:00Z", 1, +3600, "BST"; try "2014-10-26T00:59:59Z", 1, +3600, "BST"; try "2014-10-26T01:00:00Z", 0, +0, "GMT"; try "2015-03-29T00:59:59Z", 0, +0, "GMT"; try "2015-03-29T01:00:00Z", 1, +3600, "BST"; try "2015-10-25T00:59:59Z", 1, +3600, "BST"; try "2015-10-25T01:00:00Z", 0, +0, "GMT"; try "2016-03-27T00:59:59Z", 0, +0, "GMT"; try "2016-03-27T01:00:00Z", 1, +3600, "BST"; try "2016-10-30T00:59:59Z", 1, +3600, "BST"; try "2016-10-30T01:00:00Z", 0, +0, "GMT"; try "2017-03-26T00:59:59Z", 0, +0, "GMT"; try "2017-03-26T01:00:00Z", 1, +3600, "BST"; try "2017-10-29T00:59:59Z", 1, +3600, "BST"; try "2017-10-29T01:00:00Z", 0, +0, "GMT"; try "2018-03-25T00:59:59Z", 0, +0, "GMT"; try "2018-03-25T01:00:00Z", 1, +3600, "BST"; try "2018-10-28T00:59:59Z", 1, +3600, "BST"; try "2018-10-28T01:00:00Z", 0, +0, "GMT"; try "2019-03-31T00:59:59Z", 0, +0, "GMT"; try "2019-03-31T01:00:00Z", 1, +3600, "BST"; try "2019-10-27T00:59:59Z", 1, +3600, "BST"; try "2019-10-27T01:00:00Z", 0, +0, "GMT"; try "2020-03-29T00:59:59Z", 0, +0, "GMT"; try "2020-03-29T01:00:00Z", 1, +3600, "BST"; try "2020-10-25T00:59:59Z", 1, +3600, "BST"; try "2020-10-25T01:00:00Z", 0, +0, "GMT"; try "2021-03-28T00:59:59Z", 0, +0, "GMT"; try "2021-03-28T01:00:00Z", 1, +3600, "BST"; try "2021-10-31T00:59:59Z", 1, +3600, "BST"; try "2021-10-31T01:00:00Z", 0, +0, "GMT"; try "2022-03-27T00:59:59Z", 0, +0, "GMT"; try "2022-03-27T01:00:00Z", 1, +3600, "BST"; try "2022-10-30T00:59:59Z", 1, +3600, "BST"; try "2022-10-30T01:00:00Z", 0, +0, "GMT"; try "2023-03-26T00:59:59Z", 0, +0, "GMT"; try "2023-03-26T01:00:00Z", 1, +3600, "BST"; try "2023-10-29T00:59:59Z", 1, +3600, "BST"; try "2023-10-29T01:00:00Z", 0, +0, "GMT"; try "2024-03-31T00:59:59Z", 0, +0, "GMT"; try "2024-03-31T01:00:00Z", 1, +3600, "BST"; try "2024-10-27T00:59:59Z", 1, +3600, "BST"; try "2024-10-27T01:00:00Z", 0, +0, "GMT"; try "2025-03-30T00:59:59Z", 0, +0, "GMT"; try "2025-03-30T01:00:00Z", 1, +3600, "BST"; try "2025-10-26T00:59:59Z", 1, +3600, "BST"; try "2025-10-26T01:00:00Z", 0, +0, "GMT"; try "2026-03-29T00:59:59Z", 0, +0, "GMT"; try "2026-03-29T01:00:00Z", 1, +3600, "BST"; try "2026-10-25T00:59:59Z", 1, +3600, "BST"; try "2026-10-25T01:00:00Z", 0, +0, "GMT"; try "2027-03-28T00:59:59Z", 0, +0, "GMT"; try "2027-03-28T01:00:00Z", 1, +3600, "BST"; try "2027-10-31T00:59:59Z", 1, +3600, "BST"; try "2027-10-31T01:00:00Z", 0, +0, "GMT"; try "2028-03-26T00:59:59Z", 0, +0, "GMT"; try "2028-03-26T01:00:00Z", 1, +3600, "BST"; try "2028-10-29T00:59:59Z", 1, +3600, "BST"; try "2028-10-29T01:00:00Z", 0, +0, "GMT"; try "2029-03-25T00:59:59Z", 0, +0, "GMT"; try "2029-03-25T01:00:00Z", 1, +3600, "BST"; try "2029-10-28T00:59:59Z", 1, +3600, "BST"; try "2029-10-28T01:00:00Z", 0, +0, "GMT"; try "2030-03-31T00:59:59Z", 0, +0, "GMT"; try "2030-03-31T01:00:00Z", 1, +3600, "BST"; try "2030-10-27T00:59:59Z", 1, +3600, "BST"; try "2030-10-27T01:00:00Z", 0, +0, "GMT"; try "2031-03-30T00:59:59Z", 0, +0, "GMT"; try "2031-03-30T01:00:00Z", 1, +3600, "BST"; try "2031-10-26T00:59:59Z", 1, +3600, "BST"; try "2031-10-26T01:00:00Z", 0, +0, "GMT"; try "2032-03-28T00:59:59Z", 0, +0, "GMT"; try "2032-03-28T01:00:00Z", 1, +3600, "BST"; try "2032-10-31T00:59:59Z", 1, +3600, "BST"; try "2032-10-31T01:00:00Z", 0, +0, "GMT"; try "2033-03-27T00:59:59Z", 0, +0, "GMT"; try "2033-03-27T01:00:00Z", 1, +3600, "BST"; try "2033-10-30T00:59:59Z", 1, +3600, "BST"; try "2033-10-30T01:00:00Z", 0, +0, "GMT"; try "2034-03-26T00:59:59Z", 0, +0, "GMT"; try "2034-03-26T01:00:00Z", 1, +3600, "BST"; try "2034-10-29T00:59:59Z", 1, +3600, "BST"; try "2034-10-29T01:00:00Z", 0, +0, "GMT"; try "2035-03-25T00:59:59Z", 0, +0, "GMT"; try "2035-03-25T01:00:00Z", 1, +3600, "BST"; try "2035-10-28T00:59:59Z", 1, +3600, "BST"; try "2035-10-28T01:00:00Z", 0, +0, "GMT"; try "2036-03-30T00:59:59Z", 0, +0, "GMT"; try "2036-03-30T01:00:00Z", 1, +3600, "BST"; try "2036-10-26T00:59:59Z", 1, +3600, "BST"; try "2036-10-26T01:00:00Z", 0, +0, "GMT"; try "2037-03-29T00:59:59Z", 0, +0, "GMT"; try "2037-03-29T01:00:00Z", 1, +3600, "BST"; try "2037-10-25T00:59:59Z", 1, +3600, "BST"; try "2037-10-25T01:00:00Z", 0, +0, "GMT"; try "2038-03-28T00:59:59Z", 0, +0, "GMT"; try "2038-03-28T01:00:00Z", 1, +3600, "BST"; try "2038-10-31T00:59:59Z", 1, +3600, "BST"; try "2038-10-31T01:00:00Z", 0, +0, "GMT"; try "2039-03-27T00:59:59Z", 0, +0, "GMT"; try "2039-03-27T01:00:00Z", 1, +3600, "BST"; try "2039-10-30T00:59:59Z", 1, +3600, "BST"; try "2039-10-30T01:00:00Z", 0, +0, "GMT"; # The Davis base in Antarctica has been uninhabited at times. $tz = DateTime::TimeZone::Tzfile->new("t/Davis.tz"); try "1953-07-01T12:00:00Z", "zone disuse"; try "1957-01-12T23:59:59Z", "zone disuse"; try "1957-01-13T00:00:00Z", 0, +25200, "DAVT"; try "1960-01-01T12:00:00Z", 0, +25200, "DAVT"; try "1964-10-31T16:59:59Z", 0, +25200, "DAVT"; try "1964-10-31T17:00:00Z", "zone disuse"; try "1967-01-01T12:00:00Z", "zone disuse"; try "1969-01-31T23:59:59Z", "zone disuse"; try "1969-02-01T00:00:00Z", 0, +25200, "DAVT"; try "1980-01-01T12:00:00Z", 0, +25200, "DAVT"; try "2009-10-17T18:59:59Z", 0, +25200, "DAVT"; try "2009-10-17T19:00:00Z", 0, +18000, "DAVT"; try "2010-01-01T12:00:00Z", 0, +18000, "DAVT"; try "2010-03-10T19:59:59Z", 0, +18000, "DAVT"; try "2010-03-10T20:00:00Z", 0, +25200, "DAVT"; try "2011-01-01T12:00:00Z", 0, +25200, "DAVT"; # This version of Hebron.tz has a non-POSIX TZ extension rule. $tz = DateTime::TimeZone::Tzfile->new("t/Hebron.tz"); try "2035-03-29T21:59:59Z", 0, +7200, "EET"; try "2035-03-29T22:00:00Z", 1, +10800, "EEST"; try "2035-09-20T21:59:59Z", 1, +10800, "EEST"; try "2035-09-20T22:00:00Z", 0, +7200, "EET"; try "2036-03-27T21:59:59Z", 0, +7200, "EET"; try "2036-03-27T22:00:00Z", 1, +10800, "EEST"; try "2036-09-25T21:59:59Z", 1, +10800, "EEST"; try "2036-09-25T22:00:00Z", 0, +7200, "EET"; try "2037-03-26T21:59:59Z", 0, +7200, "EET"; try "2037-03-26T22:00:00Z", 1, +10800, "EEST"; try "2037-09-24T21:59:59Z", 1, +10800, "EEST"; try "2037-09-24T22:00:00Z", 0, +7200, "EET"; try "2038-03-25T21:59:59Z", 0, +7200, "EET"; try "2038-03-25T22:00:00Z", 1, +10800, "EEST"; try "2038-09-23T21:59:59Z", 1, +10800, "EEST"; try "2038-09-23T22:00:00Z", 0, +7200, "EET"; try "2039-03-31T21:59:59Z", 0, +7200, "EET"; try "2039-03-31T22:00:00Z", 1, +10800, "EEST"; try "2039-09-22T21:59:59Z", 1, +10800, "EEST"; try "2039-09-22T22:00:00Z", 0, +7200, "EET"; # This version of San_Luis.tz has no POSIX-TZ extension rule, because # the source data ends with an indefinite-future observance that is on # DST, and that can't be expressed in a POSIX-TZ recipe. The correct # interpretation of the tzfile is that the zone behaviour is unknown # after the final transition time. $tz = DateTime::TimeZone::Tzfile->new("t/San_Luis.tz"); try "2008-01-01T12:00:00Z", 1, -7200, "ARST"; try "2008-01-21T01:59:59Z", 1, -7200, "ARST"; try "2008-01-21T02:00:00Z", 1, -10800, "WARST"; try "2008-03-09T02:59:59Z", 1, -10800, "WARST"; try "2008-03-09T03:00:00Z", 0, -14400, "WART"; try "2008-10-12T03:59:59Z", 0, -14400, "WART"; try "2008-10-12T04:00:00Z", 1, -10800, "WARST"; try "2009-03-08T02:59:59Z", 1, -10800, "WARST"; try "2009-03-08T03:00:00Z", 0, -14400, "WART"; try "2009-10-11T03:59:59Z", 0, -14400, "WART"; try "2009-10-11T04:00:00Z", "missing data"; try "2010-01-01T12:00:00Z", "missing data"; # Loyston was settled in the early 19th century and ultimately abandoned # in 1936 to make way for the Norris Lake. This tzfile is not from the # Olson database. It's here to test the handling of a presently-disused # zone. $tz = DateTime::TimeZone::Tzfile->new("t/Loyston.tz"); try "1799-01-01T12:00:00Z", "zone disuse"; try "1799-12-31T23:59:59Z", "zone disuse"; try "1800-01-01T00:00:00Z", 0, -20144, "LMT"; try "1883-11-18T16:59:59Z", 0, -20144, "LMT"; try "1883-11-18T17:00:00Z", 0, -18000, "EST"; try "1918-03-31T06:59:59Z", 0, -18000, "EST"; try "1918-03-31T07:00:00Z", 1, -14400, "EDT"; try "1918-10-27T05:59:59Z", 1, -14400, "EDT"; try "1918-10-27T06:00:00Z", 0, -18000, "EST"; try "1919-03-30T06:59:59Z", 0, -18000, "EST"; try "1919-03-30T07:00:00Z", 1, -14400, "EDT"; try "1919-10-26T05:59:59Z", 1, -14400, "EDT"; try "1919-10-26T06:00:00Z", 0, -18000, "EST"; try "1936-03-04T04:59:59Z", 0, -18000, "EST"; try "1936-03-04T05:00:00Z", "zone disuse"; try "1937-01-01T12:00:00Z", "zone disuse"; # leap seconds, including changes occurring immediately after a leap second # (these are not real leap second dates) $tz = DateTime::TimeZone::Tzfile->new("t/Kaliningrad.tz"); try "2005-02-01T12:00:00Z", 0, +7200, "EET"; try "2005-02-01T23:59:59Z", 0, +7200, "EET"; try "2005-02-01T23:59:60Z", 0, +7200, "EET"; try "2005-02-02T00:00:00Z", 0, +7200, "EET"; try "2005-02-02T12:00:00Z", 0, +7200, "EET"; try "2005-03-26T12:00:00Z", 0, +7200, "EET"; try "2005-03-26T23:59:59Z", 0, +7200, "EET"; try "2005-03-26T23:59:60Z", 0, +7200, "EET"; try "2005-03-27T00:00:00Z", 1, +10800, "EEST"; try "2005-03-27T12:00:00Z", 1, +10800, "EEST"; try "2005-04-01T12:00:00Z", 1, +10800, "EEST"; try "2005-04-01T23:59:59Z", 1, +10800, "EEST"; try "2005-04-01T23:59:60Z", 1, +10800, "EEST"; try "2005-04-02T00:00:00Z", 1, +10800, "EEST"; try "2005-04-02T12:00:00Z", 1, +10800, "EEST"; try "2005-10-29T12:00:00Z", 1, +10800, "EEST"; try "2005-10-29T23:59:59Z", 1, +10800, "EEST"; try "2005-10-29T23:59:60Z", 1, +10800, "EEST"; try "2005-10-30T00:00:00Z", 0, +7200, "EET"; try "2005-10-30T12:00:00Z", 0, +7200, "EET"; try "2005-12-01T12:00:00Z", 0, +7200, "EET"; try "2005-12-01T23:59:59Z", 0, +7200, "EET"; try "2005-12-01T23:59:60Z", 0, +7200, "EET"; try "2005-12-02T00:00:00Z", 0, +7200, "EET"; try "2005-12-02T12:00:00Z", 0, +7200, "EET"; 1;