From f956978619dfb25d856d5623b0c12cdf2b32af77 Mon Sep 17 00:00:00 2001 From: Packit Service Date: Apr 04 2021 00:20:47 +0000 Subject: Source-git repo for imports/c8s/perl-DateTime-TimeZone-Tzfile-0.011-3.el8 --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4a0aff0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/Build +/Makefile +/_build +/blib +/META.json +/META.yml +/MYMETA.json +/MYMETA.yml +/Makefile.PL +/SIGNATURE +/DateTime-TimeZone-Tzfile-* diff --git a/.packit.yaml b/.packit.yaml new file mode 100644 index 0000000..6cf2444 --- /dev/null +++ b/.packit.yaml @@ -0,0 +1,13 @@ +jobs: +- job: copr_build + metadata: + targets: &id001 [centos-stream-x86_64] + trigger: pull_request +- job: tests + metadata: + targets: *id001 + trigger: pull_request +sources: +- {path: DateTime-TimeZone-Tzfile-0.011.tar.gz, url: 'https://git.centos.org/sources/perl-DateTime-TimeZone-Tzfile/c8s/247845b75dc906ae56f343d7f6dce054151a0fb0'} +specfile_path: SPECS/perl-DateTime-TimeZone-Tzfile.spec +upstream_ref: c8s-source-git diff --git a/Build.PL b/Build.PL new file mode 100644 index 0000000..990665c --- /dev/null +++ b/Build.PL @@ -0,0 +1,59 @@ +{ 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 => { + "meta-spec" => { version => "2" }, + resources => { + bugtracker => { + mailto => "bug-DateTime-TimeZone-Tzfile". + "\@rt.cpan.org", + web => "https://rt.cpan.org/Public/Dist/". + "Display.html?Name=". + "DateTime-TimeZone-Tzfile", + }, + repository => { + type => "git", + url => "git://git.fysh.org/zefram/". + "DateTime-TimeZone-Tzfile.git", + }, + }, + }, + sign => 1, +)->create_build_script; + +1; diff --git a/Changes b/Changes new file mode 100644 index 0000000..05ee4f4 --- /dev/null +++ b/Changes @@ -0,0 +1,162 @@ +version 0.011; 2017-07-25 + + * no longer include a Makefile.PL in the distribution + + * in documentation, use four-column indentation for all verbatim + material + + * in META.{yml,json}, point to public bug tracker + + * in META.json, specify type of public repository + +version 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 diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..828cee0 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,22 @@ +.gitignore +Build.PL +Changes +MANIFEST +META.json +META.yml +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 diff --git a/META.json b/META.json new file mode 100644 index 0000000..baa0c53 --- /dev/null +++ b/META.json @@ -0,0 +1,73 @@ +{ + "abstract" : "tzfile (zoneinfo) timezone files", + "author" : [ + "Andrew Main (Zefram) " + ], + "dynamic_config" : 0, + "generated_by" : "Module::Build version 0.4224", + "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.011" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "mailto" : "bug-DateTime-TimeZone-Tzfile@rt.cpan.org", + "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=DateTime-TimeZone-Tzfile" + }, + "license" : [ + "http://dev.perl.org/licenses/" + ], + "repository" : { + "type" : "git", + "url" : "git://git.fysh.org/zefram/DateTime-TimeZone-Tzfile.git" + } + }, + "version" : "0.011", + "x_serialization_backend" : "JSON::PP version 2.93" +} diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..c92b19a --- /dev/null +++ b/META.yml @@ -0,0 +1,45 @@ +--- +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.4224, CPAN::Meta::Converter version 2.150010' +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.011' +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: + bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=DateTime-TimeZone-Tzfile + license: http://dev.perl.org/licenses/ + repository: git://git.fysh.org/zefram/DateTime-TimeZone-Tzfile.git +version: '0.011' +x_serialization_backend: 'CPAN::Meta::YAML version 0.012' diff --git a/README b/README new file mode 100644 index 0000000..8dd17b9 --- /dev/null +++ b/README @@ -0,0 +1,34 @@ +NAME + +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, 2017 +Andrew Main (Zefram) + +LICENSE + +This module is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. diff --git a/SIGNATURE b/SIGNATURE new file mode 100644 index 0000000..d51e4aa --- /dev/null +++ b/SIGNATURE @@ -0,0 +1,44 @@ +This file contains message digests of all files listed in MANIFEST, +signed via the Module::Signature module, version 0.81. + +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 8e848934ab6c7808ca5a5b43d48406ba822041b5 Build.PL +SHA1 5a106007b90a912caa86f2e632d80c43c4c8f6c3 Changes +SHA1 42a2e231fdef133cc9e91f23edbd88bffa10b072 MANIFEST +SHA1 9b10c8ff1311cd0bca36fa90db545c5cb8cfcd5f META.json +SHA1 f23ef0f92da22c70acb4d2e5062741604b404237 META.yml +SHA1 f0b1e6d65320146a5c0b9f9b64f81525499a38b0 README +SHA1 58af0805c0d1c4af5100408c9bb2e12538543047 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 + +iEYEARECAAYFAll3C8oACgkQOV9mt2VyAVG/RgCdHGukVnqHntBORrMeSuKnrnG5 +fEIAoKIonKpmk/yAXhcyHO1zWkdHtlnM +=8Xon +-----END PGP SIGNATURE----- diff --git a/SPECS/perl-DateTime-TimeZone-Tzfile.spec b/SPECS/perl-DateTime-TimeZone-Tzfile.spec new file mode 100644 index 0000000..9ba9d00 --- /dev/null +++ b/SPECS/perl-DateTime-TimeZone-Tzfile.spec @@ -0,0 +1,136 @@ +# Run optional test +%bcond_without perl_DateTime_TimeZone_Tzfile_enables_optional_test + +Name: perl-DateTime-TimeZone-Tzfile +Version: 0.011 +Release: 3%{?dist} +Summary: Tzfile (zoneinfo) timezone files +License: GPL+ or Artistic +Group: Development/Libraries +URL: http://search.cpan.org/dist/DateTime-TimeZone-Tzfile/ +Source0: http://www.cpan.org/authors/id/Z/ZE/ZEFRAM/DateTime-TimeZone-Tzfile-%{version}.tar.gz +BuildArch: noarch +# Build +BuildRequires: coreutils +BuildRequires: perl-generators +BuildRequires: perl-interpreter +BuildRequires: perl(Module::Build) +# Runtime +BuildRequires: perl(Carp) +BuildRequires: perl(Date::ISO8601) +BuildRequires: perl(DateTime::TimeZone::SystemV) >= 0.009 +BuildRequires: perl(integer) +BuildRequires: perl(IO::File) >= 1.13 +BuildRequires: perl(IO::Handle) >= 1.08 +BuildRequires: perl(Params::Classify) +BuildRequires: perl(strict) +BuildRequires: perl(warnings) +# Test Suite +BuildRequires: perl(Test::More) +%if %{with perl_DateTime_TimeZone_Tzfile_enables_optional_test} +# Optional Tests +BuildRequires: perl(Test::Pod) >= 1.00 +BuildRequires: perl(Test::Pod::Coverage) +%endif +# Dependencies +Requires: perl(:MODULE_COMPAT_%(eval "$(perl -V:version)"; echo $version)) +Requires: perl(DateTime::TimeZone::SystemV) >= 0.009 + +%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. + +%prep +%setup -q -n DateTime-TimeZone-Tzfile-%{version} + +%build +perl Build.PL --installdirs=vendor +./Build + +%install +./Build install --destdir=%{buildroot} --create_packlist=0 +%{_fixperms} -c %{buildroot} + +%check +./Build test + +%files +%doc Changes README +%{perl_vendorlib}/DateTime/ +%{_mandir}/man3/DateTime::TimeZone::Tzfile.3* + +%changelog +* Thu Feb 08 2018 Fedora Release Engineering - 0.011-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 0.011-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Tue Jul 25 2017 Paul Howarth - 0.011-1 +- Update to 0.011 + - No longer include a Makefile.PL in the distribution + - In documentation, use four-column indentation for all verbatim material + - In META.{yml,json}, point to public bug tracker + - In META.json, specify type of public repository +- Drop redundant %%{?perl_default_filter} +- Make %%files list more explicit + +* Mon Jun 05 2017 Jitka Plesnikova - 0.010-7 +- Perl 5.26 rebuild + +* Sat Feb 11 2017 Fedora Release Engineering - 0.010-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Sun May 15 2016 Jitka Plesnikova - 0.010-5 +- Perl 5.24 rebuild + +* Thu Feb 04 2016 Fedora Release Engineering - 0.010-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Thu Jun 18 2015 Fedora Release Engineering - 0.010-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Sat Jun 06 2015 Jitka Plesnikova - 0.010-2 +- Perl 5.22 rebuild + +* Tue Nov 18 2014 Petr Ĺ abata - 0.010-1 +- 0.010 bump + +* Thu Aug 28 2014 Jitka Plesnikova - 0.007-9 +- Perl 5.20 rebuild + +* Sat Jun 07 2014 Fedora Release Engineering - 0.007-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Sat Aug 03 2013 Fedora Release Engineering - 0.007-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Sun Jul 21 2013 Petr Pisar - 0.007-6 +- Perl 5.18 rebuild + +* Thu Feb 14 2013 Fedora Release Engineering - 0.007-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Fri Jul 20 2012 Fedora Release Engineering - 0.007-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Wed Jun 13 2012 Petr Pisar - 0.007-3 +- Perl 5.16 rebuild + +* Sun Mar 11 2012 Iain Arnell 0.007-2 +- drop perl(constant) build dep + +* Sun Mar 11 2012 Iain Arnell 0.007-1 +- update to latest upstream version +- drop Date::JD dependency + +* Fri Jan 13 2012 Fedora Release Engineering - 0.006-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Thu Oct 27 2011 Iain Arnell 0.006-1 +- Specfile autogenerated by cpanspec 1.78. diff --git a/lib/DateTime/TimeZone/Tzfile.pm b/lib/DateTime/TimeZone/Tzfile.pm new file mode 100644 index 0000000..180c429 --- /dev/null +++ b/lib/DateTime/TimeZone/Tzfile.pm @@ -0,0 +1,594 @@ +=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.011"; + +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, 2017 +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; diff --git a/t/Davis.tz b/t/Davis.tz new file mode 100644 index 0000000..cd7acad Binary files /dev/null and b/t/Davis.tz differ diff --git a/t/Hebron.tz b/t/Hebron.tz new file mode 100644 index 0000000..3704ea5 Binary files /dev/null and b/t/Hebron.tz differ diff --git a/t/Kaliningrad.tz b/t/Kaliningrad.tz new file mode 100644 index 0000000..fa6bab8 Binary files /dev/null and b/t/Kaliningrad.tz differ diff --git a/t/London.tz b/t/London.tz new file mode 100644 index 0000000..fe63ff7 Binary files /dev/null and b/t/London.tz differ diff --git a/t/Loyston.tz b/t/Loyston.tz new file mode 100644 index 0000000..556b110 Binary files /dev/null and b/t/Loyston.tz differ diff --git a/t/San_Luis.tz b/t/San_Luis.tz new file mode 100644 index 0000000..fa30a68 Binary files /dev/null and b/t/San_Luis.tz differ diff --git a/t/construct.t b/t/construct.t new file mode 100644 index 0000000..0e2747b --- /dev/null +++ b/t/construct.t @@ -0,0 +1,113 @@ +use 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; diff --git a/t/crlf.t b/t/crlf.t new file mode 100644 index 0000000..a48c4ab --- /dev/null +++ b/t/crlf.t @@ -0,0 +1,15 @@ +use 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; diff --git a/t/ident.t b/t/ident.t new file mode 100644 index 0000000..1cbbb22 --- /dev/null +++ b/t/ident.t @@ -0,0 +1,47 @@ +use 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; diff --git a/t/local.t b/t/local.t new file mode 100644 index 0000000..37c2895 --- /dev/null +++ b/t/local.t @@ -0,0 +1,147 @@ +use 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; diff --git a/t/offset.t b/t/offset.t new file mode 100644 index 0000000..47a0387 --- /dev/null +++ b/t/offset.t @@ -0,0 +1,666 @@ +use 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; diff --git a/t/pod_cvg.t b/t/pod_cvg.t new file mode 100644 index 0000000..64f6c48 --- /dev/null +++ b/t/pod_cvg.t @@ -0,0 +1,9 @@ +use 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; diff --git a/t/pod_syn.t b/t/pod_syn.t new file mode 100644 index 0000000..6f004ac --- /dev/null +++ b/t/pod_syn.t @@ -0,0 +1,8 @@ +use 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;