DateTime-1.46/0000775000175000017500000000000013240151623012777 5ustar autarchautarchDateTime-1.46/dist.ini0000644000175000017500000000414313240151623014443 0ustar autarchautarchname = DateTime author = Dave Rolsky license = Artistic_2_0 copyright_holder = Dave Rolsky copyright_year = 2003 [PruneCruft] [@DROLSKY] dist = DateTime exclude_files = leap_seconds.h next_release_width = 6 pod_coverage_skip = DateTime::Conflicts pod_coverage_skip = DateTime::Helpers pod_coverage_skip = DateTime::PP pod_coverage_skip = DateTime::PPExtra pod_coverage_trustme = DateTime => qr/^[A-Z_]+$/ pod_coverage_trustme = DateTime => qr/0$/ pod_coverage_trustme = DateTime => qr/^STORABLE/ pod_coverage_trustme = DateTime => qr/^utc_year$/ pod_coverage_trustme = DateTime => qr/^timegm$/ pod_coverage_trustme = DateTime => qr/^day_of_month$/ pod_coverage_trustme = DateTime => qr/^doq$/ pod_coverage_trustme = DateTime => qr/^dow$/ pod_coverage_trustme = DateTime => qr/^doy$/ pod_coverage_trustme = DateTime => qr/^iso8601$/ pod_coverage_trustme = DateTime => qr/^local_rd_as_seconds$/ pod_coverage_trustme = DateTime => qr/^mday$/ pod_coverage_trustme = DateTime => qr/^min$/ pod_coverage_trustme = DateTime => qr/^mon$/ pod_coverage_trustme = DateTime => qr/^sec$/ pod_coverage_trustme = DateTime => qr/^wday$/ pod_coverage_trustme = DateTime::Duration => qr/^[A-Z_]+$/ pod_coverage_trustme = DateTime::Infinite => qr/^.+$/ ; deprecated methods pod_coverage_trustme = DateTime => qr/^DefaultLanguage$/ pod_coverage_trustme = DateTime => qr/^era$/ pod_coverage_trustme = DateTime => qr/^language$/ stopwords_file = .stopwords Test::CleanNamespaces.skip = DateTime::Conflicts use_github_issues = 1 -remove = Test::Compile -remove = Test::Pod::No404s -remove = Test::Synopsis [lib] lib = inc [=LeapSecondsHeader] [CopyFilesFromBuild] copy = leap_seconds.h [MetaResources] x_MailingList = datetime@perl.org [Prereqs / DevelopRequires] autodie = 0 ; Working around an issue with older Params::Validate releases under Perl 5.10 ; that causes failures with Travis. I'm not sure _what_ the issue is though. Module::Implementation = 0 [PurePerlTests] :version = 0.06 env_var = PERL_DATETIME_PP [Conflicts] :version = 0.18 DateTime::Format::Mail = 0.402 [Test::CheckBreaks] conflicts_module = DateTime::Conflicts DateTime-1.46/CREDITS0000644000175000017500000000223313240151623014015 0ustar autarchautarchThe core implementations for the DateTime.pm and DateTime::Duration modules originally came from Date::ICal and Date::ICal::Duration, both of which were written by Rich Bowen with help from the Reefknot team. Nowadays much of this code has been rewritten to the point that it is fundamentally original work. Parts of the API come from Time::Piece, by Matt Sergeant , who had help from Jarkko Hietaniemi . That API was originally created by Larry Wall. None of the code is shared. The DateTime::Locale functionality is based in part on the Date::Language modules that come with Graham Barr's TimeDate module suite. The strftime method in this module also borrows heavily from Graham's implementation. The week number and week year algorithms were taken from Steffen Beyer's Date::Calc module, but rewritten in Perl from scratch. The code for handling nanoseconds and the code for leap seconds were both largely written by Flavio Soibelmann Glock, who also has contributed various other features and fixes. Many others have helped out with code, ideas, and bug reports. See the Changes file for details. DateTime-1.46/META.yml0000644000175000017500000006453313240151623014261 0ustar autarchautarch--- abstract: 'A date and time object for Perl' author: - 'Dave Rolsky ' build_requires: CPAN::Meta::Check: '0.011' CPAN::Meta::Requirements: '0' ExtUtils::MakeMaker: '0' File::Spec: '0' Storable: '0' Test::Fatal: '0' Test::More: '0.96' Test::Warnings: '0.005' utf8: '0' configure_requires: Dist::CheckConflicts: '0.02' ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.010, CPAN::Meta::Converter version 2.150010' license: artistic_2 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: DateTime provides: DateTime: file: lib/DateTime.pm version: '1.46' DateTime::Duration: file: lib/DateTime/Duration.pm version: '1.46' DateTime::Helpers: file: lib/DateTime/Helpers.pm version: '1.46' DateTime::Infinite: file: lib/DateTime/Infinite.pm version: '1.46' DateTime::Infinite::Future: file: lib/DateTime/Infinite.pm version: '1.46' DateTime::Infinite::Past: file: lib/DateTime/Infinite.pm version: '1.46' DateTime::LeapSecond: file: lib/DateTime/LeapSecond.pm version: '1.46' DateTime::PP: file: lib/DateTime/PP.pm version: '1.46' DateTime::PPExtra: file: lib/DateTime/PPExtra.pm version: '1.46' DateTime::Types: file: lib/DateTime/Types.pm version: '1.46' requires: Carp: '0' DateTime::Locale: '1.06' DateTime::TimeZone: '2.02' Dist::CheckConflicts: '0.02' POSIX: '0' Params::ValidationCompiler: '0.26' Scalar::Util: '0' Specio: '0.18' Specio::Declare: '0' Specio::Exporter: '0' Specio::Library::Builtins: '0' Specio::Library::Numeric: '0' Specio::Library::String: '0' Try::Tiny: '0' XSLoader: '0' base: '0' integer: '0' namespace::autoclean: '0.19' overload: '0' parent: '0' perl: '5.008004' strict: '0' warnings: '0' warnings::register: '0' resources: MailingList: datetime@perl.org bugtracker: https://github.com/houseabsolute/DateTime.pm/issues homepage: http://metacpan.org/release/DateTime repository: git://github.com/houseabsolute/DateTime.pm.git version: '1.46' x_Dist_Zilla: perl: version: '5.026001' plugins: - class: Dist::Zilla::Plugin::PruneCruft name: PruneCruft version: '6.010' - class: Dist::Zilla::Plugin::MakeMaker config: Dist::Zilla::Role::TestRunner: default_jobs: 1 name: '@DROLSKY/MakeMaker' version: '6.010' - class: Dist::Zilla::Plugin::Git::GatherDir config: Dist::Zilla::Plugin::GatherDir: exclude_filename: - CONTRIBUTING.md - LICENSE - Makefile.PL - README.md - cpanfile - leap_seconds.h - ppport.h exclude_match: [] follow_symlinks: 0 include_dotfiles: 0 prefix: '' prune_directory: [] root: . Dist::Zilla::Plugin::Git::GatherDir: include_untracked: 0 name: '@DROLSKY/Git::GatherDir' version: '2.043' - class: Dist::Zilla::Plugin::ManifestSkip name: '@DROLSKY/ManifestSkip' version: '6.010' - class: Dist::Zilla::Plugin::License name: '@DROLSKY/License' version: '6.010' - class: Dist::Zilla::Plugin::ExecDir name: '@DROLSKY/ExecDir' version: '6.010' - class: Dist::Zilla::Plugin::ShareDir name: '@DROLSKY/ShareDir' version: '6.010' - class: Dist::Zilla::Plugin::Manifest name: '@DROLSKY/Manifest' version: '6.010' - class: Dist::Zilla::Plugin::CheckVersionIncrement name: '@DROLSKY/CheckVersionIncrement' version: '0.121750' - class: Dist::Zilla::Plugin::TestRelease name: '@DROLSKY/TestRelease' version: '6.010' - class: Dist::Zilla::Plugin::ConfirmRelease name: '@DROLSKY/ConfirmRelease' version: '6.010' - class: Dist::Zilla::Plugin::UploadToCPAN name: '@DROLSKY/UploadToCPAN' version: '6.010' - class: Dist::Zilla::Plugin::VersionFromMainModule name: '@DROLSKY/VersionFromMainModule' version: '0.03' - class: Dist::Zilla::Plugin::Authority name: '@DROLSKY/Authority' version: '1.009' - class: Dist::Zilla::Plugin::AutoPrereqs name: '@DROLSKY/AutoPrereqs' version: '6.010' - class: Dist::Zilla::Plugin::CopyFilesFromBuild name: '@DROLSKY/CopyFilesFromBuild' version: '0.170880' - class: Dist::Zilla::Plugin::GitHub::Meta name: '@DROLSKY/GitHub::Meta' version: '0.44' - class: Dist::Zilla::Plugin::GitHub::Update config: Dist::Zilla::Plugin::GitHub::Update: metacpan: 1 name: '@DROLSKY/GitHub::Update' version: '0.44' - class: Dist::Zilla::Plugin::MetaResources name: '@DROLSKY/MetaResources' version: '6.010' - class: Dist::Zilla::Plugin::MetaProvides::Package config: Dist::Zilla::Plugin::MetaProvides::Package: finder_objects: - class: Dist::Zilla::Plugin::FinderCode name: '@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM' version: '6.010' include_underscores: 0 Dist::Zilla::Role::MetaProvider::Provider: $Dist::Zilla::Role::MetaProvider::Provider::VERSION: '2.002004' inherit_missing: '1' inherit_version: '1' meta_noindex: '1' Dist::Zilla::Role::ModuleMetadata: Module::Metadata: '1.000033' version: '0.004' name: '@DROLSKY/MetaProvides::Package' version: '2.004003' - class: Dist::Zilla::Plugin::Meta::Contributors name: '@DROLSKY/Meta::Contributors' version: '0.003' - class: Dist::Zilla::Plugin::MetaConfig name: '@DROLSKY/MetaConfig' version: '6.010' - class: Dist::Zilla::Plugin::MetaJSON name: '@DROLSKY/MetaJSON' version: '6.010' - class: Dist::Zilla::Plugin::MetaYAML name: '@DROLSKY/MetaYAML' version: '6.010' - class: Dist::Zilla::Plugin::NextRelease name: '@DROLSKY/NextRelease' version: '6.010' - class: Dist::Zilla::Plugin::Prereqs config: Dist::Zilla::Plugin::Prereqs: phase: test type: requires name: '@DROLSKY/Test::More with subtest' version: '6.010' - class: Dist::Zilla::Plugin::Prereqs config: Dist::Zilla::Plugin::Prereqs: phase: develop type: requires name: '@DROLSKY/Modules for use with tidyall' version: '6.010' - class: Dist::Zilla::Plugin::Prereqs config: Dist::Zilla::Plugin::Prereqs: phase: develop type: requires name: '@DROLSKY/Test::Version which fixes https://github.com/plicease/Test-Version/issues/7' version: '6.010' - class: Dist::Zilla::Plugin::PromptIfStale config: Dist::Zilla::Plugin::PromptIfStale: check_all_plugins: 0 check_all_prereqs: 0 modules: - Dist::Zilla::PluginBundle::DROLSKY phase: build run_under_travis: 0 skip: [] name: '@DROLSKY/Dist::Zilla::PluginBundle::DROLSKY' version: '0.054' - class: Dist::Zilla::Plugin::PromptIfStale config: Dist::Zilla::Plugin::PromptIfStale: check_all_plugins: 1 check_all_prereqs: 1 modules: [] phase: release run_under_travis: 0 skip: - Dist::Zilla::Plugin::DROLSKY::Contributors - Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch - Dist::Zilla::Plugin::DROLSKY::License - Dist::Zilla::Plugin::DROLSKY::TidyAll - Dist::Zilla::Plugin::DROLSKY::WeaverConfig - Pod::Weaver::PluginBundle::DROLSKY name: '@DROLSKY/PromptIfStale' version: '0.054' - class: Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable name: '@DROLSKY/Test::Pod::Coverage::Configurable' version: '0.07' - class: Dist::Zilla::Plugin::Test::PodSpelling config: Dist::Zilla::Plugin::Test::PodSpelling: directories: - bin - lib spell_cmd: '' stopwords: - Anno - BCE - CLDR - CPAN - DATETIME - DROLSKY - "DROLSKY's" - DateTime - DateTimes - Datetime - Datetimes - Domini - EEEE - EEEEE - Flávio - Formatters - GGGG - GGGGG - Glock - Hant - IEEE - IEEE - LLL - LLLL - LLLLL - Liang - "Liang's" - MMM - MMMM - MMMMM - Measham - "Measham's" - POSIX - PayPal - PayPal - QQQ - QQQQ - Rata - Rata - Rolsky - "Rolsky's" - SU - Soibelmann - Storable - TW - TZ - Tsai - UTC - VVVV - YAPCs - ZZZZ - ZZZZZ - afterwards - bian - ccc - cccc - ccccc - conformant - datetime - "datetime's" - datetimes - decrement - dian - drolsky - durations - eee - eeee - eeeee - fallback - formatter - hh - iCal - ji - mutiplication - na - namespace - ni - nitty - "other's" - proleptic - qqq - qqqq - sexagesimal - subclasses - uu - vvvv - wiki - yy - yyyy - yyyyy - zh - zzzz wordlist: Pod::Wordlist name: '@DROLSKY/Test::PodSpelling' version: '2.007005' - class: Dist::Zilla::Plugin::PodSyntaxTests name: '@DROLSKY/PodSyntaxTests' version: '6.010' - class: Dist::Zilla::Plugin::RunExtraTests config: Dist::Zilla::Role::TestRunner: default_jobs: 1 name: '@DROLSKY/RunExtraTests' version: '0.029' - class: Dist::Zilla::Plugin::MojibakeTests name: '@DROLSKY/MojibakeTests' version: '0.8' - class: Dist::Zilla::Plugin::Test::CleanNamespaces config: Dist::Zilla::Plugin::Test::CleanNamespaces: filename: xt/author/clean-namespaces.t skips: - DateTime::Conflicts name: '@DROLSKY/Test::CleanNamespaces' version: '0.006' - class: Dist::Zilla::Plugin::Test::CPAN::Changes config: Dist::Zilla::Plugin::Test::CPAN::Changes: changelog: Changes name: '@DROLSKY/Test::CPAN::Changes' version: '0.012' - class: Dist::Zilla::Plugin::Test::CPAN::Meta::JSON name: '@DROLSKY/Test::CPAN::Meta::JSON' version: '0.004' - class: Dist::Zilla::Plugin::Test::EOL config: Dist::Zilla::Plugin::Test::EOL: filename: xt/author/eol.t finder: - ':ExecFiles' - ':InstallModules' - ':TestFiles' trailing_whitespace: 1 name: '@DROLSKY/Test::EOL' version: '0.19' - class: Dist::Zilla::Plugin::Test::NoTabs config: Dist::Zilla::Plugin::Test::NoTabs: filename: xt/author/no-tabs.t finder: - ':InstallModules' - ':ExecFiles' - ':TestFiles' name: '@DROLSKY/Test::NoTabs' version: '0.15' - class: Dist::Zilla::Plugin::Test::Portability config: Dist::Zilla::Plugin::Test::Portability: options: '' name: '@DROLSKY/Test::Portability' version: '2.001000' - class: Dist::Zilla::Plugin::Test::TidyAll name: '@DROLSKY/Test::TidyAll' version: '0.04' - class: Dist::Zilla::Plugin::Test::ReportPrereqs name: '@DROLSKY/Test::ReportPrereqs' version: '0.027' - class: Dist::Zilla::Plugin::Test::Version name: '@DROLSKY/Test::Version' version: '1.09' - class: Dist::Zilla::Plugin::DROLSKY::Contributors name: '@DROLSKY/DROLSKY::Contributors' version: '0.89' - class: Dist::Zilla::Plugin::Git::Contributors config: Dist::Zilla::Plugin::Git::Contributors: git_version: 2.16.1 include_authors: 0 include_releaser: 1 order_by: name paths: [] name: '@DROLSKY/Git::Contributors' version: '0.032' - class: Dist::Zilla::Plugin::SurgicalPodWeaver config: Dist::Zilla::Plugin::PodWeaver: config_plugins: - '@DROLSKY' finder: - ':InstallModules' - ':ExecFiles' plugins: - class: Pod::Weaver::Plugin::EnsurePod5 name: '@CorePrep/EnsurePod5' version: '4.015' - class: Pod::Weaver::Plugin::H1Nester name: '@CorePrep/H1Nester' version: '4.015' - class: Pod::Weaver::Plugin::SingleEncoding name: '@DROLSKY/SingleEncoding' version: '4.015' - class: Pod::Weaver::Plugin::Transformer name: '@DROLSKY/List' version: '4.015' - class: Pod::Weaver::Plugin::Transformer name: '@DROLSKY/Verbatim' version: '4.015' - class: Pod::Weaver::Section::Region name: '@DROLSKY/header' version: '4.015' - class: Pod::Weaver::Section::Name name: '@DROLSKY/Name' version: '4.015' - class: Pod::Weaver::Section::Version name: '@DROLSKY/Version' version: '4.015' - class: Pod::Weaver::Section::Region name: '@DROLSKY/prelude' version: '4.015' - class: Pod::Weaver::Section::Generic name: SYNOPSIS version: '4.015' - class: Pod::Weaver::Section::Generic name: DESCRIPTION version: '4.015' - class: Pod::Weaver::Section::Generic name: OVERVIEW version: '4.015' - class: Pod::Weaver::Section::Collect name: ATTRIBUTES version: '4.015' - class: Pod::Weaver::Section::Collect name: METHODS version: '4.015' - class: Pod::Weaver::Section::Collect name: FUNCTIONS version: '4.015' - class: Pod::Weaver::Section::Collect name: TYPES version: '4.015' - class: Pod::Weaver::Section::Leftovers name: '@DROLSKY/Leftovers' version: '4.015' - class: Pod::Weaver::Section::Region name: '@DROLSKY/postlude' version: '4.015' - class: Pod::Weaver::Section::GenerateSection name: '@DROLSKY/generate SUPPORT' version: '1.06' - class: Pod::Weaver::Section::AllowOverride name: '@DROLSKY/allow override SUPPORT' version: '0.05' - class: Pod::Weaver::Section::GenerateSection name: '@DROLSKY/generate SOURCE' version: '1.06' - class: Pod::Weaver::Section::GenerateSection name: '@DROLSKY/generate DONATIONS' version: '1.06' - class: Pod::Weaver::Section::Authors name: '@DROLSKY/Authors' version: '4.015' - class: Pod::Weaver::Section::Contributors name: '@DROLSKY/Contributors' version: '0.009' - class: Pod::Weaver::Section::Legal name: '@DROLSKY/Legal' version: '4.015' - class: Pod::Weaver::Section::Region name: '@DROLSKY/footer' version: '4.015' name: '@DROLSKY/SurgicalPodWeaver' version: '0.0023' - class: Dist::Zilla::Plugin::DROLSKY::WeaverConfig name: '@DROLSKY/DROLSKY::WeaverConfig' version: '0.89' - class: Dist::Zilla::Plugin::ReadmeAnyFromPod config: Dist::Zilla::Role::FileWatcher: version: '0.006' name: '@DROLSKY/README.md in build' version: '0.163250' - class: Dist::Zilla::Plugin::GenerateFile::FromShareDir config: Dist::Zilla::Plugin::GenerateFile::FromShareDir: destination_filename: CONTRIBUTING.md dist: Dist-Zilla-PluginBundle-DROLSKY encoding: UTF-8 has_xs: '1' location: build source_filename: CONTRIBUTING.md Dist::Zilla::Role::RepoFileInjector: allow_overwrite: 1 repo_root: . version: '0.007' name: '@DROLSKY/Generate CONTRIBUTING.md' version: '0.013' - class: Dist::Zilla::Plugin::InstallGuide name: '@DROLSKY/InstallGuide' version: '1.200007' - class: Dist::Zilla::Plugin::CPANFile name: '@DROLSKY/CPANFile' version: '6.010' - class: Dist::Zilla::Plugin::PPPort name: '@DROLSKY/PPPort' version: '0.008' - class: Dist::Zilla::Plugin::DROLSKY::License name: '@DROLSKY/DROLSKY::License' version: '0.89' - class: Dist::Zilla::Plugin::CheckStrictVersion name: '@DROLSKY/CheckStrictVersion' version: '0.001' - class: Dist::Zilla::Plugin::CheckSelfDependency config: Dist::Zilla::Plugin::CheckSelfDependency: finder: - ':InstallModules' Dist::Zilla::Role::ModuleMetadata: Module::Metadata: '1.000033' version: '0.004' name: '@DROLSKY/CheckSelfDependency' version: '0.011' - class: Dist::Zilla::Plugin::CheckPrereqsIndexed name: '@DROLSKY/CheckPrereqsIndexed' version: '0.020' - class: Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch config: Dist::Zilla::Role::Git::Repo: git_version: 2.16.1 repo_root: . name: '@DROLSKY/DROLSKY::Git::CheckFor::CorrectBranch' version: '0.89' - class: Dist::Zilla::Plugin::EnsureChangesHasContent name: '@DROLSKY/EnsureChangesHasContent' version: '0.02' - class: Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts config: Dist::Zilla::Role::Git::Repo: git_version: 2.16.1 repo_root: . name: '@DROLSKY/Git::CheckFor::MergeConflicts' version: '0.014' - class: Dist::Zilla::Plugin::DROLSKY::TidyAll name: '@DROLSKY/DROLSKY::TidyAll' version: '0.89' - class: Dist::Zilla::Plugin::Git::Check config: Dist::Zilla::Plugin::Git::Check: untracked_files: die Dist::Zilla::Role::Git::DirtyFiles: allow_dirty: - CONTRIBUTING.md - Changes - LICENSE - Makefile.PL - README.md - cpanfile - leap_seconds.h - ppport.h - tidyall.ini allow_dirty_match: [] changelog: Changes Dist::Zilla::Role::Git::Repo: git_version: 2.16.1 repo_root: . name: '@DROLSKY/Git::Check' version: '2.043' - class: Dist::Zilla::Plugin::Git::Commit config: Dist::Zilla::Plugin::Git::Commit: add_files_in: [] commit_msg: v%v%n%n%c Dist::Zilla::Role::Git::DirtyFiles: allow_dirty: - CONTRIBUTING.md - Changes - LICENSE - Makefile.PL - README.md - cpanfile - leap_seconds.h - ppport.h - tidyall.ini allow_dirty_match: [] changelog: Changes Dist::Zilla::Role::Git::Repo: git_version: 2.16.1 repo_root: . Dist::Zilla::Role::Git::StringFormatter: time_zone: local name: '@DROLSKY/Commit generated files' version: '2.043' - class: Dist::Zilla::Plugin::Git::Tag config: Dist::Zilla::Plugin::Git::Tag: branch: ~ changelog: Changes signed: 0 tag: v1.46 tag_format: v%v tag_message: v%v Dist::Zilla::Role::Git::Repo: git_version: 2.16.1 repo_root: . Dist::Zilla::Role::Git::StringFormatter: time_zone: local name: '@DROLSKY/Git::Tag' version: '2.043' - class: Dist::Zilla::Plugin::Git::Push config: Dist::Zilla::Plugin::Git::Push: push_to: - origin remotes_must_exist: 1 Dist::Zilla::Role::Git::Repo: git_version: 2.16.1 repo_root: . name: '@DROLSKY/Git::Push' version: '2.043' - class: Dist::Zilla::Plugin::BumpVersionAfterRelease config: Dist::Zilla::Plugin::BumpVersionAfterRelease: finders: - ':ExecFiles' - ':InstallModules' global: 0 munge_makefile_pl: 1 name: '@DROLSKY/BumpVersionAfterRelease' version: '0.017' - class: Dist::Zilla::Plugin::Git::Commit config: Dist::Zilla::Plugin::Git::Commit: add_files_in: [] commit_msg: 'Bump version after release' Dist::Zilla::Role::Git::DirtyFiles: allow_dirty: - Changes - dist.ini allow_dirty_match: - (?^:.+) changelog: Changes Dist::Zilla::Role::Git::Repo: git_version: 2.16.1 repo_root: . Dist::Zilla::Role::Git::StringFormatter: time_zone: local name: '@DROLSKY/Commit version bump' version: '2.043' - class: Dist::Zilla::Plugin::Git::Push config: Dist::Zilla::Plugin::Git::Push: push_to: - origin remotes_must_exist: 1 Dist::Zilla::Role::Git::Repo: git_version: 2.16.1 repo_root: . name: '@DROLSKY/Push version bump' version: '2.043' - class: Dist::Zilla::Plugin::lib config: Dist::Zilla::Plugin::lib: lib: - inc name: lib version: '0.001002' - class: LeapSecondsHeader name: =LeapSecondsHeader version: ~ - class: Dist::Zilla::Plugin::CopyFilesFromBuild name: CopyFilesFromBuild version: '0.170880' - class: Dist::Zilla::Plugin::MetaResources name: MetaResources version: '6.010' - class: Dist::Zilla::Plugin::Prereqs config: Dist::Zilla::Plugin::Prereqs: phase: develop type: requires name: DevelopRequires version: '6.010' - class: Dist::Zilla::Plugin::PurePerlTests name: PurePerlTests version: '0.06' - class: Dist::Zilla::Plugin::Conflicts name: Conflicts version: '0.19' - class: Dist::Zilla::Plugin::Test::CheckBreaks config: Dist::Zilla::Plugin::Test::CheckBreaks: conflicts_module: - DateTime::Conflicts no_forced_deps: 0 Dist::Zilla::Role::ModuleMetadata: Module::Metadata: '1.000033' version: '0.004' name: Test::CheckBreaks version: '0.019' - class: Dist::Zilla::Plugin::FinderCode name: ':InstallModules' version: '6.010' - class: Dist::Zilla::Plugin::FinderCode name: ':IncModules' version: '6.010' - class: Dist::Zilla::Plugin::FinderCode name: ':TestFiles' version: '6.010' - class: Dist::Zilla::Plugin::FinderCode name: ':ExtraTestFiles' version: '6.010' - class: Dist::Zilla::Plugin::FinderCode name: ':ExecFiles' version: '6.010' - class: Dist::Zilla::Plugin::FinderCode name: ':PerlExecFiles' version: '6.010' - class: Dist::Zilla::Plugin::FinderCode name: ':ShareFiles' version: '6.010' - class: Dist::Zilla::Plugin::FinderCode name: ':MainModule' version: '6.010' - class: Dist::Zilla::Plugin::FinderCode name: ':AllFiles' version: '6.010' - class: Dist::Zilla::Plugin::FinderCode name: ':NoFiles' version: '6.010' - class: Dist::Zilla::Plugin::FinderCode name: '@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM' version: '6.010' zilla: class: Dist::Zilla::Dist::Builder config: is_trial: '0' version: '6.010' x_authority: cpan:DROLSKY x_breaks: DateTime::Format::Mail: '<= 0.402' x_contributors: - 'Ben Bennett ' - 'Christian Hansen ' - 'Daisuke Maki ' - 'Dan Book ' - 'Dan Stewart ' - 'David E. Wheeler ' - 'David Precious ' - 'Doug Bell ' - 'Flávio Soibelmann Glock ' - 'Gianni Ceccarelli ' - 'Gregory Oschwald ' - 'Hauke D ' - 'Iain Truskett ' - 'Jason McIntosh ' - 'Joshua Hoblitt ' - 'Karen Etheridge ' - 'Michael Conrad ' - 'Michael R. Davis ' - 'M Somerville ' - 'Nick Tonkin <1nickt@users.noreply.github.com>' - 'Olaf Alders ' - 'Ovid ' - 'Philippe Bruhat (BooK) ' - 'Ricardo Signes ' - 'Richard Bowen ' - 'Ron Hill ' - 'Sam Kington ' - 'viviparous ' x_serialization_backend: 'YAML::Tiny version 1.70' DateTime-1.46/DateTime.xs0000644000175000017500000001546513240151623015060 0ustar autarchautarch#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #define NEED_sv_2pv_flags #include "ppport.h" #include /* This file is generated by tools/leap_seconds_header.pl */ #include "leap_seconds.h" /* This is a temporary hack until a better solution can be found to get the finite() function on Win32 */ #ifndef WIN32 # include # ifndef isfinite # ifdef finite # define finite isfinite # endif # endif #endif #define DAYS_PER_400_YEARS 146097 #define DAYS_PER_4_YEARS 1461 #define MARCH_1 306 #define SECONDS_PER_DAY 86400 const int PREVIOUS_MONTH_DOY[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; const int PREVIOUS_MONTH_DOLY[12] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; IV _real_is_leap_year(IV y) { /* See http://www.perlmonks.org/?node_id=274247 for where this silliness comes from */ return (y % 4) ? 0 : (y % 100) ? 1 : (y % 400) ? 0 : 1; } MODULE = DateTime PACKAGE = DateTime PROTOTYPES: ENABLE void _rd2ymd(self, d, extra = 0) IV d; IV extra; PREINIT: IV y, m; IV c; IV quarter; IV yadj = 0; IV dow, doy, doq; IV rd_days; PPCODE: rd_days = d; d += MARCH_1; if (d <= 0) { yadj = -1 * (((-1 * d) / DAYS_PER_400_YEARS) + 1); d -= yadj * DAYS_PER_400_YEARS; } /* c is century */ c = ((d * 4) - 1) / DAYS_PER_400_YEARS; d -= c * DAYS_PER_400_YEARS / 4; y = ((d * 4) - 1) / DAYS_PER_4_YEARS; d -= y * DAYS_PER_4_YEARS / 4; m = ((d * 12) + 1093) / 367; d -= ((m * 367) - 1094) / 12; y += (c * 100) + (yadj * 400); if (m > 12) { ++y; m -= 12; } EXTEND(SP, extra ? 7 : 3); mPUSHi(y); mPUSHi(m); mPUSHi(d); if (extra) { quarter = ( ( 1.0 / 3.1 ) * m ) + 1; dow = rd_days % 7; if ( dow <= 0 ) { dow += 7; } mPUSHi(dow); if (_real_is_leap_year(y)) { doy = PREVIOUS_MONTH_DOLY[m - 1] + d; doq = doy - PREVIOUS_MONTH_DOLY[ (3 * quarter) - 3 ]; } else { doy = PREVIOUS_MONTH_DOY[m - 1] + d; doq = doy - PREVIOUS_MONTH_DOY[ (3 * quarter ) - 3 ]; } mPUSHi(doy); mPUSHi(quarter); mPUSHi(doq); } void _ymd2rd(self, y, m, d) IV y; IV m; IV d; PREINIT: IV adj; PPCODE: if (m <= 2) { adj = (14 - m) / 12; y -= adj; m += 12 * adj; } else if (m > 14) { adj = (m - 3) / 12; y += adj; m -= 12 * adj; } if (y < 0) { adj = (399 - y) / 400; d -= DAYS_PER_400_YEARS * adj; y += 400 * adj; } d += (m * 367 - 1094) / 12 + y % 100 * DAYS_PER_4_YEARS / 4 + (y / 100 * 36524 + y / 400) - MARCH_1; EXTEND(SP, 1); mPUSHi(d); void _seconds_as_components(self, secs, utc_secs = 0, secs_modifier = 0) IV secs; IV utc_secs; IV secs_modifier; PREINIT: IV h, m, s; PPCODE: secs -= secs_modifier; h = secs / 3600; secs -= h * 3600; m = secs / 60; s = secs - (m * 60); if (utc_secs >= SECONDS_PER_DAY) { if (utc_secs >= SECONDS_PER_DAY + 1) { /* If we just use %d and the IV, we get a warning that IV is not an int. */ croak("Invalid UTC RD seconds value: %s", SvPV_nolen(newSViv(utc_secs))); } s += (utc_secs - SECONDS_PER_DAY) + 60; m = 59; h--; if (h < 0) { h = 23; } } EXTEND(SP, 3); mPUSHi(h); mPUSHi(m); mPUSHi(s); #ifdef isfinite void _normalize_tai_seconds(self, days, secs) SV* days; SV* secs; PPCODE: if (isfinite(SvNV(days)) && isfinite(SvNV(secs))) { IV d = SvIV(days); IV s = SvIV(secs); IV adj; if (s < 0) { adj = (s - (SECONDS_PER_DAY - 1)) / SECONDS_PER_DAY; } else { adj = s / SECONDS_PER_DAY; } d += adj; s -= adj * SECONDS_PER_DAY; sv_setiv(days, (IV) d); sv_setiv(secs, (IV) s); } void _normalize_leap_seconds(self, days, secs) SV* days; SV* secs; PPCODE: if (isfinite(SvNV(days)) && isfinite(SvNV(secs))) { IV d = SvIV(days); IV s = SvIV(secs); IV day_length; while (s < 0) { SET_DAY_LENGTH(d - 1, day_length); s += day_length; d--; } SET_DAY_LENGTH(d, day_length); while (s > day_length - 1) { s -= day_length; d++; SET_DAY_LENGTH(d, day_length); } sv_setiv(days, (IV) d); sv_setiv(secs, (IV) s); } #endif /* ifdef isfinite */ void _time_as_seconds(self, h, m, s) IV h; IV m; IV s; PPCODE: EXTEND(SP, 1); mPUSHi(h * 3600 + m * 60 + s); void _is_leap_year(self, y) IV y; PPCODE: EXTEND(SP, 1); mPUSHi(_real_is_leap_year(y)); void _day_length(self, utc_rd) IV utc_rd; PPCODE: IV day_length; SET_DAY_LENGTH(utc_rd, day_length); EXTEND(SP, 1); mPUSHi(day_length); void _day_has_leap_second(self, utc_rd) IV utc_rd; PPCODE: IV day_length; SET_DAY_LENGTH(utc_rd, day_length); EXTEND(SP, 1); mPUSHi(day_length > 86400 ? 1 : 0); void _accumulated_leap_seconds(self, utc_rd) IV utc_rd; PPCODE: IV leap_seconds; SET_LEAP_SECONDS(utc_rd, leap_seconds); EXTEND(SP, 1); mPUSHi(leap_seconds); DateTime-1.46/perltidyrc0000644000175000017500000000045513240151623015105 0ustar autarchautarch-l=78 -i=4 -ci=4 -se -b -bar -boc -vt=0 -vtc=0 -cti=0 -pt=1 -bt=1 -sbt=1 -bbt=1 -nolq -npro -nsfs --blank-lines-before-packages=0 --opening-hash-brace-right --no-outdent-long-comments --iterations=2 -wbb="% + - * / x != == >= <= =~ !~ < > | & >= < = **= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x=" DateTime-1.46/appveyor.yml0000644000175000017500000000056313240151623015371 0ustar autarchautarch--- skip_tags: true cache: - C:\strawberry install: - if not exist "C:\strawberry" cinst strawberryperl -y - set PATH=C:\strawberry\perl\bin;C:\strawberry\perl\site\bin;C:\strawberry\c\bin;%PATH% - cd %APPVEYOR_BUILD_FOLDER% - cpanm --installdeps . -n build_script: - perl -e 1 test_script: - prove -lrv t/ ### __app_cisetup__ # --- {} ### __app_cisetup__ DateTime-1.46/TODO0000644000175000017500000000120413240151623013462 0ustar autarchautarchTODO list for Perl module DateTime - what's the relation between UT1 and MJD/JD ? see: http://hpiers.obspm.fr/eop-pc/earthor/utc/leapsecond.html * strftime method - more tests for other languages * sub-second resolution - more tests: add/subtract/compare * Other - document RD days/seconds(/nanosecs?) in a separate document that will be the reference for DateTime.pm internals, as well as being useful for other calendar implementors. - thorough tests for subtraction & addition overloading NOTE TO FUTURE DEVELOPERS: Attempting to implement add_duration in XS actually seemed to slow date math operations down. Sad but true. DateTime-1.46/t/0000775000175000017500000000000013240151623013242 5ustar autarchautarchDateTime-1.46/t/09greg.t0000644000175000017500000000613413240151623014526 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; ## no critic (Subroutines::ProtectPrivateSubs) # test _ymd2rd and _rd2ymd for various dates # 2 tests are performed for each date (on _ymd2rd and _rd2ymd) # dates are specified as [rd,year,month,day] for ( # min and max supported days (for 32-bit system) [ -( 2**28 ), -734951, 9, 7 ], [ 2**28, 734952, 4, 25 ], # some miscellaneous dates (these are actually epoch dates for # various calendars from Calendrical Calculations (1st ed) Table # 1.1) [ -1721425, -4713, 11, 24 ], [ -1373427, -3760, 9, 7 ], [ -1137142, -3113, 8, 11 ], [ -1132959, -3101, 1, 23 ], [ -963099, -2636, 2, 15 ], [ -1, 0, 12, 30 ], [ 1, 1, 1, 1 ], [ 2796, 8, 8, 27 ], [ 103605, 284, 8, 29 ], [ 226896, 622, 3, 22 ], [ 227015, 622, 7, 19 ], [ 654415, 1792, 9, 22 ], [ 673222, 1844, 3, 21 ] ) { is( join( '/', DateTime->_rd2ymd( $_->[0] ) ), join( '/', @{$_}[ 1 .. 3 ] ), $_->[0] . " \t=> " . join '/', @{$_}[ 1 .. 3 ] ); is( DateTime->_ymd2rd( @{$_}[ 1 .. 3 ] ), $_->[0], join( '/', @{$_}[ 1 .. 3 ] ) . " \t=> " . $_->[0] ); } # normalization tests for ( [ -1753469, -4797, -33, 1 ], [ -1753469, -4803, 39, 1 ], [ -1753105, -4796, -34, 28 ], [ -1753105, -4802, 38, 28 ] ) { is( DateTime->_ymd2rd( @{$_}[ 1 .. 3 ] ), $_->[0], join( '/', @{$_}[ 1 .. 3 ] ) . " \t=> " . $_->[0] . ' (normalization)' ); } # test first and last day of each month from Jan -4800..Dec 4800 # this test bails after the first failure with a not ok. # if it completes successfully, only one ok is issued. my @mlen = ( 0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); my ( $dno, $y, $m, $dno2, $y2, $m2, $d2, $mlen ) = ( -1753530, -4800, 1 ); while ( $y <= 4800 ) { # test $y,$m,1 ++$dno; $dno2 = DateTime->_ymd2rd( $y, $m, 1 ); if ( $dno != $dno2 ) { is( $dno2, $dno, "greg torture test: _ymd2rd($y,$m,1) should be $dno" ); last; } ( $y2, $m2, $d2 ) = DateTime->_rd2ymd($dno); if ( $y2 != $y || $m2 != $m || $d2 != 1 ) { is( "$y2/$m2/$d2", "$y/$m/1", "greg torture test: _rd2ymd($dno) should be $y/$m/1" ); last; } # test $y,$m,$mlen $mlen = $mlen[$m] || ( $y % 4 ? 28 : $y % 100 ? 29 : $y % 400 ? 28 : 29 ); $dno += $mlen - 1; $dno2 = DateTime->_ymd2rd( $y, $m, $mlen ); if ( $dno != $dno2 ) { is( $dno2, $dno, "greg torture test: _ymd2rd($y,$m,$mlen) should be $dno" ); last; } ( $y2, $m2, $d2 ) = DateTime->_rd2ymd($dno); if ( $y2 != $y || $m2 != $m || $d2 != $mlen ) { is( "$y2/$m2/$d2", "$y/$m/$mlen", "greg torture test: _rd2ymd($dno) should be $y/$m/$mlen" ); last; } # and on to the next month... if ( ++$m > 12 ) { $m = 1; ++$y; } } pass('greg torture test') if $y == 4801; done_testing(); DateTime-1.46/t/45core-time.t0000644000175000017500000000045513240151623015466 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; no warnings 'redefine'; ## no critic (Variables::ProtectPrivateVars) local *DateTime::_core_time = sub {0}; my $dt = DateTime->now; is( "$dt", '1970-01-01T00:00:00', 'overriding DateTime::_core_time() works' ); done_testing(); DateTime-1.46/t/06add.t0000644000175000017500000002775413240151623014342 0ustar autarchautarchuse strict; use warnings; use Test::More; use Test::Fatal; use DateTime; { my $dt = DateTime->new( year => 1996, month => 11, day => 22, hour => 18, minute => 30, second => 20, time_zone => 'UTC', ); $dt->add( weeks => 8 ); is( $dt->year, 1997, 'year rollover' ); is( $dt->month, 1, 'month set on year rollover' ); is( $dt->datetime, '1997-01-17T18:30:20', 'okay on year rollover' ); $dt->add( weeks => 2 ); is( $dt->datetime, '1997-01-31T18:30:20', 'Adding weeks' ); $dt->add( seconds => 15 ); is( $dt->datetime, '1997-01-31T18:30:35', 'Adding seconds' ); $dt->add( minutes => 12 ); is( $dt->datetime, '1997-01-31T18:42:35', 'Adding minutes' ); $dt->add( minutes => 25, hours => 3, seconds => 7 ); is( $dt->datetime, '1997-01-31T22:07:42', 'Adding h,m,s' ); } { # Now, test the adding of durations my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( minutes => 1, seconds => 12 ); is( $dt->datetime, '1986-01-28T16:39:12', 'Adding durations with minutes and seconds works' ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( seconds => 30 ); is( $dt->datetime, '1986-01-28T16:38:30', 'Adding durations with seconds only works' ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( hours => 1, minutes => 10 ); is( $dt->datetime, '1986-01-28T17:48:00', 'Adding durations with hours and minutes works' ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( days => 3 ); is( $dt->datetime, '1986-01-31T16:38:00', 'Adding durations with days only works' ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( days => 3, hours => 2 ); is( $dt->datetime, '1986-01-31T18:38:00', 'Adding durations with days and hours works' ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( days => 3, hours => 2, minutes => 20, seconds => 15 ); is( $dt->datetime, '1986-01-31T18:58:15', 'Adding durations with days, hours, minutes, and seconds works' ); } { # Add 15M - this test failed at one point in N::I::Time my $dt = DateTime->new( year => 2001, month => 4, day => 5, hour => 16, time_zone => 'UTC' ); $dt->add( minutes => 15 ); is( $dt->datetime, '2001-04-05T16:15:00', 'Adding minutes to an ical string' ); # Subtract a duration $dt->add( minutes => -15 ); is( $dt->datetime, '2001-04-05T16:00:00', 'Back where we started' ); } { # Syntactic sugar works as well my $dt = DateTime->new( year => 2016, month => 11, day => 11, hour => 17, time_zone => 'UTC' ); my $duration = DateTime::Duration->new( years => 1 ); $dt->add($duration); is( $dt->datetime, '2017-11-11T17:00:00', 'Adding a Duration object via ->add works', ); $duration = DateTime::Duration->new( months => 5, days => 1 ); $dt->subtract($duration); is( $dt->datetime, '2017-06-10T17:00:00', 'Subtracting a Duration object via ->subtract works', ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( seconds => 60 ); is( $dt->datetime, '1986-01-28T16:39:00', 'adding positive seconds with seconds works' ); $dt->add( seconds => -120 ); is( $dt->datetime, '1986-01-28T16:37:00', 'adding negative seconds with seconds works' ); } { # test sub months my $dt = DateTime->new( year => 2001, month => 1, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-02-01', 'february 1st' ); } { my $dt = DateTime->new( year => 2001, month => 2, day => 28, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-03-01', 'march 1st' ); } { my $dt = DateTime->new( year => 2001, month => 3, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-04-01', 'april 1st' ); } { my $dt = DateTime->new( year => 2001, month => 4, day => 30, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-05-01', 'may 1st' ); } { my $dt = DateTime->new( year => 2001, month => 5, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-06-01', 'june 1st' ); } { my $dt = DateTime->new( year => 2001, month => 6, day => 30, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-07-01', 'july 1st' ); } { my $dt = DateTime->new( year => 2001, month => 7, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-08-01', 'august 1st' ); } { my $dt = DateTime->new( year => 2001, month => 8, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-09-01', 'september 1st' ); } { my $dt = DateTime->new( year => 2001, month => 9, day => 30, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-10-01', 'october 1st' ); } { my $dt = DateTime->new( year => 2001, month => 10, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-11-01', 'november 1st' ); } { my $dt = DateTime->new( year => 2001, month => 11, day => 30, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-12-01', 'december 1st' ); } { my $dt = DateTime->new( year => 2001, month => 12, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2002-01-01', 'january 1st' ); } { # Before leap day, not a leap year ... my $dt = DateTime->new( year => 2001, month => 2, day => 28, time_zone => 'UTC', ); $dt->add( years => 1 ); is( $dt->date, '2002-02-28', 'Adding a year' ); $dt->add( years => 17 ); is( $dt->date, '2019-02-28', 'Adding 17 years' ); } { # After leap day, not a leap year ... my $dt = DateTime->new( year => 2001, month => 3, day => 28, time_zone => 'UTC', ); $dt->add( years => 1 ); is( $dt->date, '2002-03-28', 'Adding a year' ); $dt->add( years => 17 ); is( $dt->date, '2019-03-28', 'Adding 17 years' ); } { # On leap day, in a leap year ... my $dt = DateTime->new( year => 2000, month => 2, day => 29, time_zone => 'UTC', ); $dt->add( years => 1 ); is( $dt->date, '2001-03-01', 'Adding a year' ); $dt->add( years => 17 ); is( $dt->date, '2018-03-01', 'Adding 17 years' ); } { # Before leap day, in a leap year ... my $dt = DateTime->new( year => 2000, month => 2, day => 28, time_zone => 'UTC', ); $dt->add( years => 1 ); is( $dt->date, '2001-02-28', 'Adding a year' ); $dt->add( years => 17 ); is( $dt->date, '2018-02-28', 'Adding 17 years' ); } { # After leap day, in a leap year ... my $dt = DateTime->new( year => 2000, month => 3, day => 28, time_zone => 'UTC', ); $dt->add( years => 1 ); is( $dt->date, '2001-03-28', 'Adding a year' ); $dt->add( years => 17 ); is( $dt->date, '2018-03-28', 'Adding 17 years' ); } { # Test a bunch of years, before leap day for ( 1 .. 99 ) { my $dt = DateTime->new( year => 2000, month => 2, day => 28, time_zone => 'UTC', ); $dt->add( years => $_ ); my $x = sprintf '%02d', $_; is( $dt->date, "20${x}-02-28", "Adding $_ years" ); } # Test a bunch of years, after leap day for ( 1 .. 99 ) { my $dt = DateTime->new( year => 2000, month => 3, day => 28, time_zone => 'UTC', ); $dt->add( years => $_ ); my $x = sprintf '%02d', $_; is( $dt->date, "20${x}-03-28", "Adding $_ years" ); } } # And more of the same, starting on a non-leap year { # Test a bunch of years, before leap day for ( 1 .. 97 ) { my $dt = DateTime->new( year => 2002, month => 2, day => 28, time_zone => 'UTC', ); $dt->add( years => $_ ); my $x = sprintf '%02d', $_ + 2; is( $dt->date, "20${x}-02-28", "Adding $_ years" ); } # Test a bunch of years, after leap day for ( 1 .. 97 ) { my $dt = DateTime->new( year => 2002, month => 3, day => 28, time_zone => 'UTC', ); $dt->add( years => $_ ); my $x = sprintf '%02d', $_ + 2; is( $dt->date, "20${x}-03-28", "Adding $_ years" ); } } { # subtract years for ( 1 .. 97 ) { my $dt = DateTime->new( year => 1999, month => 3, day => 1, time_zone => 'UTC', ); $dt->add( years => -$_ ); my $x = sprintf '%02d', 99 - $_; is( $dt->date, "19${x}-03-01", "Subtracting $_ years" ); } } # test some old bugs { # bug adding months where current month + months added were > 25 my $dt = DateTime->new( year => 1997, month => 12, day => 1, time_zone => 'UTC', ); $dt->add( months => 14 ); is( $dt->date, '1999-02-01', 'Adding months--rollover year' ); } { # bug subtracting months with year rollover my $dt = DateTime->new( year => 1997, month => 1, day => 1, time_zone => 'UTC', ); $dt->add( months => -1 ); is( $dt->date, '1996-12-01', 'Subtracting months--rollover year' ); my $new = $dt + DateTime::Duration->new( years => 2 ); is( $new->date, '1998-12-01', 'test + overloading' ); } { my $dt = DateTime->new( year => 1997, month => 1, day => 1, hour => 1, minute => 1, second => 59, nanosecond => 500000000, time_zone => 'UTC', ); $dt->add( nanoseconds => 500000000 ); is( $dt->second, 0, 'fractional second rollover' ); $dt->add( nanoseconds => 123000000 ); is( $dt->fractional_second, 0.123, 'as fractional_second' ); } { my $dt = DateTime->new( year => 2003, month => 2, day => 28 ); $dt->add( months => 1, days => 1 ); is( $dt->ymd, '2003-04-01', 'order of units in date math' ); } { my $dt = DateTime->new( year => 2003, hour => 12, minute => 1 ); $dt->add( minutes => 30, seconds => -1 ); is( $dt->hour, 12, 'hour is 12' ); is( $dt->minute, 30, 'minute is 30' ); is( $dt->second, 59, 'second is 59' ); } { my $dt = DateTime->new( year => 2014, month => 7, day => 1, time_zone => 'floating', ); $dt->add( days => 2 ); is( $dt->date, '2014-07-03', 'adding 2 days to a floating datetime' ); } { my $dt = DateTime->new( year => 0, month => 1, day => 1 ); my $dt2; is( exception { $dt2 = $dt->clone->add( days => 268_526_345 ) }, undef, 'no exception adding 268,526,345 days to 0000-01-01' ); if ($dt2) { is( $dt2->ymd(), '735200-02-29', 'adding 268,526,345 days produces 735200-02-29' ); } } done_testing(); DateTime-1.46/t/05set.t0000644000175000017500000000576613240151623014403 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 1996, month => 11, day => 22, hour => 18, minute => 30, second => 20, time_zone => 'UTC', ); is( $dt->month, 11, 'check month' ); $dt->set( month => 5 ); is( $dt->year, 1996, 'check year after setting month' ); is( $dt->month, 5, 'check month after setting it' ); is( $dt->day, 22, 'check day after setting month' ); is( $dt->hour, 18, 'check hour after setting month' ); is( $dt->minute, 30, 'check minute after setting month' ); is( $dt->second, 20, 'check second after setting month' ); $dt->set_time_zone('-060001'); is( $dt->year, 1996, 'check year after setting time zone' ); is( $dt->month, 5, 'check month after setting time zone' ); is( $dt->day, 22, 'check day after setting time zone' ); is( $dt->hour, 12, 'check hour after setting time zone' ); is( $dt->minute, 30, 'check minute after setting time zone' ); is( $dt->second, 19, 'check second after setting time zone' ); is( $dt->offset, -21601, 'check time zone offset after setting new time zone' ); $dt->set_time_zone('+0100'); is( $dt->year, 1996, 'check year after setting time zone' ); is( $dt->month, 5, 'check month after setting time zone' ); is( $dt->day, 22, 'check day after setting time zone' ); is( $dt->hour, 19, 'check hour after setting time zone' ); is( $dt->minute, 30, 'check minute after setting time zone' ); is( $dt->second, 20, 'check second after setting time zone' ); is( $dt->offset, 3600, 'check time zone offset after setting new time zone' ); $dt->set( hour => 17 ); is( $dt->year, 1996, 'check year after setting hour' ); is( $dt->month, 5, 'check month after setting hour' ); is( $dt->day, 22, 'check day after setting hour' ); is( $dt->hour, 17, 'check hour after setting hour' ); is( $dt->minute, 30, 'check minute after setting hour' ); is( $dt->second, 20, 'check second after setting hour' ); } { my $dt = DateTime->new( year => 1996, month => 11, day => 22, hour => 18, minute => 30, second => 20, time_zone => 'UTC', ); $dt->set_year(2000); is( $dt->year, 2000, 'check year after set_year' ); $dt->set_month(5); is( $dt->month, 5, 'check month after set_month' ); $dt->set_day(6); is( $dt->day, 6, 'check day after set_day' ); $dt->set_hour(7); is( $dt->hour, 7, 'check hour after set_hour' ); $dt->set_minute(8); is( $dt->minute, 8, 'check minute after set_minute' ); $dt->set_second(9); is( $dt->second, 9, 'check second after set_second' ); $dt->set_nanosecond(9999); is( $dt->nanosecond, 9999, 'check nanosecond after set_nanosecond' ); $dt->set_locale('fr_FR'); is( $dt->month_name, 'mai', 'check month name after set_locale' ); } done_testing(); DateTime-1.46/t/10subtract.t0000644000175000017500000003375113240151623015426 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 4, minute => 3, second => 2, nanosecond => 12, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 6, day => 12, hour => 5, minute => 7, second => 23, nanosecond => 7, time_zone => 'UTC' ); my $dur = $date2 - $date1; is( $dur->delta_months, 1, 'delta_months should be 1' ); is( $dur->delta_days, 2, 'delta_days should be 2' ); is( $dur->delta_minutes, 64, 'delta_minutes should be 64' ); is( $dur->delta_seconds, 20, 'delta_seconds should be 20' ); is( $dur->delta_nanoseconds, 999_999_995, 'delta_nanoseconds should be 999,999,995' ); is( $dur->years, 0, 'Years' ); is( $dur->months, 1, 'Months' ); is( $dur->weeks, 0, 'Weeks' ); is( $dur->days, 2, 'Days' ); is( $dur->hours, 1, 'Hours' ); is( $dur->minutes, 4, 'Minutes' ); is( $dur->seconds, 20, 'Seconds' ); is( $dur->nanoseconds, 999_999_995, 'Nanoseconds' ); } { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 4, minute => 3, second => 2, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 6, day => 12, hour => 5, minute => 7, second => 23, time_zone => 'UTC' ); my $dur = $date1 - $date2; is( $dur->delta_months, -1, 'delta_months should be -1' ); is( $dur->delta_days, -2, 'delta_days should be -2' ); is( $dur->delta_minutes, -64, 'delta_minutes should be 64' ); is( $dur->delta_seconds, -21, 'delta_seconds should be 20' ); is( $dur->delta_nanoseconds, 0, 'delta_nanoseconds should be 0' ); is( $dur->years, 0, 'Years' ); is( $dur->months, 1, 'Months' ); is( $dur->weeks, 0, 'Weeks' ); is( $dur->days, 2, 'Days' ); is( $dur->hours, 1, 'Hours' ); is( $dur->minutes, 4, 'Minutes' ); is( $dur->seconds, 21, 'Seconds' ); is( $dur->nanoseconds, 0, 'Nanoseconds' ); $dur = $date1 - $date1; is( $dur->delta_days, 0, 'date minus itself should have no delta days' ); is( $dur->delta_seconds, 0, 'date minus itself should have no delta seconds' ); my $new = $date1 - DateTime::Duration->new( years => 2 ); is( $new->datetime, '1999-05-10T04:03:02', 'test - overloading' ); } { my $d = DateTime->new( year => 2001, month => 10, day => 19, hour => 5, minute => 1, second => 1, time_zone => 'UTC' ); my $d2 = $d->clone; $d2->subtract( weeks => 1, days => 1, hours => 1, minutes => 1, seconds => 1, ); ok( defined $d2, 'Defined' ); is( $d2->datetime, '2001-10-11T04:00:00', 'Subtract and get the right thing' ); } # based on bug report from Eric Cholet { my $dt1 = DateTime->new( year => 2003, month => 2, day => 9, hour => 0, minute => 0, second => 1, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2003, month => 2, day => 7, hour => 23, minute => 59, second => 59, time_zone => 'UTC', ); my $dur1 = $dt1->subtract_datetime($dt2); is( $dur1->delta_days, 1, 'delta_days should be 1' ); is( $dur1->delta_seconds, 2, 'delta_seconds should be 2' ); my $dt3 = $dt2 + $dur1; is( DateTime->compare( $dt1, $dt3 ), 0, 'adding difference back to dt1 should give same datetime' ); my $dur2 = $dt2->subtract_datetime($dt1); is( $dur2->delta_days, -1, 'delta_days should be -1' ); is( $dur2->delta_seconds, -2, 'delta_seconds should be -2' ); my $dt4 = $dt1 + $dur2; is( DateTime->compare( $dt2, $dt4 ), 0, 'adding difference back to dt2 should give same datetime' ); } # test if the day changes because of a nanosecond subtract { my $dt = DateTime->new( year => 2001, month => 6, day => 12, hour => 0, minute => 0, second => 0, time_zone => 'UTC' ); $dt->subtract( nanoseconds => 1 ); is( $dt->nanosecond, 999999999, 'negative nanoseconds normalize ok' ); is( $dt->second, 59, 'seconds normalize ok' ); is( $dt->minute, 59, 'minutes normalize ok' ); is( $dt->hour, 23, 'hours normalize ok' ); is( $dt->day, 11, 'days normalize ok' ); } # test for a bug when nanoseconds were greater in earlier datetime { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 1, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2000, month => 1, day => 6, hour => 0, minute => 10, second => 0, nanosecond => 0, time_zone => 'UTC', ); my $dur = $dt2 - $dt1; is( $dur->delta_days, 0, 'delta_days is 0' ); is( $dur->delta_minutes, 1439, 'delta_minutes is 1439' ); is( $dur->delta_seconds, 59, 'delta_seconds is 59' ); is( $dur->delta_nanoseconds, 999_999_999, 'delta_nanoseconds is 999,999,999' ); ok( $dur->is_positive, 'duration is positive' ); } { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 20, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 10, time_zone => 'UTC', ); my $dur = $dt2 - $dt1; is( $dur->delta_days, 0, 'days is 0' ); is( $dur->delta_seconds, 0, 'seconds is 0' ); is( $dur->delta_nanoseconds, -10, 'nanoseconds is -10' ); ok( $dur->is_negative, 'duration is negative' ); } { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 11, second => 0, nanosecond => 20, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 10, time_zone => 'UTC', ); my $dur = $dt2 - $dt1; is( $dur->delta_days, 0, 'delta_days is 0' ); is( $dur->delta_minutes, -1, 'delta_minutes is -1' ); is( $dur->delta_seconds, 0, 'delta_seconds is 0' ); is( $dur->delta_nanoseconds, -10, 'nanoseconds is -10' ); ok( $dur->is_negative, 'duration is negative' ); } { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 20, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 11, second => 0, nanosecond => 10, time_zone => 'UTC', ); my $dur = $dt2 - $dt1; is( $dur->delta_days, 0, 'days is 0' ); is( $dur->delta_seconds, 59, 'seconds is 59' ); is( $dur->delta_nanoseconds, 999_999_990, 'nanoseconds is 999,999,990' ); ok( $dur->is_positive, 'duration is positive' ); } { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 11, second => 0, nanosecond => 10, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 20, time_zone => 'UTC', ); my $dur = $dt2 - $dt1; is( $dur->delta_days, 0, 'days is 0' ); is( $dur->delta_seconds, -59, 'seconds is -59' ); is( $dur->delta_nanoseconds, -999_999_990, 'nanoseconds is -999,999,990' ); ok( $dur->is_negative, 'duration is negative' ); } { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 11, second => 0, nanosecond => 20, time_zone => 'UTC', ); my $dur = $dt1 - $dt1; is( $dur->delta_days, 0, 'days is 0' ); is( $dur->delta_seconds, 0, 'seconds is 0' ); is( $dur->delta_nanoseconds, 0, 'nanoseconds is 0' ); ok( !$dur->is_positive, 'not positive' ); ok( !$dur->is_negative, 'not negative' ); } { my $dt1 = DateTime->new( year => 2003, month => 12, day => 31 ); my $dt2 = $dt1->clone->subtract( months => 1 ); is( $dt2->year, 2003, '2003-12-31 - 1 month = 2003-11-30' ); is( $dt2->month, 11, '2003-12-31 - 1 month = 2003-11-30' ); is( $dt2->day, 30, '2003-12-31 - 1 month = 2003-11-30' ); } { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 4, minute => 3, second => 2, nanosecond => 12, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 6, day => 12, hour => 5, minute => 7, second => 23, nanosecond => 7, time_zone => 'UTC' ); my $dur = $date2->subtract_datetime_absolute($date1); is( $dur->delta_months, 0, 'delta_months is 0' ); is( $dur->delta_minutes, 0, 'delta_minutes is 0' ); is( $dur->delta_seconds, 2_855_060, 'delta_seconds is 2,855,060' ); is( $dur->delta_nanoseconds, 999_999_995, 'delta_seconds is 999,999,995' ); } { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 4, minute => 3, second => 2, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 6, day => 12, hour => 5, minute => 7, second => 23, time_zone => 'UTC' ); my $dur = $date1->subtract_datetime_absolute($date2); is( $dur->delta_months, 0, 'delta_months is 0' ); is( $dur->delta_minutes, 0, 'delta_minutes is 0' ); is( $dur->delta_seconds, -2_855_061, 'delta_seconds is -2,855,061' ); is( $dur->delta_nanoseconds, 0, 'delta_nanoseconds is 0' ); } { my $date1 = DateTime->new( year => 2003, month => 9, day => 30 ); my $date2 = DateTime->new( year => 2003, month => 10, day => 1 ); my $date3 = DateTime->new( year => 2003, month => 10, day => 31 ); my $date4 = DateTime->new( year => 2003, month => 11, day => 1 ); my $date5 = DateTime->new( year => 2003, month => 2, day => 28 ); my $date6 = DateTime->new( year => 2003, month => 3, day => 1 ); my $date7 = DateTime->new( year => 2003, month => 1, day => 31 ); my $date8 = DateTime->new( year => 2003, month => 2, day => 1 ); foreach my $p ( [ $date1, $date2 ], [ $date3, $date4 ], [ $date5, $date6 ], [ $date7, $date8 ], ) { my $pos_diff = $p->[1]->subtract_datetime( $p->[0] ); is( $pos_diff->delta_days, 1, '1 day diff at end of month' ); is( $pos_diff->delta_months, 0, '0 month diff at end of month' ); my $neg_diff = $p->[0]->subtract_datetime( $p->[1] ); is( $neg_diff->delta_days, -1, '-1 day diff at end of month' ); is( $neg_diff->delta_months, 0, '0 month diff at end of month' ); } } { my $dt1 = DateTime->new( year => 2005, month => 6, day => 11, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2005, month => 11, day => 10, time_zone => 'UTC', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 4, '4 months - smaller day > bigger day' ); is( $deltas{days}, 29, '29 days - smaller day > bigger day' ); is( $deltas{minutes}, 0, '0 minutes - smaller day > bigger day' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, '$dt1 + $dur == $dt2' ); # XXX - this does not work, nor will it ever work # is( $dt2->clone->subtract_duration($dur), $dt1, '$dt2 - $dur == $dt1' ); } { my $dt1 = DateTime->new( year => 2005, month => 6, day => 11, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2005, month => 11, day => 10, time_zone => 'UTC', ); my $dur = $dt2->delta_days($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, '30 months - smaller day > bigger day' ); is( $deltas{days}, 152, '152 days - smaller day > bigger day' ); is( $deltas{minutes}, 0, '0 minutes - smaller day > bigger day' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, '$dt1 + $dur == $dt2' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, '$dt2 - $dur == $dt1' ); } { my $dt = DateTime->new( year => 2012, month => 6, day => 30, time_zone => 'floating', ); my $default = $dt->clone()->subtract( months => 1 ); is( $default->format_cldr('yyyy-MM-dd'), '2012-05-31', 'default subtract uses preserve end_of_month mode' ); my $with_mode = $dt->clone()->subtract( months => 1, end_of_month => 'limit', ); is( $with_mode->format_cldr('yyyy-MM-dd'), '2012-05-30', 'set end_of_month mode to limit in call to subtract()' ); } { my $dt = DateTime->new( year => 2014, month => 7, day => 3, time_zone => 'floating', ); $dt->subtract( days => 2 ); is( $dt->date, '2014-07-01', 'subtracting 2 days from a floating datetime' ); } done_testing(); DateTime-1.46/t/00load.t0000644000175000017500000000012613240151623014503 0ustar autarchautarchuse strict; use warnings; use Test::More 0.88; use_ok('DateTime'); done_testing(); DateTime-1.46/t/11duration.t0000644000175000017500000003306513240151623015423 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; use DateTime::Duration; { my %pairs = ( years => 1, months => 2, weeks => 3, days => 4, hours => 6, minutes => 7, seconds => 8, nanoseconds => 9, ); my $dur = DateTime::Duration->new(%pairs); while ( my ( $unit, $val ) = each %pairs ) { is( $dur->$unit(), $val, "$unit should be $val" ); } is( $dur->delta_months, 14, 'delta_months' ); is( $dur->delta_days, 25, 'delta_days' ); is( $dur->delta_minutes, 367, 'delta_minutes' ); is( $dur->delta_seconds, 8, 'delta_seconds' ); is( $dur->delta_nanoseconds, 9, 'delta_nanoseconds' ); is( $dur->in_units('months'), 14, 'in_units months' ); is( $dur->in_units('days'), 25, 'in_units days' ); is( $dur->in_units('minutes'), 367, 'in_units minutes' ); is( $dur->in_units('seconds'), 8, 'in_units seconds' ); is( $dur->in_units( 'nanoseconds', 'seconds' ), 9, 'in_units nanoseconds, seconds' ); is( $dur->in_units('years'), 1, 'in_units years' ); is( $dur->in_units( 'months', 'years' ), 2, 'in_units months, years' ); is( $dur->in_units('weeks'), 3, 'in_units weeks' ); is( $dur->in_units( 'days', 'weeks' ), 4, 'in_units days, weeks' ); is( $dur->in_units('hours'), 6, 'in_units hours' ); is( $dur->in_units( 'minutes', 'hours' ), 7, 'in_units minutes, hours' ); is( $dur->in_units('nanoseconds'), 8_000_000_009, 'in_units nanoseconds' ); my ( $years, $months, $weeks, $days, $hours, $minutes, $seconds, $nanoseconds ) = $dur->in_units( qw( years months weeks days hours minutes seconds nanoseconds ) ); is( $years, 1, 'in_units years, list context' ); is( $months, 2, 'in_units months, list context' ); is( $weeks, 3, 'in_units weeks, list context' ); is( $days, 4, 'in_units days, list context' ); is( $hours, 6, 'in_units hours, list context' ); is( $minutes, 7, 'in_units minutes, list context' ); is( $seconds, 8, 'in_units seconds, list context' ); is( $nanoseconds, 9, 'in_units nanoseconds, list context' ); ok( $dur->is_positive, 'should be positive' ); ok( !$dur->is_zero, 'should not be zero' ); ok( !$dur->is_negative, 'should not be negative' ); ok( $dur->is_wrap_mode, 'wrap mode' ); } { my %pairs = ( years => 1, months => 2, weeks => 3, days => 4, hours => 6, minutes => 7, seconds => 8, nanoseconds => 9, ); my $dur = DateTime::Duration->new( %pairs, end_of_month => 'limit' ); my $calendar_dur = $dur->calendar_duration; is( $calendar_dur->delta_months, 14, 'date - delta_months is 14' ); is( $calendar_dur->delta_minutes, 0, 'date - delta_minutes is 0' ); is( $calendar_dur->delta_seconds, 0, 'date - delta_seconds is 0' ); is( $calendar_dur->delta_nanoseconds, 0, 'date - delta_nanoseconds is 0' ); ok( $calendar_dur->is_limit_mode, 'limit mode' ); my $clock_dur = $dur->clock_duration; is( $clock_dur->delta_months, 0, 'time - delta_months is 0' ); is( $clock_dur->delta_minutes, 367, 'time - delta_minutes is 367' ); is( $clock_dur->delta_seconds, 8, 'time - delta_seconds is 8' ); is( $clock_dur->delta_nanoseconds, 9, 'time - delta_nanoseconds is 9' ); ok( $clock_dur->is_limit_mode, 'limit mode' ); } { my $dur = DateTime::Duration->new( days => 1, end_of_month => 'limit' ); ok( $dur->is_limit_mode, 'limit mode' ); } { my $dur = DateTime::Duration->new( days => 1, end_of_month => 'preserve' ); ok( $dur->is_preserve_mode, 'preserve mode' ); } my $leap_day = DateTime->new( year => 2004, month => 2, day => 29, time_zone => 'UTC', ); { my $new = $leap_day + DateTime::Duration->new( years => 1, end_of_month => 'wrap' ); is( $new->date, '2005-03-01', 'new date should be 2005-03-01' ); } { my $new = $leap_day + DateTime::Duration->new( years => 1, end_of_month => 'limit' ); is( $new->date, '2005-02-28', 'new date should be 2005-02-28' ); } { my $new = $leap_day + DateTime::Duration->new( years => 1, end_of_month => 'preserve' ); is( $new->date, '2005-02-28', 'new date should be 2005-02-28' ); my $new2 = $leap_day + DateTime::Duration->new( months => 1, end_of_month => 'preserve' ); is( $new2->date, '2004-03-31', 'new date should be 2004-03-31' ); } { my $inverse = DateTime::Duration->new( years => 1, months => 1, weeks => 1, days => 1, hours => 1, minutes => 2, seconds => 3, )->inverse; is( $inverse->years, 1, 'inverse years should be positive' ); is( $inverse->months, 1, 'inverse months should be positive' ); is( $inverse->weeks, 1, 'inverse weeks should be positive' ); is( $inverse->days, 1, 'inverse days should be positive' ); is( $inverse->hours, 1, 'inverse hours should be positive' ); is( $inverse->minutes, 2, 'inverse minutes should be positive' ); is( $inverse->seconds, 3, 'inverse minutes should be positive' ); is( $inverse->delta_months, -13, 'inverse delta months should be negative' ); is( $inverse->delta_days, -8, 'inverse delta months should be negative' ); is( $inverse->delta_minutes, -62, 'inverse delta minutes should be negative' ); is( $inverse->delta_seconds, -3, 'inverse delta seconds should be negative' ); ok( $inverse->is_negative, 'should be negative' ); ok( !$inverse->is_zero, 'should not be zero' ); ok( !$inverse->is_positive, 'should not be positivea' ); is( $inverse->end_of_month_mode(), 'preserve', 'inverse method uses default end_of_month_mode without explicit parameter' ); my $inverse2 = DateTime::Duration->new( years => 1 ) ->inverse( end_of_month => 'limit' ); is( $inverse2->end_of_month_mode(), 'limit', 'inverse method allows setting end_of_month_mode' ); } { my $dur1 = DateTime::Duration->new( months => 6, days => 10 ); my $dur2 = DateTime::Duration->new( months => 3, days => 7 ); my $new1 = $dur1 + $dur2; is( $new1->delta_months, 9, 'test + overloading' ); is( $new1->delta_days, 17, 'test + overloading' ); my $new2 = $dur1 - $dur2; is( $new2->delta_months, 3, 'test - overloading' ); is( $new2->delta_days, 3, 'test - overloading' ); my $new3 = $dur2 - $dur1; is( $new3->delta_months, -3, 'test - overloading' ); is( $new3->delta_days, -3, 'test - overloading' ); } { my $dur1 = DateTime::Duration->new( months => 6, days => 10 ); my $new1 = $dur1 * 4; is( $new1->delta_months, 24, 'test * overloading' ); is( $new1->delta_days, 40, 'test * overloading' ); $dur1->multiply(4); is( $dur1->delta_months, 24, 'test multiply' ); is( $dur1->delta_days, 40, 'test multiply' ); } { my $dur1 = DateTime::Duration->new( months => 6, days => 10, seconds => 3, nanoseconds => 1_200_300_400 ); my $dur2 = DateTime::Duration->new( seconds => 1, nanoseconds => 500_000_000 ); is( $dur1->delta_seconds, 4, 'test nanoseconds overflow' ); is( $dur1->delta_nanoseconds, 200_300_400, 'test nanoseconds remainder' ); my $new1 = $dur1 - $dur2; is( $new1->delta_seconds, 2, 'seconds is positive' ); is( $new1->delta_nanoseconds, 700_300_400, 'nanoseconds remainder is negative' ); $new1->add( nanoseconds => 500_000_000 ); is( $new1->delta_seconds, 3, 'seconds are unaffected' ); is( $new1->delta_nanoseconds, 200_300_400, 'nanoseconds are back' ); my $new2 = $dur1 - $dur2; $new2->add( nanoseconds => 1_500_000_000 ); is( $new2->delta_seconds, 4, 'seconds go up' ); is( $new2->delta_nanoseconds, 200_300_400, 'nanoseconds are normalized' ); $new2->subtract( nanoseconds => 100_000_000 ); is( $new2->delta_nanoseconds, 100_300_400, 'sub nanoseconds works' ); my $new3 = $dur2 * 3; is( $new3->delta_seconds, 4, 'seconds normalized after multiplication' ); is( $new3->delta_nanoseconds, 500_000_000, 'nanoseconds normalized after multiplication' ); } { my $dur1 = DateTime::Duration->new( seconds => 1 ); my $dur2 = DateTime::Duration->new( seconds => 1 ); $dur1->add($dur2); is( $dur1->delta_seconds, 2, 'add method works with a duration object' ); $dur1->subtract($dur2); is( $dur1->delta_seconds, 1, 'subtract method works with a duration object' ); } { my $dur = DateTime::Duration->new( nanoseconds => -10 ); is( $dur->nanoseconds, 10, 'nanoseconds is 10' ); is( $dur->delta_nanoseconds, -10, 'delta_nanoseconds is -10' ); ok( $dur->is_negative, 'duration is negative' ); } { my $dur = DateTime::Duration->new( days => 0 ); is( $dur->delta_days, 0, 'delta_days is 0' ); ok( !$dur->is_positive, 'not positive' ); ok( $dur->is_zero, 'is zero' ); ok( !$dur->is_negative, 'not negative' ); } { is( exception { DateTime::Duration->new( months => 3 )->add( hours => -3 ) ->add( minutes => 1 ); }, undef, 'method chaining should work' ); } { my $min_1 = DateTime::Duration->new( minutes => 1 ); my $hour_1 = DateTime::Duration->new( hours => 1 ); my $min_59 = $hour_1 - $min_1; is( $min_59->delta_months, 0, 'delta_months is 0' ); is( $min_59->delta_days, 0, 'delta_days is 0' ); is( $min_59->delta_minutes, 59, 'delta_minutes is 59' ); is( $min_59->delta_seconds, 0, 'delta_seconds is 0' ); is( $min_59->delta_nanoseconds, 0, 'delta_nanoseconds is 0' ); my $min_neg_59 = $min_1 - $hour_1; is( $min_neg_59->delta_months, 0, 'delta_months is 0' ); is( $min_neg_59->delta_days, 0, 'delta_days is 0' ); is( $min_neg_59->delta_minutes, -59, 'delta_minutes is -59' ); is( $min_neg_59->delta_seconds, 0, 'delta_seconds is 0' ); is( $min_neg_59->delta_nanoseconds, 0, 'delta_nanoseconds is 0' ); } { my $dur1 = DateTime::Duration->new( minutes => 10 ); my $dur2 = DateTime::Duration->new( minutes => 20 ); like( exception { 1 if $dur1 <=> $dur2 }, qr/does not overload comparison/, 'check error for duration comparison overload' ); is( DateTime::Duration->compare( $dur1, $dur2 ), -1, '20 minutes is greater than 10 minutes' ); is( DateTime::Duration->compare( $dur1, $dur2, DateTime->new( year => 1 ) ), -1, '20 minutes is greater than 10 minutes' ); } { my $dur1 = DateTime::Duration->new( days => 29 ); my $dur2 = DateTime::Duration->new( months => 1 ); my $base = DateTime->new( year => 2004 ); is( DateTime::Duration->compare( $dur1, $dur2, $base ), -1, '29 days is less than 1 month with base of 2004-01-01' ); $base = DateTime->new( year => 2004, month => 2 ); is( DateTime::Duration->compare( $dur1, $dur2, $base ), 0, '29 days is equal to 1 month with base of 2004-02-01' ); $base = DateTime->new( year => 2005, month => 2 ); is( DateTime::Duration->compare( $dur1, $dur2, $base ), 1, '29 days is greater than 1 month with base of 2005-02-01' ); } { my $dur1 = DateTime::Duration->new( nanoseconds => 1_000, seconds => 1, ); my $dur2 = $dur1->clone->subtract( nanoseconds => 5_000 ); is( $dur2->delta_seconds, 0, 'normalize nanoseconds to positive' ); is( $dur2->delta_nanoseconds, 999_996_000, 'normalize nanoseconds to positive' ); my $dur3 = $dur1->clone->subtract( nanoseconds => 6_000 ) ->subtract( nanoseconds => 999_999_000 ); is( $dur3->delta_seconds, 0, 'normalize nanoseconds to negative' ); is( $dur3->delta_nanoseconds, -4_000, 'normalize nanoseconds to negative' ); my $dur4 = DateTime::Duration->new( seconds => -1, nanoseconds => -2_500_000_000 ); is( $dur4->delta_seconds, -3, 'normalize many negative nanoseconds' ); is( $dur4->delta_nanoseconds, -500_000_000, 'normalize many negative nanoseconds' ); } { my $dur = DateTime::Duration->new( minutes => 30, seconds => -1, ); ok( !$dur->is_positive, 'is not positive' ); ok( !$dur->is_zero, 'is not zero' ); ok( !$dur->is_negative, 'is not negative' ); } { my $dur = DateTime::Duration->new( minutes => 50 ); is( $dur->in_units('years'), 0, 'in_units returns 0 for years' ); is( $dur->in_units('months'), 0, 'in_units returns 0 for months' ); is( $dur->in_units('days'), 0, 'in_units returns 0 for days' ); is( $dur->in_units('hours'), 0, 'in_units returns 0 for hours' ); is( $dur->in_units('seconds'), 0, 'in_units returns 0 for seconds' ); is( $dur->in_units('nanoseconds'), 0, 'in_units returns 0 for nanoseconds' ); } { local $TODO = 'reject fractional units in DateTime::Duration->new'; like( exception { DateTime::Duration->new( minutes => 50.2 ) }, qr/is an integer/, 'cannot create a duration with fractional units' ); } done_testing(); DateTime-1.46/t/35rd-values.t0000644000175000017500000000271113240151623015500 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 2000, hour => 1, nanosecond => 500, time_zone => 'UTC', ); my ( $utc_rd_days, $utc_rd_secs, $utc_nanosecs ) = $dt->utc_rd_values; is( $utc_rd_days, 730120, 'utc rd days is 730120' ); is( $utc_rd_secs, 3600, 'utc rd seconds is 3600' ); is( $utc_nanosecs, 500, 'nanoseconds is 500' ); my ( $local_rd_days, $local_rd_secs, $local_nanosecs ) = $dt->local_rd_values; is( $local_rd_days, $utc_rd_days, 'local & utc rd days are equal' ); is( $local_rd_secs, $utc_rd_secs, 'local & utc rd seconds are equal' ); is( $local_nanosecs, $utc_nanosecs, 'local & UTC nanoseconds are equal' ); } { my $dt = DateTime->new( year => 2000, hour => 1, nanosecond => 500, time_zone => '+02:00', ); my ( $utc_rd_days, $utc_rd_secs, $utc_nanosecs ) = $dt->utc_rd_values; is( $utc_rd_days, 730119, 'utc rd days is 730119' ); is( $utc_rd_secs, 82800, 'utc rd seconds is 82800' ); is( $utc_nanosecs, 500, 'nanoseconds is 500' ); my ( $local_rd_days, $local_rd_secs, $local_nanosecs ) = $dt->local_rd_values; is( $local_rd_days, 730120, 'local rd days is 730120' ); is( $local_rd_secs, 3600, 'local rd seconds is 3600' ); is( $local_nanosecs, 500, 'local nanoseconds is 500' ); } done_testing(); DateTime-1.46/t/00-report-prereqs.t0000644000175000017500000001342613240151623016642 0ustar autarchautarch#!perl use strict; use warnings; # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.027 use Test::More tests => 1; use ExtUtils::MakeMaker; use File::Spec; # from $version::LAX my $lax_version_re = qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? | (?:\.[0-9]+) (?:_[0-9]+)? ) | (?: v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? | (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? ) )/x; # hide optional CPAN::Meta modules from prereq scanner # and check if they are available my $cpan_meta = "CPAN::Meta"; my $cpan_meta_pre = "CPAN::Meta::Prereqs"; my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic # Verify requirements? my $DO_VERIFY_PREREQS = 1; sub _max { my $max = shift; $max = ( $_ > $max ) ? $_ : $max for @_; return $max; } sub _merge_prereqs { my ($collector, $prereqs) = @_; # CPAN::Meta::Prereqs object if (ref $collector eq $cpan_meta_pre) { return $collector->with_merged_prereqs( CPAN::Meta::Prereqs->new( $prereqs ) ); } # Raw hashrefs for my $phase ( keys %$prereqs ) { for my $type ( keys %{ $prereqs->{$phase} } ) { for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; } } } return $collector; } my @include = qw( ); my @exclude = qw( ); # Add static prereqs to the included modules list my $static_prereqs = do './t/00-report-prereqs.dd'; # Merge all prereqs (either with ::Prereqs or a hashref) my $full_prereqs = _merge_prereqs( ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), $static_prereqs ); # Add dynamic prereqs to the included modules list (if we can) my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; my $cpan_meta_error; if ( $source && $HAS_CPAN_META && (my $meta = eval { CPAN::Meta->load_file($source) } ) ) { $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); } else { $cpan_meta_error = $@; # capture error from CPAN::Meta->load_file($source) $source = 'static metadata'; } my @full_reports; my @dep_errors; my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; # Add static includes into a fake section for my $mod (@include) { $req_hash->{other}{modules}{$mod} = 0; } for my $phase ( qw(configure build test runtime develop other) ) { next unless $req_hash->{$phase}; next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); for my $type ( qw(requires recommends suggests conflicts modules) ) { next unless $req_hash->{$phase}{$type}; my $title = ucfirst($phase).' '.ucfirst($type); my @reports = [qw/Module Want Have/]; for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { next if $mod eq 'perl'; next if grep { $_ eq $mod } @exclude; my $file = $mod; $file =~ s{::}{/}g; $file .= ".pm"; my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; my $want = $req_hash->{$phase}{$type}{$mod}; $want = "undef" unless defined $want; $want = "any" if !$want && $want == 0; my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; if ($prefix) { my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); $have = "undef" unless defined $have; push @reports, [$mod, $want, $have]; if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { if ( $have !~ /\A$lax_version_re\z/ ) { push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; } elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { push @dep_errors, "$mod version '$have' is not in required range '$want'"; } } } else { push @reports, [$mod, $want, "missing"]; if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { push @dep_errors, "$mod is not installed ($req_string)"; } } } if ( @reports ) { push @full_reports, "=== $title ===\n\n"; my $ml = _max( map { length $_->[0] } @reports ); my $wl = _max( map { length $_->[1] } @reports ); my $hl = _max( map { length $_->[2] } @reports ); if ($type eq 'modules') { splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; } else { splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; } push @full_reports, "\n"; } } } if ( @full_reports ) { diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; } if ( $cpan_meta_error || @dep_errors ) { diag "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n"; } if ( $cpan_meta_error ) { my ($orig_source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; diag "\nCPAN::Meta->load_file('$orig_source') failed with: $cpan_meta_error\n"; } if ( @dep_errors ) { diag join("\n", "\nThe following REQUIRED prerequisites were not satisfied:\n", @dep_errors, "\n" ); } pass; # vim: ts=4 sts=4 sw=4 et: DateTime-1.46/t/42duration-class.t0000644000175000017500000000115513240151623016525 0ustar autarchautarch## no critic (Modules::ProhibitMultiplePackages) use strict; use warnings; use Test::More; use DateTime; { package DateTime::MySubclass; use base 'DateTime'; sub duration_class {'DateTime::Duration::MySubclass'} package DateTime::Duration::MySubclass; use base 'DateTime::Duration'; sub is_my_subclass {1} } my $dt = DateTime::MySubclass->now; my $delta = $dt - $dt; isa_ok( $delta, 'DateTime::Duration::MySubclass' ); isa_ok( $dt + $delta, 'DateTime::MySubclass' ); my $delta_days = $dt->delta_days($dt); isa_ok( $delta_days, 'DateTime::Duration::MySubclass' ); done_testing(); DateTime-1.46/t/13strftime.t0000644000175000017500000002727313240151623015441 0ustar autarchautarch# test suite stolen shamelessly from TimeDate distro use strict; use warnings; use utf8; use Test::More 0.96; use DateTime; use DateTime::Locale; test_strftime_for_locale( 'en-US', en_tests() ); test_strftime_for_locale( 'de', de_tests() ); test_strftime_for_locale( 'it', it_tests() ); subtest( 'strftime with multiple params', sub { my $dt = DateTime->new( year => 1800, month => 1, day => 10, time_zone => 'UTC', ); my ( $y, $d ) = $dt->strftime( '%Y', '%d' ); is( $y, 1800, 'first value is year' ); is( $d, 10, 'second value is day' ); $y = $dt->strftime( '%Y', '%d' ); is( $y, 1800, 'scalar context returns year' ); } ); subtest( 'hour formatting', sub { my $dt = DateTime->new( year => 2003, hour => 0, minute => 0 ); is( $dt->strftime('%I %M %p'), '12 00 AM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), '12 00 AM', 'formatting of hours as 1-12' ); $dt->set( hour => 1 ); is( $dt->strftime('%I %M %p'), '01 00 AM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), ' 1 00 AM', 'formatting of hours as 1-12' ); $dt->set( hour => 11 ); is( $dt->strftime('%I %M %p'), '11 00 AM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), '11 00 AM', 'formatting of hours as 1-12' ); $dt->set( hour => 12 ); is( $dt->strftime('%I %M %p'), '12 00 PM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), '12 00 PM', 'formatting of hours as 1-12' ); $dt->set( hour => 13 ); is( $dt->strftime('%I %M %p'), '01 00 PM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), ' 1 00 PM', 'formatting of hours as 1-12' ); $dt->set( hour => 23 ); is( $dt->strftime('%I %M %p'), '11 00 PM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), '11 00 PM', 'formatting of hours as 1-12' ); $dt->set( hour => 0 ); is( $dt->strftime('%I %M %p'), '12 00 AM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), '12 00 AM', 'formatting of hours as 1-12' ); } ); subtest( '%V', sub { is( DateTime->new( year => 2003, month => 1, day => 1 ) ->strftime('%V'), '01', '%V is 01' ); } ); subtest( '%% and %{method}', sub { my $dt = DateTime->new( year => 2004, month => 8, day => 16, hour => 15, minute => 30, nanosecond => 123456789, locale => 'en', ); # Should print '%{day_name}', prints '30onday'! is( $dt->strftime('%%{day_name}%n'), "%{day_name}\n", '%%{day_name}%n bug' ); # Should print '%6N', prints '123456' is( $dt->strftime('%%6N%n'), "%6N\n", '%%6N%n bug' ); } ); subtest( 'nanosecond formatting', sub { subtest( 'nanosecond floating point rounding', sub { # Internally this becomes 119999885 nanoseconds (floating point math is awesome) my $epoch = 1297777805.12; my $dt = DateTime->from_epoch( epoch => $epoch ); my @vals = ( 1, 12, 120, 1200, 12000, 120000, 1200000, 12000000, 120000000, 1200000000, ); my $x = 1; for my $val (@vals) { my $spec = '%' . $x++ . 'N'; is( $dt->strftime($spec), $val, "strftime($spec) for $epoch == $val" ); } } ); subtest( 'nanosecond rounding in strftime', sub { my $dt = DateTime->new( 'year' => 1999, month => 9, day => 7, hour => 13, minute => 2, second => 42, nanosecond => 12345678, ); my %tests = ( '%N' => '012345678', '%3N' => '012', '%6N' => '012345', '%10N' => '0123456780', ); for my $fmt ( sort keys %tests ) { is( $dt->strftime($fmt), $tests{$fmt}, "$fmt is $tests{$fmt}" ); } } ); } ); subtest( '0 nanoseconds', sub { my $dt = DateTime->new( year => 2011 ); for my $i ( 1 .. 9 ) { my $spec = '%' . $i . 'N'; my $expect = '0' x $i; is( $dt->strftime($spec), $expect, "strftime $spec with 0 nanoseconds" ); } } ); subtest( 'week-year formatting', sub { my $dt = DateTime->new( 'year' => 2012, month => 1, day => 1 ); subtest( $dt->ymd, sub { my %tests = ( '%U' => '01', '%W' => '00', '%j' => '001', ); for my $fmt ( sort keys %tests ) { is( $dt->strftime($fmt), $tests{$fmt}, "$fmt is $tests{$fmt}" ); } } ); $dt = DateTime->new( 'year' => 2012, month => 1, day => 10 ); subtest( $dt->ymd, sub { my %tests = ( '%U' => '02', '%W' => '02', '%j' => '010', ); for my $fmt ( sort keys %tests ) { is( $dt->strftime($fmt), $tests{$fmt}, "$fmt is $tests{$fmt}" ); } } ); } ); done_testing(); sub test_strftime_for_locale { my $locale = shift; my $tests = shift; my $dt = DateTime->new( year => 1999, month => 9, day => 7, hour => 13, minute => 2, second => 42, nanosecond => 123456789, time_zone => 'UTC', locale => $locale, ); subtest( $locale, sub { for my $fmt ( sort keys %{$tests} ) { is( $dt->strftime($fmt), $tests->{$fmt}, "$fmt is $tests->{$fmt}" ); } } ); } sub en_tests { my $en_locale = DateTime::Locale->load('en-US'); my $c_format = $en_locale->datetime_format; $c_format =~ s/\{1\}/$en_locale->month_format_abbreviated->[8] . ' 7, 1999'/e; $c_format =~ s/\{0\}/'1:02:42 ' . $en_locale->am_pm_abbreviated->[1]/e; return { '%%' => '%', '%a' => $en_locale->day_format_abbreviated->[1], '%A' => $en_locale->day_format_wide->[1], '%b' => $en_locale->month_format_abbreviated->[8], '%B' => $en_locale->month_format_wide->[8], '%C' => '19', '%d' => '07', '%e' => ' 7', '%D' => '09/07/99', '%h' => $en_locale->month_format_abbreviated->[8], '%H' => '13', '%I' => '01', '%j' => '250', '%k' => '13', '%l' => ' 1', '%m' => '09', '%M' => '02', '%N' => '123456789', '%3N' => '123', '%6N' => '123456', '%10N' => '1234567890', '%p' => $en_locale->am_pm_abbreviated->[1], '%r' => '01:02:42 ' . $en_locale->am_pm_abbreviated->[1], '%R' => '13:02', '%s' => '936709362', '%S' => '42', '%T' => '13:02:42', '%U' => '36', '%V' => '36', '%w' => '2', '%W' => '36', '%y' => '99', '%Y' => '1999', '%Z' => 'UTC', '%z' => '+0000', '%E' => '%E', '%{foobar}' => '%{foobar}', '%{month}' => '9', '%{year}' => '1999', '%x' => $en_locale->month_format_abbreviated->[8] . ' 7, 1999', '%X' => '1:02:42 ' . $en_locale->am_pm_abbreviated->[1], '%c' => $c_format, }; } sub de_tests { my $de_locale = DateTime::Locale->load('de'); return { '%%' => '%', '%a' => $de_locale->day_format_abbreviated->[1], '%A' => $de_locale->day_format_wide->[1], '%b' => $de_locale->month_format_abbreviated->[8], '%B' => $de_locale->month_format_wide->[8], '%C' => '19', '%d' => '07', '%e' => ' 7', '%D' => '09/07/99', '%b' => $de_locale->month_format_abbreviated->[8], '%H' => '13', '%I' => '01', '%j' => '250', '%k' => '13', '%l' => ' 1', '%m' => '09', '%M' => '02', '%p' => $de_locale->am_pm_abbreviated->[1], '%r' => '01:02:42 ' . $de_locale->am_pm_abbreviated->[1], '%R' => '13:02', '%s' => '936709362', '%S' => '42', '%T' => '13:02:42', '%U' => '36', '%V' => '36', '%w' => '2', '%W' => '36', '%y' => '99', '%Y' => '1999', '%Z' => 'UTC', '%z' => '+0000', '%{month}' => '9', '%{year}' => '1999', }; } sub it_tests { my $it_locale = DateTime::Locale->load('it'); return { '%%' => '%', '%a' => $it_locale->day_format_abbreviated->[1], '%A' => $it_locale->day_format_wide->[1], '%b' => $it_locale->month_format_abbreviated->[8], '%B' => $it_locale->month_format_wide->[8], '%C' => '19', '%d' => '07', '%e' => ' 7', '%D' => '09/07/99', '%b' => $it_locale->month_format_abbreviated->[8], '%H' => '13', '%I' => '01', '%j' => '250', '%k' => '13', '%l' => ' 1', '%m' => '09', '%M' => '02', '%p' => $it_locale->am_pm_abbreviated->[1], '%r' => '01:02:42 ' . $it_locale->am_pm_abbreviated->[1], '%R' => '13:02', '%s' => '936709362', '%S' => '42', '%T' => '13:02:42', '%U' => '36', '%V' => '36', '%w' => '2', '%W' => '36', '%y' => '99', '%Y' => '1999', '%Z' => 'UTC', '%z' => '+0000', '%{month}' => '9', '%{year}' => '1999', }; } DateTime-1.46/t/16truncate.t0000644000175000017500000002037413240151623015427 0ustar autarchautarch## no critic (Modules::ProhibitExcessMainComplexity) use strict; use warnings; use Test::Fatal; use Test::More 0.88; use DateTime; use Try::Tiny; my %vals = ( year => 50, month => 3, day => 15, hour => 10, minute => 55, second => 17, nanosecond => 1234, ); { my $dt = DateTime->new(%vals); $dt->truncate( to => 'second' ); foreach my $f (qw( year month day hour minute second )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new(%vals); $dt->truncate( to => 'minute' ); foreach my $f (qw( year month day hour minute )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( second nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new(%vals); $dt->truncate( to => 'hour' ); foreach my $f (qw( year month day hour )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( minute second nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new(%vals); $dt->truncate( to => 'day' ); foreach my $f (qw( year month day )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( hour minute second nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new(%vals); $dt->truncate( to => 'month' ); foreach my $f (qw( year month )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( day )) { is( $dt->$f(), 1, "$f should be 1" ); } foreach my $f (qw( hour minute second nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new(%vals); $dt->truncate( to => 'year' ); foreach my $f (qw( year )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( month day )) { is( $dt->$f(), 1, "$f should be 1" ); } foreach my $f (qw( hour minute second nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new( year => 2003, month => 11, day => 17 ); for ( 1 .. 6 ) { my $trunc = $dt->clone->add( days => $_ )->truncate( to => 'week' ); is( $trunc->day, 17, 'truncate to week should always truncate to monday of week' ); } { my $trunc = $dt->clone->add( days => 7 )->truncate( to => 'week' ); is( $trunc->day, 24, 'truncate to week should always truncate to monday of week' ); } } { my $dt = DateTime->new( year => 2003, month => 10, day => 2 ) ->truncate( to => 'week' ); is( $dt->year, 2003, 'truncation to week across month boundary' ); is( $dt->month, 9, 'truncation to week across month boundary' ); is( $dt->day, 29, 'truncation to week across month boundary' ); } { my $dt = DateTime->new( year => 2013, month => 12, day => 16, locale => 'fr_FR' ); for ( 1 .. 6 ) { my $trunc = $dt->clone->add( days => $_ )->truncate( to => 'local_week' ); is( $trunc->day, 16, 'truncate to local_week returns correct date - locale start is Monday' ); } { my $trunc = $dt->clone->add( days => 7 )->truncate( to => 'local_week' ); is( $trunc->day, 23, 'truncate to local_week returns correct date - locale start is Monday' ); } } { my $dt = DateTime->new( year => 2013, month => 11, day => 2, locale => 'fr_FR' )->truncate( to => 'local_week' ); is( $dt->year, 2013, 'truncation to local_week across month boundary - locale start is Monday' ); is( $dt->month, 10, 'truncation to local_week across month boundary - locale start is Monday' ); is( $dt->day, 28, 'truncation to local_week across month boundary - locale start is Monday' ); } { my $dt = DateTime->new( year => 2013, month => 12, day => 15, locale => 'en_US' ); for ( 1 .. 6 ) { my $trunc = $dt->clone->add( days => $_ )->truncate( to => 'local_week' ); is( $trunc->day, 15, 'truncate to local_week returns correct date - locale start is Sunday' ); } { my $trunc = $dt->clone->add( days => 7 )->truncate( to => 'local_week' ); is( $trunc->day, 22, 'truncate to local_week returns correct date - locale start is Sunday' ); } } { my $dt = DateTime->new( year => 2013, month => 11, day => 2, locale => 'en_US' )->truncate( to => 'local_week' ); is( $dt->year, 2013, 'truncation to local_week across month boundary - locale start is Sunday' ); is( $dt->month, 10, 'truncation to local_week across month boundary - locale start is Sunday' ); is( $dt->day, 27, 'truncation to local_week across month boundary - locale start is Sunday' ); } { my %months_to_quarter = ( 1 => 1, 2 => 1, 3 => 1, 4 => 4, 5 => 4, 6 => 4, 7 => 7, 8 => 7, 9 => 7, 10 => 10, 11 => 10, 12 => 10, ); for my $year ( -1, 100, 2016 ) { for my $month ( sort keys %months_to_quarter ) { for my $day ( 1, 15, 27 ) { my $dt = DateTime->new( year => $year, month => $month, day => $day, ); subtest( 'truncate to quarter - ' . $dt->ymd, sub { $dt->truncate( to => 'quarter' ); is( $dt->year, $year, 'year is unchanged' ); is( $dt->month, $months_to_quarter{$month}, "month $month becomes month $months_to_quarter{$month}" ); is( $dt->day, 1, 'day is always 1' ); is( $dt->hour, 0, 'hour is always 0' ); is( $dt->minute, 0, 'minute is always 0' ); is( $dt->second, 0, 'second is always 0' ); is( $dt->nanosecond, 0, 'nanosecond is always 0' ); } ); } } } } { my $dt = DateTime->new(%vals); for my $bad (qw( seconds minutes year_foo month_bar )) { like( exception { $dt->truncate( to => $bad ) }, qr/Validation failed for type named TruncationLevel/, "bad truncate parameter ($bad) throws an error" ); } } { my $dt = DateTime->new( year => 2010, month => 3, day => 25, hour => 1, minute => 5, time_zone => 'Asia/Tehran', ); is( $dt->day_of_week(), 4, 'day of week is Thursday' ); my $error; try { $dt->truncate( to => 'week' ); } catch { $error = $_; }; like( $error, qr/Invalid local time for date/, 'truncate operation threw an error because of an invalid local datetime' ); is( $dt->day_of_week(), 4, 'day of week does not change after failed truncate() call' ); } done_testing(); DateTime-1.46/t/04epoch.t0000644000175000017500000001264613240151623014700 0ustar autarchautarchuse strict; use warnings; use Test::More; use Test::Fatal; use DateTime; { # Tests creating objects from epoch time my $t1 = DateTime->from_epoch( epoch => 0 ); is( $t1->epoch, 0, 'epoch should be 0' ); is( $t1->second, 0, 'seconds are correct on epoch 0' ); is( $t1->minute, 0, 'minutes are correct on epoch 0' ); is( $t1->hour, 0, 'hours are correct on epoch 0' ); is( $t1->day, 1, 'days are correct on epoch 0' ); is( $t1->month, 1, 'months are correct on epoch 0' ); is( $t1->year, 1970, 'year is correct on epoch 0' ); } { my $dt = DateTime->from_epoch( epoch => '3600' ); is( $dt->epoch, 3600, 'creation test from epoch = 3600 (compare to epoch)' ); } { # these tests could break if the time changed during the next three lines my $now = time; my $nowtest = DateTime->now(); my $nowtest2 = DateTime->from_epoch( epoch => $now ); is( $nowtest->hour, $nowtest2->hour, 'Hour: Create without args' ); is( $nowtest->month, $nowtest2->month, 'Month : Create without args' ); is( $nowtest->minute, $nowtest2->minute, 'Minute: Create without args' ); } { my $epochtest = DateTime->from_epoch( epoch => '997121000' ); is( $epochtest->epoch, 997121000, 'epoch method returns correct value' ); is( $epochtest->hour, 18, 'hour' ); is( $epochtest->min, 3, 'minute' ); } { my $dt = DateTime->from_epoch( epoch => 3600 ); $dt->set_time_zone('+0100'); is( $dt->epoch, 3600, 'epoch is 3600' ); is( $dt->hour, 2, 'hour is 2' ); } { my $dt = DateTime->new( year => 1970, month => 1, day => 1, hour => 0, time_zone => '-0100', ); is( $dt->epoch, 3600, 'epoch is 3600' ); } { my $dt = DateTime->from_epoch( epoch => 0, time_zone => '-0100', ); is( $dt->offset, -3600, 'offset should be -3600' ); is( $dt->epoch, 0, 'epoch is 0' ); } # Adding/subtracting should affect epoch { my $expected = 1049160602; my $epochtest = DateTime->from_epoch( epoch => $expected ); is( $epochtest->epoch, $expected, "epoch method returns correct value ($expected)" ); is( $epochtest->hour, 1, 'hour' ); is( $epochtest->min, 30, 'minute' ); $epochtest->add( hours => 2 ); $expected += 2 * 60 * 60; is( $epochtest->hour, 3, 'adjusted hour' ); is( $epochtest->epoch, $expected, "epoch method returns correct adjusted value ($expected)" ); } { my $dt = DateTime->from_epoch( epoch => 0.5 ); is( $dt->nanosecond, 500_000_000, 'nanosecond should be 500,000,000 with 0.5 as epoch' ); is( $dt->epoch, 0, 'epoch should be 0' ); is( $dt->hires_epoch, 0.5, 'hires_epoch should be 0.5' ); } { my $dt = DateTime->from_epoch( epoch => -0.5 ); is( $dt->nanosecond, 500_000_000, 'nanosecond should be 500,000,000 with -0.5 as epoch' ); is( $dt->epoch, -1, 'epoch should be -1' ); is( $dt->hires_epoch, -0.5, 'hires_epoch should be -0.5' ); } { my $dt = DateTime->from_epoch( epoch => 1609459199.999999 ); is( $dt->nanosecond, 999999000, 'nanosecond should be 999,999,000 with 1609459199.999999 as epoch' ); is( $dt->epoch, 1609459199, 'epoch should be 1609459199' ); } { my $dt = DateTime->from_epoch( epoch => 0.1234567891 ); is( $dt->nanosecond, 123_457_000, 'nanosecond should be rounded to 123,457,000 when given 0.1234567891' ); } { my $dt = DateTime->from_epoch( epoch => -0.1234567891 ); is( $dt->nanosecond, 876_543_000, 'nanosecond should be rounded to 876,543,000 when given -0.1234567891' ); } { is( DateTime->new( year => 1904 )->epoch, -2082844800, 'epoch should work back to at least 1904' ); my $dt = DateTime->from_epoch( epoch => -2082844800 ); is( $dt->year, 1904, 'year should be 1904' ); is( $dt->month, 1, 'month should be 1904' ); is( $dt->day, 1, 'day should be 1904' ); } { for my $pair ( [ 1 => -62135596800 ], [ 99 => -59042995200 ], [ 100 => -59011459200 ], [ 999 => -30641760000 ], ) { my ( $year, $epoch ) = @{$pair}; is( DateTime->new( year => $year )->epoch, $epoch, "epoch for $year is $epoch" ); } } { package Number::Overloaded; use overload '0+' => sub { $_[0]->{num} }, fallback => 1; sub new { bless { num => $_[1] }, $_[0] } } { my $time = Number::Overloaded->new(12345); my $dt = DateTime->from_epoch( epoch => $time ); is( $dt->epoch, 12345, 'can pass overloaded object to from_epoch' ); $time = Number::Overloaded->new(12345.1234); $dt = DateTime->from_epoch( epoch => $time ); is( $dt->epoch, 12345, 'decimal epoch in overloaded object' ); } { my $time = Number::Overloaded->new(-12345); my $dt = DateTime->from_epoch( epoch => $time ); is( $dt->epoch, -12345, 'negative epoch in overloaded object' ); } { my @tests = ( 'asldkjlkjd', '1234 foo', 'adlkj 1234', ); for my $test (@tests) { like( exception { DateTime->from_epoch( epoch => $test ) }, qr/Validation failed for type named Num/, qq{'$test' is not a valid epoch value} ); } } done_testing(); DateTime-1.46/t/39no-so.t0000644000175000017500000000141013240151623014630 0ustar autarchautarch# no pp test # HARNESS-NO-PRELOAD use strict; use warnings; use Test::Fatal; use Test::More; ## no critic (TestingAndDebugging::ProhibitNoWarnings) no warnings 'once', 'redefine'; require XSLoader; my $orig = \&XSLoader::load; my $sub = sub { if ( defined $_[0] && $_[0] eq 'DateTime' ) { die q{Can't locate loadable object for module DateTime in @INC}; } else { goto $orig; } }; *XSLoader::load = $sub; is( exception { require DateTime }, undef,, 'No error loading DateTime without DateTime.so file' ); ## no critic (Variables::ProhibitPackageVars) ok( $DateTime::IsPurePerl, '$DateTime::IsPurePerl is true' ); ok( DateTime->new( year => 2005 ), 'can make DateTime object without DateTime.so file' ); done_testing(); DateTime-1.46/t/12week.t0000644000175000017500000000273413240151623014531 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; my @tests = ( [ [ 1964, 12, 31 ], [ 1964, 53 ] ], [ [ 1965, 1, 1 ], [ 1964, 53 ] ], [ [ 1971, 9, 7 ], [ 1971, 36 ] ], [ [ 1971, 10, 25 ], [ 1971, 43 ] ], [ [ 1995, 1, 1 ], [ 1994, 52 ] ], [ [ 1995, 11, 18 ], [ 1995, 46 ] ], [ [ 1995, 12, 31 ], [ 1995, 52 ] ], [ [ 1996, 12, 31 ], [ 1997, 1 ] ], [ [ 2001, 4, 28 ], [ 2001, 17 ] ], [ [ 2001, 8, 2 ], [ 2001, 31 ] ], [ [ 2001, 9, 11 ], [ 2001, 37 ] ], [ [ 2002, 12, 25 ], [ 2002, 52 ] ], [ [ 2002, 12, 31 ], [ 2003, 1 ] ], [ [ 2003, 1, 1 ], [ 2003, 1 ] ], [ [ 2003, 12, 31 ], [ 2004, 1 ] ], [ [ 2004, 1, 1 ], [ 2004, 1 ] ], [ [ 2004, 12, 31 ], [ 2004, 53 ] ], [ [ 2005, 1, 1 ], [ 2004, 53 ] ], [ [ 2005, 12, 31 ], [ 2005, 52 ] ], [ [ 2006, 1, 1 ], [ 2005, 52 ] ], [ [ 2006, 12, 31 ], [ 2006, 52 ] ], [ [ 2007, 1, 1 ], [ 2007, 1 ] ], [ [ 2007, 12, 31 ], [ 2008, 1 ] ], [ [ 2008, 1, 1 ], [ 2008, 1 ] ], [ [ 2008, 12, 31 ], [ 2009, 1 ] ], [ [ 2009, 1, 1 ], [ 2009, 1 ] ], ); foreach my $test (@tests) { my @args = @{ $test->[0] }; my @results = @{ $test->[1] }; my $dt = DateTime->new( year => $args[0], month => $args[1], day => $args[2], time_zone => 'UTC', ); my ( $year, $week ) = $dt->week(); is( "$year-W$week", "$results[0]-W$results[1]", 'week for ' . $dt->ymd ); } done_testing(); DateTime-1.46/t/32leap-second2.t0000644000175000017500000001651413240151623016055 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 59, second => 58, time_zone => '+0100', ); is( $t->second, 58, 'second value for leap second T-2, +0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-2' ); is( $t->{utc_rd_secs}, 86398, 'UTC RD seconds for leap second T-2' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second T-2' ); is( $t->{local_rd_secs}, 3598, 'local RD seconds for leap second T-2' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 59, second => 59, time_zone => '+0100', ); is( $t->second, 59, 'second value for leap second T-1, +0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-1' ); is( $t->{utc_rd_secs}, 86399, 'UTC RD seconds for leap second T-1' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second T-1' ); is( $t->{local_rd_secs}, 3599, 'local RD seconds for leap second T-1' ); } { my $t = eval { DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 59, second => 60, time_zone => '+0100', ); }; ok( !$@, 'constructor for second = 60' ); SKIP: { skip 'constructor failed - no object to test', 5 unless $t; is( $t->second, 60, 'second value for leap second T-0, +0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-0' ); is( $t->{utc_rd_secs}, 86400, 'UTC RD seconds for leap second T-0' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second T-0' ); is( $t->{local_rd_secs}, 3600, 'local RD seconds for leap second T-0' ); } } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 1, minute => 0, second => 0, time_zone => '+0100', ); is( $t->second, 0, 'second value for leap second T+1, +0100' ); is( $t->{utc_rd_days}, 720075, 'UTC RD days for leap second T+1' ); is( $t->{utc_rd_secs}, 0, 'UTC RD seconds for leap second T+1' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second T+1' ); is( $t->{local_rd_secs}, 3601, 'local RD seconds for leap second T+1' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 1, minute => 0, second => 1, time_zone => '+0100', ); is( $t->second, 1, 'second value for leap second T+2, +0100' ); is( $t->{utc_rd_days}, 720075, 'UTC RD days for leap second T+2' ); is( $t->{utc_rd_secs}, 1, 'UTC RD seconds for leap second T+2' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second T+2' ); is( $t->{local_rd_secs}, 3602, 'local RD seconds for leap second T+2' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 23, minute => 59, second => 59, time_zone => '+0100', ); is( $t->second, 59, 'second value for end of leap second day, +0100' ); is( $t->{utc_rd_days}, 720075, 'UTC RD days for end of leap second day' ); is( $t->{utc_rd_secs}, 82799, 'UTC RD seconds for end of leap second day' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second day' ); is( $t->{local_rd_secs}, 86400, 'local RD seconds for end of leap second day' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 22, minute => 59, second => 58, time_zone => '-0100', ); is( $t->second, 58, 'second value for leap second T-2, -0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-2' ); is( $t->{utc_rd_secs}, 86398, 'UTC RD seconds for leap second T-2' ); is( $t->{local_rd_days}, 720074, 'local RD days for leap second T-2' ); is( $t->{local_rd_secs}, 82798, 'local RD seconds for leap second T-2' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 22, minute => 59, second => 59, time_zone => '-0100', ); is( $t->second, 59, 'second value for leap second T-1, -0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-1' ); is( $t->{utc_rd_secs}, 86399, 'UTC RD seconds for leap second T-1' ); is( $t->{local_rd_days}, 720074, 'local RD days for leap second T-1' ); is( $t->{local_rd_secs}, 82799, 'local RD seconds for leap second T-1' ); } { my $t = eval { DateTime->new( year => 1972, month => 6, day => 30, hour => 22, minute => 59, second => 60, time_zone => '-0100', ); }; ok( !$@, 'constructor for second = 60' ); SKIP: { skip 'constructor failed - no object to test', 5 unless $t; is( $t->second, 60, 'second value for leap second T-0, -0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-0' ); is( $t->{utc_rd_secs}, 86400, 'UTC RD seconds for leap second T-0' ); is( $t->{local_rd_days}, 720074, 'local RD days for leap second T-0' ); is( $t->{local_rd_secs}, 82800, 'local RD seconds for leap second T-0' ); } } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 0, second => 0, time_zone => '-0100', ); is( $t->second, 0, 'second value for leap second T+1, -0100' ); is( $t->{utc_rd_days}, 720075, 'UTC RD days for leap second T+1' ); is( $t->{utc_rd_secs}, 0, 'UTC RD seconds for leap second T+1' ); is( $t->{local_rd_days}, 720074, 'local RD days for leap second T+1' ); is( $t->{local_rd_secs}, 82801, 'local RD seconds for leap second T+1' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 0, second => 1, time_zone => '-0100', ); is( $t->second, 1, 'second value for leap second T+2, -0100' ); is( $t->{utc_rd_days}, 720075, 'UTC RD days for leap second T+2' ); is( $t->{utc_rd_secs}, 1, 'UTC RD seconds for leap second T+2' ); is( $t->{local_rd_days}, 720074, 'local RD days for leap second T+2' ); is( $t->{local_rd_secs}, 82802, 'local RD seconds for leap second T+2' ); } done_testing(); DateTime-1.46/t/07compare.t0000644000175000017500000001407713240151623015233 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; my $date1 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); # make sure that comparing to itself eq 0 my $identity = $date1->compare($date2); ok( $identity == 0, 'Identity comparison' ); $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 1, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 second diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 1, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 minute diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 13, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 hour diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 25, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 day diff' ); $date2 = DateTime->new( year => 1997, month => 11, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 month diff' ); $date2 = DateTime->new( year => 1998, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 year diff' ); # $a > $b tests $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 11, minute => 59, second => 59, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 second diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 11, minute => 59, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 minute diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 11, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 hour diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 23, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 day diff' ); $date2 = DateTime->new( year => 1997, month => 9, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 month diff' ); $date2 = DateTime->new( year => 1996, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 year diff' ); my $infinity = DateTime::INFINITY; ok( $date1->compare($infinity) == -1, 'Comparison $a < inf' ); ok( $date1->compare( -$infinity ) == 1, 'Comparison $a > -inf' ); # comparison overloading, and infinity ok( ( $date1 <=> $infinity ) == -1, 'Comparison overload $a <=> inf' ); ok( ( $infinity <=> $date1 ) == 1, 'Comparison overload $inf <=> $a' ); # comparison with floating time { my $dt1 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'America/Chicago' ); my $dt2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'floating' ); is( DateTime->compare( $dt1, $dt2 ), 0, 'Comparison with floating time (cmp)' ); is( ( $dt1 <=> $dt2 ), 0, 'Comparison with floating time (<=>)' ); is( ( $dt1 cmp $dt2 ), 0, 'Comparison with floating time (cmp)' ); is( DateTime->compare_ignore_floating( $dt1, $dt2 ), 1, 'Comparison with floating time (cmp)' ); } # sub-second { my $dt1 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, nanosecond => 100, ); my $dt2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, nanosecond => 200, ); is( DateTime->compare( $dt1, $dt2 ), -1, 'Comparison with floating time (cmp)' ); is( ( $dt1 <=> $dt2 ), -1, 'Comparison with floating time (<=>)' ); is( ( $dt1 cmp $dt2 ), -1, 'Comparison with floating time (cmp)' ); } { my $dt1 = DateTime->new( year => 2000, month => 10, day => 24, hour => 12, minute => 0, second => 0, nanosecond => 10000, ); my $dt2 = DateTime->new( year => 2000, month => 10, day => 24, hour => 12, minute => 0, second => 0, nanosecond => 10000, ); is( DateTime->compare( $dt1, $dt2 ), 0, 'Comparison with floating time (cmp)' ); is( ( $dt1 <=> $dt2 ), 0, 'Comparison with floating time (<=>)' ); is( ( $dt1 cmp $dt2 ), 0, 'Comparison with floating time (cmp)' ); is( DateTime->compare_ignore_floating( $dt1, $dt2 ), 0, 'Comparison with compare_ignore_floating (cmp)' ); } { package DT::Test; sub new { my $class = shift; return bless [@_], $class; } sub utc_rd_values { @{ $_[0] } } } { my $dt = DateTime->new( year => 1950 ); my @values = $dt->utc_rd_values; $values[2] += 50; my $dt_test1 = DT::Test->new(@values); ok( $dt < $dt_test1, 'comparison works across different classes' ); $values[0] -= 1; my $dt_test2 = DT::Test->new(@values); ok( $dt > $dt_test2, 'comparison works across different classes' ); } done_testing(); DateTime-1.46/t/48rt-115983.t0000644000175000017500000000110013240151623014766 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; # The bug here is that if DateTime doesn't clean it's namespace, it ends up # having a catch method that is getting called here and being passed a hashref # containing the return value of $dt->truncate. See # https://rt.cpan.org/Ticket/Display.html?id=115983 my $dt = DateTime->now; like( exception { try { } catch { $dt->truncate( to => 'hour' ); }; }, qr/Can\'t locate object method "catch"/, 'DateTime does not have a catch method' ); done_testing(); DateTime-1.46/t/15jd.t0000644000175000017500000000343313240151623014173 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; # Borrowed from Matt Sergeant's Time::Piece # A table of MJD and components my @mjd = ( '51603.524' => { year => 2000, month => 2, day => 29, hour => 12, minute => 34, second => 56, }, '40598.574' => { year => 1970, month => 1, day => 12, hour => 13, minute => 46, second => 51, }, '52411.140' => { year => 2002, month => 5, day => 17, hour => 3, minute => 21, second => 43, }, '53568.547' => { year => 2005, month => 7, day => 17, hour => 13, minute => 8, second => 23, }, '52295.218' => { year => 2002, month => 1, day => 21, hour => 5, minute => 13, second => 20, }, '52295.399' => { year => 2002, month => 1, day => 21, hour => 9, minute => 35, second => 3, }, # beginning of MJD '0.000' => { year => 1858, month => 11, day => 17, hour => 0, minute => 0, second => 0, }, # beginning of JD '-2400000.500' => { year => -4713, month => 11, day => 24, hour => 12, minute => 0, second => 0, }, ); while ( my ( $mjd, $comps ) = splice @mjd, 0, 2 ) { my $dt = DateTime->new( %$comps, time_zone => 'UTC', ); is( sprintf( '%.3f', $dt->mjd ), $mjd, "MJD should be $mjd" ); my $jd = sprintf( '%.3f', $mjd + 2_400_000.5 ); is( sprintf( '%.3f', $dt->jd ), $jd, "JD should be $jd" ); } done_testing(); DateTime-1.46/t/17set-return.t0000644000175000017500000000174013240151623015707 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; use DateTime::Duration; { my $dt = DateTime->new( year => 2008, month => 2, day => 28 ); my $du = DateTime::Duration->new( years => 1 ); my $p; $p = $dt->set( year => 1882 ); is( DateTime->compare( $p, $dt ), 0, 'set returns self' ); $p = $dt->set_time_zone('Australia/Sydney'); is( DateTime->compare( $p, $dt ), 0, 'set_time_zone returns self' ); $p = $dt->add_duration($du); is( DateTime->compare( $p, $dt ), 0, 'add_duration returns self' ); $p = $dt->add( years => 2 ); is( DateTime->compare( $p, $dt ), 0, 'add returns self' ); $p = $dt->subtract_duration($du); is( DateTime->compare( $p, $dt ), 0, 'subtract_duration returns self' ); $p = $dt->subtract( years => 3 ); is( DateTime->compare( $p, $dt ), 0, 'subtract returns self' ); $p = $dt->truncate( to => 'day' ); is( DateTime->compare( $p, $dt ), 0, 'truncate returns self' ); } done_testing(); DateTime-1.46/t/37local-add.t0000644000175000017500000001257613240151623015432 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; # These tests should be the final word on dt addition involving a # DST-changing time zone # time addition is "wait X amount of time, then what does the clock # say?" this means it acts on the UTC components. { my $dt = DateTime->new( year => 2003, month => 4, day => 6, time_zone => 'America/Chicago', ); $dt->add( hours => 1 ); is( $dt->datetime, '2003-04-06T01:00:00', 'add one hour to midnight, get 1 am' ); is( exception { $dt->add( hours => 1 ) }, undef, 'no error adding 1 hour just before DST leap forward' ); is( $dt->datetime, '2003-04-06T03:00:00', 'add one hour to 1 am, get 3 am' ); $dt->subtract( hours => 1 ); is( $dt->datetime, '2003-04-06T01:00:00', 'subtract one hour from 3 am, get 1 am' ); $dt->subtract( hours => 1 ); is( $dt->datetime, '2003-04-06T00:00:00', 'subtract one hour from 1 am, get midnight' ); } { my $dt = DateTime->new( year => 2003, month => 10, day => 26, time_zone => 'America/Chicago', ); $dt->add( hours => 1 ); is( $dt->datetime, '2003-10-26T01:00:00', 'add one hour to midnight, get 1 am' ); $dt->add( hours => 1 ); is( $dt->datetime, '2003-10-26T01:00:00', 'add one hour to 1 am, get 1 am (again)' ); $dt->add( hours => 1 ); is( $dt->datetime, '2003-10-26T02:00:00', 'add one hour to 1 am (2nd time), get 2 am' ); $dt->subtract( hours => 1 ); is( $dt->datetime, '2003-10-26T01:00:00', 'subtract 1 hour from 2 am, get 1 am' ); $dt->subtract( hours => 1 ); is( $dt->datetime, '2003-10-26T01:00:00', 'subtract 1 hour from 1 am, get 1 am (again)' ); $dt->subtract( hours => 1 ); is( $dt->datetime, '2003-10-26T00:00:00', 'subtract 1 hour from 1 am (2nd), get midnight' ); } # date addition is "leave the clock alone, just change the date # portion". this means it acts on local components { my $dt = DateTime->new( year => 2003, month => 4, day => 6, time_zone => 'America/Chicago', ); $dt->add( days => 1 ); is( $dt->datetime, '2003-04-07T00:00:00', 'add 1 day at midnight, same clock time' ); $dt->add( months => 7 ); is( $dt->datetime, '2003-11-07T00:00:00', 'add 7 months at midnight, same clock time' ); $dt->subtract( months => 7 ); is( $dt->datetime, '2003-04-07T00:00:00', 'subtract 7 months at midnight, same clock time' ); $dt->subtract( days => 1 ); is( $dt->datetime, '2003-04-06T00:00:00', 'subtract 1 day at midnight, same clock time' ); } { my $dt = DateTime->new( year => 2003, month => 10, day => 26, time_zone => 'America/Chicago', ); $dt->add( days => 1 ); is( $dt->datetime, '2003-10-27T00:00:00', 'add 1 day at midnight, get midnight' ); $dt->add( months => 7 ); is( $dt->datetime, '2004-05-27T00:00:00', 'add 7 months at midnight, get midnight' ); $dt->subtract( months => 7 ); is( $dt->datetime, '2003-10-27T00:00:00', 'subtract 7 months at midnight, get midnight' ); $dt->subtract( days => 1 ); is( $dt->datetime, '2003-10-26T00:00:00', 'subtract 1 day at midnight, get midnight' ); } # date and time addition in one call is still two separate operations. # First we do date, then time. { my $dt = DateTime->new( year => 2003, month => 4, day => 5, time_zone => 'America/Chicago', ); $dt->add( days => 1, hours => 2 ); is( $dt->datetime, '2003-04-06T03:00:00', 'add one day & 2 hours from midnight, get 3 am' ); # !!! - not reversible this way - needs some good docs my $dt1 = $dt->clone->subtract( days => 1, hours => 2 ); is( $dt1->datetime, '2003-04-05T01:00:00', 'subtract one day & 2 hours from 3 am, get 1 am' ); # is reversible this way - also needs docs my $dt2 = $dt->clone->subtract( hours => 2 )->subtract( days => 1 ); is( $dt2->datetime, '2003-04-05T00:00:00', 'subtract 2 hours and then one day from 3 am, get midnight' ); } { my $dt = DateTime->new( year => 2003, month => 10, day => 25, time_zone => 'America/Chicago', ); $dt->add( days => 1, hours => 2 ); is( $dt->datetime, '2003-10-26T01:00:00', 'add one day & 2 hours from midnight, get 1 am' ); my $dt1 = $dt->clone->subtract( days => 1, hours => 2 ); is( $dt1->datetime, '2003-10-24T23:00:00', 'add one day & 2 hours from midnight, get 11 pm' ); my $dt2 = $dt->clone->subtract( hours => 2 )->subtract( days => 1 ); is( $dt2->datetime, '2003-10-25T00:00:00', 'subtract 2 hours and then one day from 3 am, get midnight' ); } # an example from the docs { my $dt = DateTime->new( year => 2003, month => 4, day => 5, hour => 2, time_zone => 'America/Chicago', ); $dt->add( hours => 24 ); is( $dt->datetime, '2003-04-06T03:00:00', 'datetime after adding 24 hours is 2003-04-06T03:00:00' ); } done_testing(); DateTime-1.46/t/44set-formatter.t0000644000175000017500000000130313240151623016366 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; use overload; my $dt = DateTime->now; like( exception { $dt->set_formatter('Invalid::Formatter') }, qr/\QValidation failed for type named Maybe[Formatter]/, 'set_format is validated' ); SKIP: { ## no critic (BuiltinFunctions::ProhibitStringyEval) skip 'This test requires DateTime::Format::Strptime 1.2000+', 1 unless eval 'use DateTime::Format::Strptime 1.2000; 1;'; my $formatter = DateTime::Format::Strptime->new( pattern => '%Y%m%d %T', ); is( $dt->set_formatter($formatter), $dt, 'set_formatter returns the datetime object' ); } done_testing(); DateTime-1.46/t/47default-time-zone.t0000644000175000017500000000542113240151623017133 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 2000, month => 2, day => 21 ); is( $dt->time_zone->name, 'floating', 'Time zones for new DateTime objects should default to floating' ); is( DateTime->last_day_of_month( year => 2000, month => 2 ) ->time_zone->name, 'floating', 'last_day_of_month time zone also should default to floating' ); is( DateTime->from_day_of_year( year => 2000, day_of_year => 212 ) ->time_zone->name, 'floating', 'from_day_of_year time zone also should default to floating' ); is( DateTime->now->time_zone->name, 'UTC', '... except for constructors which assume UTC' ); is( DateTime->from_epoch( epoch => time() )->time_zone->name, 'UTC', '... except for constructors which assume UTC' ); } { my $dt1 = DateTime->new( year => 1970, hour => 1, nanosecond => 100 ); my $dt2 = DateTime->from_object( object => $dt1 ); is( $dt2->time_zone->name, 'floating', 'Copying DateTime objects from other DateTime objects should retain the timezone' ); } { my $dt = DateTime->new( year => 2000, month => 2, day => 21 ); local $ENV{PERL_DATETIME_DEFAULT_TZ} = 'America/Los_Angeles'; is( $dt->time_zone->name, 'floating', 'Setting PERL_DATETIME_DEFAULT_TZ env should not impact existing objects' ); $dt = DateTime->new( year => 2000, month => 2, day => 21 ); is( $dt->time_zone->name, $ENV{PERL_DATETIME_DEFAULT_TZ}, '... but new objects should no longer default to the floating time zone' ); is( DateTime->last_day_of_month( year => 2000, month => 2 ) ->time_zone->name, $ENV{PERL_DATETIME_DEFAULT_TZ}, 'last_day_of_month time zone also should default to floating' ); is( DateTime->from_day_of_year( year => 2000, day_of_year => 212 ) ->time_zone->name, $ENV{PERL_DATETIME_DEFAULT_TZ}, 'from_day_of_year time zone also should default to floating' ); is( DateTime->now->time_zone->name, 'UTC', '... and constructors which assume UTC should remain unchanged' ); my $dt1 = DateTime->new( year => 1970, hour => 1, nanosecond => 100 ); my $dt2 = DateTime->from_object( object => $dt1 ); is( $dt2->time_zone->name, $ENV{PERL_DATETIME_DEFAULT_TZ}, 'Copying DateTime objects from other DateTime objects should retain the timezone' ); } { my $dt = DateTime->new( year => 2000, month => 2, day => 21 ); is( $dt->time_zone->name, 'floating', 'Default time zone should revert to "floating" when PERL_DATETIME_DEFAULT_TZ no longer set' ); } done_testing(); DateTime-1.46/t/22from-doy.t0000644000175000017500000000313513240151623015327 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; my @last_day = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); my @leap_last_day = @last_day; $leap_last_day[1]++; { my $doy = 15; foreach my $month ( 1 .. 12 ) { $doy += $last_day[ $month - 2 ] if $month > 1; my $dt = DateTime->from_day_of_year( year => 2001, day_of_year => $doy, time_zone => 'UTC', ); is( $dt->year, 2001, 'check year' ); is( $dt->month, $month, 'check month' ); is( $dt->day, 15, 'check day' ); is( $dt->day_of_year, $doy, 'check day of year' ); } } { my $doy = 15; foreach my $month ( 1 .. 12 ) { $doy += $leap_last_day[ $month - 2 ] if $month > 1; my $dt = DateTime->from_day_of_year( year => 2004, day_of_year => $doy, time_zone => 'UTC', ); is( $dt->year, 2004, 'check year' ); is( $dt->month, $month, 'check month' ); is( $dt->day, 15, 'check day' ); is( $dt->day_of_year, $doy, 'check day of year' ); } } { like( exception { DateTime->from_day_of_year( year => 2001, day_of_year => 366 ) }, qr/2001 is not a leap year/, 'Cannot give day of year 366 in non-leap years' ); is( exception { DateTime->from_day_of_year( year => 2004, day_of_year => 366 ) }, undef, 'Day of year 366 should work in leap years' ); } done_testing(); DateTime-1.46/t/40leap-years.t0000644000175000017500000000050313240151623015631 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; ## no critic (Subroutines::ProtectPrivateSubs) for my $y ( 0, 400, 2000, 2004 ) { ok( DateTime->_is_leap_year($y), "$y is a leap year" ); } for my $y ( 1, 100, 1900, 2133 ) { ok( !DateTime->_is_leap_year($y), "$y is not a leap year" ); } done_testing(); DateTime-1.46/t/02last-day.t0000644000175000017500000000224513240151623015310 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; my @last_day = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); my @leap_last_day = @last_day; $leap_last_day[1]++; foreach my $month ( 1 .. 12 ) { my $dt = DateTime->last_day_of_month( year => 2001, month => $month, time_zone => 'UTC', ); is( $dt->year, 2001, 'check year' ); is( $dt->month, $month, 'check month' ); is( $dt->day, $last_day[ $month - 1 ], 'check day' ); } foreach my $month ( 1 .. 12 ) { my $dt = DateTime->last_day_of_month( year => 2004, month => $month, time_zone => 'UTC', ); is( $dt->year, 2004, 'check year' ); is( $dt->month, $month, 'check month' ); is( $dt->day, $leap_last_day[ $month - 1 ], 'check day' ); } { is( exception { DateTime->last_day_of_month( year => 2000, month => 1, nanosecond => 2000 ); }, undef, 'last_day_of_month should accept nanosecond' ); } done_testing(); DateTime-1.46/t/34set-tz.t0000644000175000017500000000501713240151623015025 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More 0.88; use DateTime; # These tests are for a bug related to a bad interaction between the # horrid ->_handle_offset_modifier method and calling ->set_time_zone # on a real Olson time zone. When _handle_offset_modifier was called # from set_time_zone, it tried calling ->_offset_for_local_datetime, # which was bogus, because at that point it doesn't know the local # date time any more, only UTC. # # The fix is to have ->_handle_offset_modifier call ->offset when it # knows that UTC is valid, which is determined by an arg to # ->_handle_offset_modifier # These tests come from one of the zdump-generated test files in # DT::TZ { my $dt = DateTime->new( year => 1922, month => 8, day => 31, hour => 23, minute => 59, second => 59, time_zone => 'UTC', ); $dt->set_time_zone('Africa/Accra'); is( $dt->year, 1922, 'local year should be 1922 (1922-08-31 23:59:59)' ); is( $dt->month, 8, 'local month should be 8 (1922-08-31 23:59:59)' ); is( $dt->day, 31, 'local day should be 31 (1922-08-31 23:59:59)' ); is( $dt->hour, 23, 'local hour should be 23 (1922-08-31 23:59:59)' ); is( $dt->minute, 59, 'local minute should be 59 (1922-08-31 23:59:59)' ); is( $dt->second, 59, 'local second should be 59 (1922-08-31 23:59:59)' ); is( $dt->is_dst, 0, 'is_dst should be 0 (1922-08-31 23:59:59)' ); is( $dt->offset, 0, 'offset should be 0 (1922-08-31 23:59:59)' ); is( $dt->time_zone_short_name, 'GMT', 'short name should be GMT (1922-08-31 23:59:59)' ); } { my $dt = DateTime->new( year => 2013, month => 3, day => 10, hour => 2, minute => 4, time_zone => 'floating', ); like( exception { $dt->set_time_zone('America/Los_Angeles') }, qr/\QInvalid local time for date in time zone/, 'got an exception when trying to set time zone when it leads to invalid local time' ); is( $dt->time_zone()->name(), 'floating', 'time zone was not changed after set_time_zone() throws an exception' ); } { my $dt = DateTime->now( time_zone => 'America/Chicago' ); ok( $dt->set_time_zone('America/Chicago'), 'set_time_zone returns object when time zone name is same as current' ); ok( $dt->set_time_zone( $dt->time_zone() ), 'set_time_zone returns object when time zone object is same as current' ); } done_testing(); DateTime-1.46/t/20infinite.t0000644000175000017500000001127613240151623015403 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; use DateTime::Locale; my $pos = DateTime::Infinite::Future->new; my $neg = DateTime::Infinite::Past->new; my $posinf = DateTime::INFINITY; my $neginf = DateTime::NEG_INFINITY; my $nan_string = DateTime::NAN; # infinite date math { ok( $pos->is_infinite, 'positive infinity should be infinite' ); ok( $neg->is_infinite, 'negative infinity should be infinite' ); ok( !$pos->is_finite, 'positive infinity should not be finite' ); ok( !$neg->is_finite, 'negative infinity should not be finite' ); # These methods produce numbers or strings - we want to make sure they all # return Inf or -Inf as expected. my @ification_methods = qw( ymd mdy dmy hms time iso8601 datetime year ce_year month day day_of_week quarter hour hour_1 hour_12 hour_12_0 minute second fractional_second week week_year week_number mjd jd nanosecond millisecond microsecond epoch ); for my $meth (@ification_methods) { is( $pos->$meth, $posinf, "+Infinity $meth returns $posinf" ); is( $neg->$meth, $neginf, "-Infinity $meth returns $neginf" ); } # that's a long time ago! my $long_ago = DateTime->new( year => -100_000 ); ok( $neg < $long_ago, 'negative infinity is really negative' ); my $far_future = DateTime->new( year => 100_000 ); ok( $pos > $far_future, 'positive infinity is really positive' ); ok( $pos > $neg, 'positive infinity is bigger than negative infinity' ); my $pos_dur = $pos - $far_future; ok( $pos_dur->is_positive, 'infinity - normal = infinity' ); my $pos2 = $long_ago + $pos_dur; ok( $pos2 == $pos, 'normal + infinite duration = infinity' ); my $neg_dur = $far_future - $pos; ok( $neg_dur->is_negative, 'normal - infinity = neg infinity' ); my $neg2 = $long_ago + $neg_dur; ok( $neg2 == $neg, 'normal + neg infinite duration = neg infinity' ); my $dur = $pos - $pos; my %deltas = $dur->deltas; my @compare = qw( days seconds nanoseconds ); foreach (@compare) { # NaN != NaN (but should stringify the same) is( $deltas{$_} . q{}, $nan_string, "infinity - infinity = nan ($_)" ); } my $new_pos = $pos->clone->add( days => 10 ); ok( $new_pos == $pos, 'infinity + normal duration = infinity' ); my $new_pos2 = $pos->clone->subtract( days => 10 ); ok( $new_pos2 == $pos, 'infinity - normal duration = infinity' ); ok( $pos == $posinf, 'infinity (datetime) == infinity (number)' ); ok( $neg == $neginf, 'neg infinity (datetime) == neg infinity (number)' ); } # This could vary across platforms my $pos_as_string = $posinf . q{}; my $neg_as_string = $neginf . q{}; # formatting { foreach my $m ( qw( year month day hour minute second microsecond millisecond nanosecond ) ) { is( $pos->$m() . q{}, $pos_as_string, "pos $m is $pos_as_string" ); is( $neg->$m() . q{}, $neg_as_string, "neg $m is $pos_as_string" ); } } { my $now = DateTime->now; is( DateTime->compare( $pos, $now ), 1, 'positive infinite is greater than now' ); is( DateTime->compare( $neg, $now ), -1, 'negative infinite is less than now' ); } { my $now = DateTime->now; my $pos2 = $pos + DateTime::Duration->new( months => 1 ); ok( $pos == $pos2, 'infinity (datetime) == infinity (datetime)' ); } { my $now = DateTime->now; my $neg2 = $neg + DateTime::Duration->new( months => 1 ); ok( $neg == $neg2, '-infinity (datetime) == -infinity (datetime)' ); } { cmp_ok( "$pos", 'eq', $posinf, 'stringified infinity (datetime) eq infinity (number)' ); cmp_ok( "$neg", 'eq', $neginf, 'stringified neg infinity (datetime) eq neg infinity (number)' ); } { is( $pos->day_name(), undef, 'day_name returns undef', ); is( $pos->am_or_pm(), undef, 'am_or_pm returns undef' ); is( $pos->locale()->name(), 'Fake locale for Infinite DateTime objects', 'locale name for fake locale' ); is( $pos->locale()->datetime_format_long(), DateTime::Locale->load('en_US')->datetime_format_long(), 'fake locale returns same format as en_US' ); } done_testing(); DateTime-1.46/t/03components.t0000644000175000017500000003371313240151623015764 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; { my $d = DateTime->new( year => 2001, month => 7, day => 5, hour => 2, minute => 12, second => 50, time_zone => 'UTC', ); is( $d->year, 2001, '->year' ); is( $d->ce_year, 2001, '->ce_year' ); is( $d->month, 7, '->month' ); is( $d->quarter, 3, '->quarter' ); is( $d->month_0, 6, '->month_0' ); is( $d->month_name, 'July', '->month_name' ); is( $d->month_abbr, 'Jul', '->month_abbr' ); is( $d->day_of_month, 5, '->day_of_month' ); is( $d->day_of_month_0, 4, '->day_of_month_0' ); is( $d->day, 5, '->day' ); is( $d->day_0, 4, '->day_0' ); is( $d->mday, 5, '->mday' ); is( $d->mday_0, 4, '->mday_0' ); is( $d->mday, 5, '->mday' ); is( $d->mday_0, 4, '->mday_0' ); is( $d->hour, 2, '->hour' ); is( $d->hour_1, 2, '->hour_1' ); is( $d->hour_12, 2, '->hour_12' ); is( $d->hour_12_0, 2, '->hour_12_0' ); is( $d->minute, 12, '->minute' ); is( $d->min, 12, '->min' ); is( $d->second, 50, '->second' ); is( $d->sec, 50, '->sec' ); is( $d->day_of_year, 186, '->day_of_year' ); is( $d->day_of_year_0, 185, '->day_of_year' ); is( $d->day_of_quarter, 5, '->day_of_quarter' ); is( $d->doq, 5, '->doq' ); is( $d->day_of_quarter_0, 4, '->day_of_quarter_0' ); is( $d->doq_0, 4, '->doq_0' ); is( $d->day_of_week, 4, '->day_of_week' ); is( $d->day_of_week_0, 3, '->day_of_week_0' ); is( $d->week_of_month, 1, '->week_of_month' ); is( $d->weekday_of_month, 1, '->weekday_of_month' ); is( $d->wday, 4, '->wday' ); is( $d->wday_0, 3, '->wday_0' ); is( $d->dow, 4, '->dow' ); is( $d->dow_0, 3, '->dow_0' ); is( $d->day_name, 'Thursday', '->day_name' ); is( $d->day_abbr, 'Thu', '->day_abrr' ); is( $d->ymd, '2001-07-05', '->ymd' ); is( $d->ymd('!'), '2001!07!05', q{->ymd('!')} ); is( $d->date, '2001-07-05', '->date' ); is( $d->date('!'), '2001!07!05', q{->date('!')} ); is( $d->mdy, '07-05-2001', '->mdy' ); is( $d->mdy('!'), '07!05!2001', q{->mdy('!')} ); is( $d->dmy, '05-07-2001', '->dmy' ); is( $d->dmy('!'), '05!07!2001', q{->dmy('!')} ); is( $d->hms, '02:12:50', '->hms' ); is( $d->hms('!'), '02!12!50', q{->hms('!')} ); is( $d->time, '02:12:50', '->hms' ); is( $d->time('!'), '02!12!50', q{->time('!')} ); is( $d->datetime, '2001-07-05T02:12:50', '->datetime' ); is( $d->datetime(q{ }), '2001-07-05 02:12:50', q{->datetime(q{ }} ); is( $d->iso8601, '2001-07-05T02:12:50', '->iso8601' ); is( $d->iso8601(q{ }), '2001-07-05T02:12:50', '->iso8601 ignores arguments' ); ok( !$d->is_leap_year, '->is_leap_year' ); ok( !$d->is_last_day_of_month, '->is_last_day_of_month' ); is( $d->month_length, 31, '->month_length' ); is( $d->quarter_length, 92, '->quarter_length' ); is( $d->year_length, 365, '->year_length' ); is( $d->era_abbr, 'AD', '->era_abbr' ); is( $d->era, $d->era_abbr, '->era (deprecated)' ); is( $d->era_name, 'Anno Domini', '->era_abbr' ); is( $d->quarter_abbr, 'Q3', '->quarter_abbr' ); is( $d->quarter_name, '3rd quarter', '->quarter_name' ); } { my $leap_d = DateTime->new( year => 2004, month => 7, day => 5, hour => 2, minute => 12, second => 50, time_zone => 'UTC', ); ok( $leap_d->is_leap_year, '->is_leap_year' ); is( $leap_d->year_length, 366, '->year_length' ); } { my @tests = ( { year => 2017, month => 8, day => 19, expect => 0 }, { year => 2017, month => 8, day => 31, expect => 1 }, { year => 2017, month => 2, day => 28, expect => 1 }, { year => 2016, month => 2, day => 28, expect => 0 }, ); for my $t (@tests) { my $expect = delete $t->{expect}; my $dt = DateTime->new($t); my $is = $dt->is_last_day_of_month; ok( ( $expect ? $is : !$is ), '->is_last_day_of_month' ); } } { my @tests = ( { year => 2016, month => 2, day => 1, expect => 29 }, { year => 2017, month => 2, day => 1, expect => 28 }, ); for my $t (@tests) { my $expect = delete $t->{expect}; my $dt = DateTime->new($t); is( $dt->month_length, $expect, '->month_length' ); } } { my $sunday = DateTime->new( year => 2003, month => 1, day => 26, time_zone => 'UTC', ); is( $sunday->day_of_week, 7, 'Sunday is day 7' ); } { my $monday = DateTime->new( year => 2003, month => 1, day => 27, time_zone => 'UTC', ); is( $monday->day_of_week, 1, 'Monday is day 1' ); } { # time zone offset should not affect the values returned my $d = DateTime->new( year => 2001, month => 7, day => 5, hour => 2, minute => 12, second => 50, time_zone => '-0124', ); is( $d->year, 2001, '->year' ); is( $d->ce_year, 2001, '->ce_year' ); is( $d->month, 7, '->month' ); is( $d->day_of_month, 5, '->day_of_month' ); is( $d->hour, 2, '->hour' ); is( $d->hour_1, 2, '->hour_1' ); is( $d->minute, 12, '->minute' ); is( $d->second, 50, '->second' ); } { my $dt0 = DateTime->new( year => 1, time_zone => 'UTC' ); is( $dt0->year, 1, 'year 1 is year 1' ); is( $dt0->ce_year, 1, 'ce_year 1 is year 1' ); is( $dt0->era_abbr, 'AD', 'era is AD' ); is( $dt0->year_with_era, '1AD', 'year_with_era is 1AD' ); is( $dt0->christian_era, 'AD', 'christian_era is AD' ); is( $dt0->year_with_christian_era, '1AD', 'year_with_christian_era is 1AD' ); is( $dt0->secular_era, 'CE', 'secular_era is CE' ); is( $dt0->year_with_secular_era, '1CE', 'year_with_secular_era is 1CE' ); $dt0->subtract( years => 1 ); is( $dt0->year, 0, 'year 1 minus 1 is year 0' ); is( $dt0->ce_year, -1, 'ce_year 1 minus 1 is year -1' ); is( $dt0->era_abbr, 'BC', 'era is BC' ); is( $dt0->year_with_era, '1BC', 'year_with_era is 1BC' ); is( $dt0->christian_era, 'BC', 'christian_era is BC' ); is( $dt0->year_with_christian_era, '1BC', 'year_with_christian_era is 1BC' ); is( $dt0->secular_era, 'BCE', 'secular_era is BCE' ); is( $dt0->year_with_secular_era, '1BCE', 'year_with_secular_era is 1BCE' ); } { my $dt_neg = DateTime->new( year => -10, time_zone => 'UTC', ); is( $dt_neg->year, -10, 'Year -10 is -10' ); is( $dt_neg->ce_year, -11, 'year -10 is ce_year -11' ); my $dt1 = $dt_neg + DateTime::Duration->new( years => 10 ); is( $dt1->year, 0, 'year is 0 after adding ten years to year -10' ); is( $dt1->ce_year, -1, 'ce_year is -1 after adding ten years to year -10' ); } { my $dt = DateTime->new( year => 50, month => 2, hour => 3, minute => 20, second => 5, time_zone => 'UTC', ); is( $dt->ymd('%s'), '0050%s02%s01', 'use %s as separator in ymd' ); is( $dt->mdy('%s'), '02%s01%s0050', 'use %s as separator in mdy' ); is( $dt->dmy('%s'), '01%s02%s0050', 'use %s as separator in dmy' ); is( $dt->hms('%s'), '03%s20%s05', 'use %s as separator in hms' ); } # test doy in leap year { my $dt = DateTime->new( year => 2000, month => 1, day => 5, time_zone => 'UTC', ); is( $dt->day_of_year, 5, 'doy for 2000-01-05 should be 5' ); is( $dt->day_of_year_0, 4, 'doy_0 for 2000-01-05 should be 4' ); } { my $dt = DateTime->new( year => 2000, month => 2, day => 29, time_zone => 'UTC', ); is( $dt->day_of_year, 60, 'doy for 2000-02-29 should be 60' ); is( $dt->day_of_year_0, 59, 'doy_0 for 2000-02-29 should be 59' ); } { my $dt = DateTime->new( year => -6, month => 2, day => 25, time_zone => 'UTC', ); is( $dt->ymd, '-0006-02-25', 'ymd is -0006-02-25' ); is( $dt->iso8601, '-0006-02-25T00:00:00', 'iso8601 is -0005-02-25T00:00:00' ); is( $dt->year, -6, 'year is -6' ); is( $dt->ce_year, -7, 'ce_year is -7' ); } { my $dt = DateTime->new( year => 1995, month => 2, day => 1 ); is( $dt->quarter, 1, '->quarter is 1' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 90, '->quarter_length' ); } { my $dt = DateTime->new( year => 1995, month => 5, day => 1 ); is( $dt->quarter, 2, '->quarter is 2' ); is( $dt->day_of_quarter, 31, '->day_of_quarter' ); is( $dt->quarter_length, 91, '->quarter_length' ); } { my $dt = DateTime->new( year => 1995, month => 8, day => 1 ); is( $dt->quarter, 3, '->quarter is 3' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 92, '->quarter_length' ); } { my $dt = DateTime->new( year => 1995, month => 11, day => 1 ); is( $dt->quarter, 4, '->quarter is 4' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 92, '->quarter_length' ); } { my $dt = DateTime->new( year => 1996, month => 2, day => 1 ); is( $dt->quarter, 1, '->quarter is 1' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 91, '->quarter_length' ); } { my $dt = DateTime->new( year => 1996, month => 5, day => 1 ); is( $dt->quarter, 2, '->quarter is 2' ); is( $dt->day_of_quarter, 31, '->day_of_quarter' ); is( $dt->quarter_length, 91, '->quarter_length' ); } { my $dt = DateTime->new( year => 1996, month => 8, day => 1 ); is( $dt->quarter, 3, '->quarter is 3' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 92, '->quarter_length' ); } { my $dt = DateTime->new( year => 1996, month => 11, day => 1 ); is( $dt->quarter, 4, '->quarter is 4' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 92, '->quarter_length' ); } # nano, micro, and milli seconds { my $dt = DateTime->new( year => 1996, nanosecond => 500_000_000 ); is( $dt->nanosecond, 500_000_000, 'nanosecond is 500,000,000' ); is( $dt->microsecond, 500_000, 'microsecond is 500,000' ); is( $dt->millisecond, 500, 'millisecond is 500' ); $dt->set( nanosecond => 500_000_500 ); is( $dt->nanosecond, 500_000_500, 'nanosecond is 500,000,500' ); is( $dt->microsecond, 500_000, 'microsecond is 500,000' ); is( $dt->millisecond, 500, 'millisecond is 500' ); $dt->set( nanosecond => 499_999_999 ); is( $dt->nanosecond, 499_999_999, 'nanosecond is 499,999,999' ); is( $dt->microsecond, 499_999, 'microsecond is 499,999' ); is( $dt->millisecond, 499, 'millisecond is 499' ); $dt->set( nanosecond => 450_000_001 ); is( $dt->nanosecond, 450_000_001, 'nanosecond is 450,000,001' ); is( $dt->microsecond, 450_000, 'microsecond is 450,000' ); is( $dt->millisecond, 450, 'millisecond is 450' ); $dt->set( nanosecond => 450_500_000 ); is( $dt->nanosecond, 450_500_000, 'nanosecond is 450,500,000' ); is( $dt->microsecond, 450_500, 'microsecond is 450,500' ); is( $dt->millisecond, 450, 'millisecond is 450' ); } { my $dt = DateTime->new( year => 2003, month => 5, day => 7 ); is( $dt->weekday_of_month, 1, '->weekday_of_month' ); is( $dt->week_of_month, 2, '->week_of_month' ); } { my $dt = DateTime->new( year => 2003, month => 5, day => 8 ); is( $dt->weekday_of_month, 2, '->weekday_of_month' ); is( $dt->week_of_month, 2, '->week_of_month' ); } { my $dt = DateTime->new( year => 1000, hour => 23 ); is( $dt->hour, 23, '->hour' ); is( $dt->hour_1, 23, '->hour_1' ); is( $dt->hour_12, 11, '->hour_12' ); is( $dt->hour_12_0, 11, '->hour_12_0' ); } { my $dt = DateTime->new( year => 1000, hour => 0 ); is( $dt->hour, 0, '->hour' ); is( $dt->hour_1, 24, '->hour_1' ); is( $dt->hour_12, 12, '->hour_12' ); is( $dt->hour_12_0, 0, '->hour_12_0' ); } SKIP: { ## no critic (BuiltinFunctions::ProhibitStringyEval) skip 'These tests require Test::Warn', 9 unless eval 'use Test::Warn; 1'; my $dt = DateTime->new( year => 2000 ); warnings_like( sub { $dt->year(2001) }, qr/is a read-only/, 'year() is read-only' ); warnings_like( sub { $dt->month(5) }, qr/is a read-only/, 'month() is read-only' ); warnings_like( sub { $dt->day(5) }, qr/is a read-only/, 'day() is read-only' ); warnings_like( sub { $dt->hour(5) }, qr/is a read-only/, 'hour() is read-only' ); warnings_like( sub { $dt->minute(5) }, qr/is a read-only/, 'minute() is read-only' ); warnings_like( sub { $dt->second(5) }, qr/is a read-only/, 'second() is read-only' ); warnings_like( sub { $dt->nanosecond(5) }, qr/is a read-only/, 'nanosecond() is read-only' ); warnings_like( sub { $dt->time_zone('America/Chicago') }, qr/is a read-only/, 'time_zone() is read-only' ); warnings_like( sub { $dt->locale('en_US') }, qr/is a read-only/, 'locale() is read-only' ); } done_testing(); DateTime-1.46/t/21bad-params.t0000644000175000017500000000376013240151623015605 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; foreach my $p ( { year => 2000, month => 13 }, { year => 2000, month => 0 }, { year => 2000, month => 12, day => 32 }, { year => 2000, month => 12, day => 0 }, { year => 2000, month => 12, day => 10, hour => -1 }, { year => 2000, month => 12, day => 10, hour => 24 }, { year => 2000, month => 12, day => 10, hour => 12, minute => -1 }, { year => 2000, month => 12, day => 10, hour => 12, minute => 60 }, { year => 2000, month => 12, day => 10, hour => 12, second => -1 }, { year => 2000, month => 12, day => 10, hour => 12, second => 62 }, ) { like( exception { DateTime->new(%$p) }, qr/Validation failed/, 'Parameters outside valid range should fail in call to new()' ); like( exception { DateTime->new( year => 2000 )->set(%$p) }, qr/Validation failed/, 'Parameters outside valid range should fail in call to set()' ); } { like( exception { DateTime->last_day_of_month( year => 2000, month => 13, ); }, qr/Validation failed/, 'Parameters outside valid range should fail in call to last_day_of_month()' ); like( exception { DateTime->last_day_of_month( year => 2000, month => 0 ) }, qr/Validation failed/, 'Parameters outside valid range should fail in call to last_day_of_month()' ); } { like( exception { DateTime->new( year => 2000, month => 4, day => 31 ) }, qr/valid day of month/i, 'Day past last day of month should fail' ); like( exception { DateTime->new( year => 2001, month => 2, day => 29 ) }, qr/valid day of month/i, 'Day past last day of month should fail' ); is( exception { DateTime->new( year => 2000, month => 2, day => 29 ) }, undef, 'February 29 should be valid in leap years' ); } done_testing(); DateTime-1.46/t/26dt-leapsecond-pm.t0000644000175000017500000000213413240151623016731 0ustar autarchautarch# no pp test use strict; use warnings; use Test::More; use DateTime::LeapSecond; is( DateTime::LeapSecond::leap_seconds(100), 0, 'before 1970' ); # at the start of the table: # 1972-06-30 my $day = 720074; is( DateTime::LeapSecond::leap_seconds($day), 0, 'before leap-second transition' ); is( DateTime::LeapSecond::extra_seconds($day) + 0, 1, 'leap day' ); # 1972-07-01 $day = 720075; is( DateTime::LeapSecond::leap_seconds($day), 1, 'day after leap-second day' ); is( DateTime::LeapSecond::extra_seconds($day), 0, 'not a leap day' ); # 1972-07-02 $day = 720076; is( DateTime::LeapSecond::leap_seconds($day), 1, 'after leap-second day' ); # at the end of the table: # 1998-12-31 $day = 729754; is( DateTime::LeapSecond::leap_seconds($day), 21, 'before leap-second day' ); # 1999-01-01 $day = 729755; is( DateTime::LeapSecond::leap_seconds($day), 22, 'leap-second day' ); # 1999-01-02 $day = 729756; is( DateTime::LeapSecond::leap_seconds($day), 22, 'after leap-second day' ); # some leap second dates: # 1972 Jul. 1 # 1973 Jan. 1 # ... # 1997 Jul. 1 # 1999 Jan. 1 done_testing(); DateTime-1.46/t/27delta.t0000644000175000017500000000740213240151623014672 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 4, minute => 3, second => 2, nanosecond => 12, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 6, day => 12, hour => 5, minute => 7, second => 23, nanosecond => 7, time_zone => 'UTC' ); { my $dur_md = $date2->delta_md($date1); is( $dur_md->delta_months, 1, 'delta_md months is 1' ); is( $dur_md->delta_days, 2, 'delta_md days is 2' ); is( $dur_md->delta_minutes, 0, 'delta_md minutes is 0' ); is( $dur_md->delta_seconds, 0, 'delta_md seconds is 0' ); is( $dur_md->delta_nanoseconds, 0, 'delta_md nanoseconds is 0' ); my $dur_d = $date2->delta_days($date1); is( $dur_d->delta_months, 0, 'delta_d months is 0' ); is( $dur_d->delta_days, 33, 'delta_d days is 33' ); is( $dur_d->delta_minutes, 0, 'delta_d minutes is 0' ); is( $dur_d->delta_seconds, 0, 'delta_d seconds is 0' ); is( $dur_d->delta_nanoseconds, 0, 'delta_d nanoseconds is 0' ); my $dur_ms = $date2->delta_ms($date1); is( $dur_ms->delta_months, 0, 'delta_ms months is 0' ); is( $dur_ms->delta_days, 0, 'delta_ms days is 0' ); is( $dur_ms->delta_minutes, 47584, 'delta_ms minutes is 47584' ); is( $dur_ms->delta_seconds, 20, 'delta_ms seconds is 20' ); is( $dur_ms->delta_nanoseconds, 0, 'delta_ms nanoseconds is 0' ); is( $dur_ms->hours, 793, 'hours is 793' ); } { my $dur_md = $date1->delta_md($date2); is( $dur_md->delta_months, 1, 'delta_md months is 1' ); is( $dur_md->delta_days, 2, 'delta_md days is 2' ); is( $dur_md->delta_minutes, 0, 'delta_md minutes is 0' ); is( $dur_md->delta_seconds, 0, 'delta_md seconds is 0' ); is( $dur_md->delta_nanoseconds, 0, 'delta_md nanoseconds is 0' ); my $dur_d = $date1->delta_days($date2); is( $dur_d->delta_months, 0, 'delta_d months is 0' ); is( $dur_d->delta_days, 33, 'delta_d days is 33' ); is( $dur_d->delta_minutes, 0, 'delta_d minutes is 0' ); is( $dur_d->delta_seconds, 0, 'delta_d seconds is 0' ); is( $dur_d->delta_nanoseconds, 0, 'delta_d nanoseconds is 0' ); my $dur_ms = $date1->delta_ms($date2); is( $dur_ms->delta_months, 0, 'delta_ms months is 0' ); is( $dur_ms->delta_days, 0, 'delta_ms days is 0' ); is( $dur_ms->delta_minutes, 47584, 'delta_ms minutes is 47584' ); is( $dur_ms->delta_seconds, 20, 'delta_ms seconds is 20' ); is( $dur_ms->delta_nanoseconds, 0, 'delta_ms nanoseconds is 0' ); is( $dur_ms->hours, 793, 'hours is 793' ); } } { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 15, minute => 0, second => 0, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 5, day => 11, hour => 12, minute => 30, second => 10, time_zone => 'UTC' ); my $dur_ms = $date1->delta_ms($date2); is( $dur_ms->delta_months, 0, 'delta_ms months is 0' ); is( $dur_ms->delta_days, 0, 'delta_ms days is 0' ); is( $dur_ms->delta_minutes, 1290, 'delta_ms minutes is 1290' ); is( $dur_ms->delta_seconds, 10, 'delta_ms seconds is 30' ); is( $dur_ms->delta_nanoseconds, 0, 'delta_ms nanoseconds is 0' ); is( $dur_ms->hours, 21, 'hours is 21' ); } done_testing(); DateTime-1.46/t/01sanity.t0000644000175000017500000000314513240151623015100 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 1870, month => 10, day => 21, hour => 12, minute => 10, second => 45, nanosecond => 123456, time_zone => 'UTC' ); is( $dt->year, '1870', 'Year accessor, outside of the epoch' ); is( $dt->month, '10', 'Month accessor, outside the epoch' ); is( $dt->day, '21', 'Day accessor, outside the epoch' ); is( $dt->hour, '12', 'Hour accessor, outside the epoch' ); is( $dt->minute, '10', 'Minute accessor, outside the epoch' ); is( $dt->second, '45', 'Second accessor, outside the epoch' ); is( $dt->nanosecond, '123456', 'nanosecond accessor, outside the epoch' ); $dt = DateTime->from_object( object => $dt ); is( $dt->year, '1870', 'Year should be identical' ); is( $dt->month, '10', 'Month should be identical' ); is( $dt->day, '21', 'Day should be identical' ); is( $dt->hour, '12', 'Hour should be identical' ); is( $dt->minute, '10', 'Minute should be identical' ); is( $dt->second, '45', 'Second should be identical' ); is( $dt->nanosecond, '123456', 'nanosecond should be identical' ); } { my $dt = DateTime->new( year => 1870, month => 10, day => 21, hour => 12, minute => 10, second => 45, time_zone => 'UTC' ); is( $dt->minute, '10', 'Minute accessor, outside the epoch' ); is( $dt->second, '45', 'Second accessor, outside the epoch' ); } done_testing(); DateTime-1.46/t/29overload.t0000644000175000017500000001050413240151623015413 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use Test::Warnings 0.005 ':all'; use DateTime; { my $dt = DateTime->new( year => 1900, month => 12, day => 1 ); is( "$dt", '1900-12-01T00:00:00', 'stringification overloading' ); } { my $dt = DateTime->new( year => 2050, month => 1, day => 15, hour => 20, minute => 10, second => 10 ); my $before_string = '2050-01-15T20:10:09'; my $same_string = '2050-01-15T20:10:10'; my $after_string = '2050-01-15T20:10:11'; is( "$dt", $same_string, 'stringification overloading' ); ok( $dt eq $same_string, 'eq overloading true' ); ok( !( $dt eq $after_string ), 'eq overloading false' ); ok( $dt ne $after_string, 'ne overloading true' ); ok( !( $dt ne $same_string ), 'ne overloading false' ); is( $dt cmp $same_string, 0, 'cmp overloading' ); is( $dt cmp $after_string, -1, ' less than' ); ok( $dt lt $after_string, 'lt overloading' ); ok( !( $dt lt $same_string ), ' not' ); { package Other::Date; use overload q[""] => sub { return ${ $_[0] }; }, fallback => 1; sub new { my ( $class, $date ) = @_; return bless \$date, $class; } } my $same_od = Other::Date->new($same_string); my $after_od = Other::Date->new($after_string); my $before_od = Other::Date->new($before_string); ok( $dt eq $same_od, 'DateTime eq non-DateTime overloaded object true' ); ok( !( $dt eq $after_od ), ' eq false' ); ok( $dt ne $after_od, ' ne true' ); ok( !( $dt ne $same_od ), ' ne false' ); is( $dt cmp $same_od, 0, 'cmp overloading' ); is( $dt cmp $after_od, -1, ' lt overloading' ); ok( $dt lt $after_od, 'lt overloading' ); ok( !( $dt lt $same_od ), ' not' ); is_deeply( [ map { $_ . ' - ' . ( ref $_ || 'no ref' ) } sort { $a cmp $b or ref $a cmp ref $b } $same_od, $after_od, $before_od, $dt, $same_string, $after_string, $before_string ], [ map { $_ . ' - ' . ( ref $_ || 'no ref' ) } $before_string, $before_od, $same_string, $dt, $same_od, $after_string, $after_od ], 'eq sort' ); like( exception { my $x = $dt + 1 }, qr/Cannot add 1 to a DateTime object/, 'Cannot add plain scalar to a DateTime object' ); like( exception { my $x = $dt + bless {}, 'FooBar' }, qr/Cannot add FooBar=HASH\([^\)]+\) to a DateTime object/, 'Cannot add plain FooBar object to a DateTime object' ); like( exception { my $x = $dt - 1 }, qr/Cannot subtract 1 from a DateTime object/, 'Cannot subtract plain scalar from a DateTime object' ); like( exception { my $x = $dt - bless {}, 'FooBar' }, qr/Cannot subtract FooBar=HASH\([^\)]+\) from a DateTime object/, 'Cannot subtract plain FooBar object from a DateTime object' ); like( exception { my $x = $dt > 1 }, qr/A DateTime object can only be compared to another DateTime object/, 'Cannot compare a DateTime object to a scalar' ); like( exception { my $x = $dt > bless {}, 'FooBar' }, qr/A DateTime object can only be compared to another DateTime object/, 'Cannot compare a DateTime object to a FooBar object' ); like( warning { my $x = undef; $dt > $x; }, qr/uninitialized value in numeric gt .+ at .*x?t.(author.pp.)?29overload\.t/, 'Comparing undef to a DateTime object generates a Perl warning at the right spot ($dt > undef)' ); like( warning { my $x = undef; $x > $dt; }, qr/uninitialized value in numeric gt .+ at .*x?t.(author.pp.)?29overload\.t/, 'Comparing undef to a DateTime object generates a Perl warning at the right spot (undef > $dt)' ); ok( !( $dt eq 'some string' ), 'DateTime object always compares false to a string' ); ok( $dt ne 'some string', 'DateTime object always compares false to a string' ); ok( $dt eq $dt->clone, 'DateTime object is equal to a clone of itself' ); ok( !( $dt ne $dt->clone ), 'DateTime object is equal to a clone of itself (! ne)' ); } done_testing(); DateTime-1.46/t/zzz-check-breaks.t0000644000175000017500000000172413240151623016606 0ustar autarchautarchuse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::CheckBreaks 0.019 use Test::More tests => 2; SKIP: { eval { +require DateTime::Conflicts; DateTime::Conflicts->check_conflicts }; skip('no DateTime::Conflicts module found', 1) if not $INC{'DateTime/Conflicts.pm'}; diag $@ if $@; pass 'conflicts checked via DateTime::Conflicts'; } # this data duplicates x_breaks in META.json my $breaks = { "DateTime::Format::Mail" => "<= 0.402" }; use CPAN::Meta::Requirements; use CPAN::Meta::Check 0.011; my $reqs = CPAN::Meta::Requirements->new; $reqs->add_string_requirement($_, $breaks->{$_}) foreach keys %$breaks; our $result = CPAN::Meta::Check::check_requirements($reqs, 'conflicts'); if (my @breaks = grep { defined $result->{$_} } keys %$result) { diag 'Breakages found with DateTime:'; diag "$result->{$_}" for sort @breaks; diag "\n", 'You should now update these modules!'; } pass 'checked x_breaks data'; DateTime-1.46/t/00-report-prereqs.dd0000644000175000017500000001170013240151623016757 0ustar autarchautarchdo { my $x = { 'configure' => { 'requires' => { 'Dist::CheckConflicts' => '0.02', 'ExtUtils::MakeMaker' => '0' }, 'suggests' => { 'JSON::PP' => '2.27300' } }, 'develop' => { 'requires' => { 'Code::TidyAll' => '0.56', 'Code::TidyAll::Plugin::SortLines::Naturally' => '0.000003', 'Code::TidyAll::Plugin::Test::Vars' => '0.02', 'Cwd' => '0', 'Devel::PPPort' => '3.23', 'Module::Implementation' => '0', 'Parallel::ForkManager' => '1.19', 'Perl::Critic' => '1.126', 'Perl::Tidy' => '20160302', 'Pod::Coverage::TrustPod' => '0', 'Pod::Wordlist' => '0', 'Storable' => '0', 'Test::CPAN::Changes' => '0.19', 'Test::CPAN::Meta::JSON' => '0.16', 'Test::CleanNamespaces' => '0.15', 'Test::Code::TidyAll' => '0.50', 'Test::DependentModules' => '0', 'Test::EOL' => '0', 'Test::Fatal' => '0', 'Test::Mojibake' => '0', 'Test::More' => '0.96', 'Test::NoTabs' => '0', 'Test::Pod' => '1.41', 'Test::Pod::Coverage' => '1.08', 'Test::Portability::Files' => '0', 'Test::Spelling' => '0.12', 'Test::Vars' => '0.009', 'Test::Version' => '2.05', 'Test::Warnings' => '0.005', 'autodie' => '0', 'utf8' => '0' } }, 'runtime' => { 'requires' => { 'Carp' => '0', 'DateTime::Locale' => '1.06', 'DateTime::TimeZone' => '2.02', 'Dist::CheckConflicts' => '0.02', 'POSIX' => '0', 'Params::ValidationCompiler' => '0.26', 'Scalar::Util' => '0', 'Specio' => '0.18', 'Specio::Declare' => '0', 'Specio::Exporter' => '0', 'Specio::Library::Builtins' => '0', 'Specio::Library::Numeric' => '0', 'Specio::Library::String' => '0', 'Try::Tiny' => '0', 'XSLoader' => '0', 'base' => '0', 'integer' => '0', 'namespace::autoclean' => '0.19', 'overload' => '0', 'parent' => '0', 'perl' => '5.008004', 'strict' => '0', 'warnings' => '0', 'warnings::register' => '0' } }, 'test' => { 'recommends' => { 'CPAN::Meta' => '2.120900' }, 'requires' => { 'CPAN::Meta::Check' => '0.011', 'CPAN::Meta::Requirements' => '0', 'ExtUtils::MakeMaker' => '0', 'File::Spec' => '0', 'Storable' => '0', 'Test::Fatal' => '0', 'Test::More' => '0.96', 'Test::Warnings' => '0.005', 'utf8' => '0' } } }; $x; }DateTime-1.46/t/36invalid-local.t0000644000175000017500000000252213240151623016315 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; my $badlt_rx = qr/Invalid local time|local time [0-9\-:T]+ does not exist/; { like( exception { DateTime->new( year => 2003, month => 4, day => 6, hour => 2, time_zone => 'America/Chicago', ); }, $badlt_rx, 'exception for invalid time' ); like( exception { DateTime->new( year => 2003, month => 4, day => 6, hour => 2, minute => 59, second => 59, time_zone => 'America/Chicago', ); }, $badlt_rx, 'exception for invalid time' ); } { is( exception { DateTime->new( year => 2003, month => 4, day => 6, hour => 1, minute => 59, second => 59, time_zone => 'America/Chicago', ); }, undef, 'no exception for valid time' ); my $dt = DateTime->new( year => 2003, month => 4, day => 5, hour => 2, time_zone => 'America/Chicago', ); like( exception { $dt->add( days => 1 ) }, $badlt_rx, 'exception for invalid time produced via add' ); } done_testing(); DateTime-1.46/t/41cldr-format.t0000644000175000017500000001514513240151623016012 0ustar autarchautarchuse strict; use warnings; use utf8; use Test::More; use DateTime; for my $o ( Test::Builder->new->output, Test::Builder->new->failure_output, Test::Builder->new->todo_output ) { binmode $o, ':encoding(UTF-8)' or die $!; } { my $dt = DateTime->new( year => 1976, month => 10, day => 20, hour => 18, minute => 34, second => 55, nanosecond => 1_000_000, locale => 'en', time_zone => 'America/Chicago', ); my %tests = ( 'GGGGG' => 'A', 'GGGG' => 'Anno Domini', 'GGG' => 'AD', 'GG' => 'AD', 'G' => 'AD', 'yyyyy' => '01976', 'yyyy' => '1976', 'yyy' => '1976', 'yy' => '76', 'y' => '1976', 'uuuuuu' => '001976', 'uuuuu' => '01976', 'uuuu' => '1976', 'uuu' => '1976', 'uu' => '1976', 'u' => '1976', 'YYYYY' => '01976', 'YYYY' => '1976', 'YYY' => '1976', 'YY' => '1976', 'Y' => '1976', 'QQQQ' => '4th quarter', 'QQQ' => 'Q4', 'QQ' => '04', 'Q' => '4', 'qqqq' => '4th quarter', 'qqq' => 'Q4', 'qq' => '04', 'q' => '4', 'MMMMM' => 'O', 'MMMM' => 'October', 'MMM' => 'Oct', 'MM' => '10', 'M' => '10', 'LLLLL' => 'O', 'LLLL' => 'October', 'LLL' => 'Oct', 'LL' => '10', 'L' => '10', 'ww' => '43', 'w' => '43', 'W' => '3', 'dd' => '20', 'd' => '20', 'DDD' => '294', 'DD' => '294', 'D' => '294', 'F' => '3', 'gggggg' => '043071', 'g' => '43071', 'EEEEE' => 'W', 'EEEE' => 'Wednesday', 'EEE' => 'Wed', 'EE' => 'Wed', 'E' => 'Wed', 'eeeee' => 'W', 'eeee' => 'Wednesday', 'eee' => 'Wed', 'ee' => '03', 'e' => '3', 'ccccc' => 'W', 'cccc' => 'Wednesday', 'ccc' => 'Wed', 'cc' => '03', 'c' => '3', 'a' => 'PM', 'hh' => '06', 'h' => '6', 'HH' => '18', 'H' => '18', 'KK' => '06', 'K' => '6', 'kk' => '18', 'j' => '6', 'jj' => '06', 'mm' => '34', 'm' => '34', 'ss' => '55', 's' => '55', 'SS' => '00', 'SSSSSS' => '001000', 'A' => '66895001', 'zzzz' => 'America/Chicago', 'zzz' => 'CDT', 'ZZZZ' => 'CDT-0500', 'ZZZ' => '-0500', 'vvvv' => 'America/Chicago', 'vvv' => 'CDT', 'VVVV' => 'America/Chicago', 'VVV' => 'CDT', 'ZZZZZ' => '-05:00', q{'one fine day'} => 'one fine day', q{'yy''yy' yyyy} => q{yy'yy 1976}, q{'yy''yy' 'hello' yyyy} => q{yy'yy hello 1976}, # Non-pattern text should pass through unchanged 'd日' => '20日', ); for my $k ( sort keys %tests ) { is( $dt->format_cldr($k), $tests{$k}, "format_cldr for $k" ); } } { my $dt = DateTime->new( year => 2008, month => 10, day => 20, hour => 18, minute => 34, second => 55, nanosecond => 1_000_000, locale => 'en', time_zone => 'America/Chicago', ); is( $dt->format_cldr('yy'), '08', 'format_cldr for yy in 2008 should be 08' ); } { my $dt = DateTime->new( year => 2008, month => 10, day => 20, hour => 18, minute => 34, second => 55, nanosecond => 1_000_000, locale => 'en_US', time_zone => 'America/Chicago', ); is( $dt->format_cldr('j'), '6', 'format_cldr for j in en_US should be 6 (at 18:34)' ); } { my $dt = DateTime->new( year => 2008, month => 10, day => 20, hour => 18, minute => 34, second => 55, nanosecond => 1_000_000, locale => 'fr', time_zone => 'America/Chicago', ); is( $dt->format_cldr('j'), '18', 'format_cldr for j in fr should be 18 (at 18:34)' ); } { my $dt = DateTime->new( year => 2009, month => 4, day => 13, locale => 'en_US', ); is( $dt->format_cldr('e'), '2', 'format_cldr for e in en_US should be 2 (for Monday, 2009-04-13)' ); is( $dt->format_cldr('c'), '1', 'format_cldr for c in en_US should be 1 (for Monday, 2009-04-13)' ); } { my $dt = DateTime->new( year => 2009, month => 4, day => 13, locale => 'fr_FR', ); is( $dt->format_cldr('e'), '1', 'format_cldr for e in fr_FR should be 1 (for Monday, 2009-04-13)' ); is( $dt->format_cldr('c'), '1', 'format_cldr for c in fr_FR should be 1 (for Monday, 2009-04-13)' ); } { my $dt = DateTime->new( year => -10 ); my %tests = ( 'y' => '-10', 'yy' => '-10', 'yyy' => '-10', 'yyyy' => '-010', 'yyyyy' => '-0010', 'u' => '-10', 'uu' => '-10', 'uuu' => '-10', 'uuuu' => '-010', 'uuuuu' => '-0010', ); for my $k ( sort keys %tests ) { is( $dt->format_cldr($k), $tests{$k}, "format_cldr for $k" ); } } { my $dt = DateTime->new( year => -1976 ); my %tests = ( 'y' => '-1976', 'yy' => '-76', 'yyy' => '-1976', 'yyyy' => '-1976', 'yyyyy' => '-1976', 'u' => '-1976', 'uu' => '-1976', 'uuu' => '-1976', 'uuuu' => '-1976', 'uuuuu' => '-1976', ); for my $k ( sort keys %tests ) { is( $dt->format_cldr($k), $tests{$k}, "format_cldr for $k" ); } } { my $dt = DateTime->new( year => 1976, month => 10, day => 20, hour => 18, minute => 34, second => 55, nanosecond => 999_999_999, locale => 'en', time_zone => 'UTC', ); is( $dt->format_cldr('ss,SSS'), '55,999', 'milliseconds are rounded down', ); } done_testing(); DateTime-1.46/t/18today.t0000644000175000017500000000066513240151623014725 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; { my $now = DateTime->now; my $today = DateTime->today; is( $today->year, $now->year, 'today->year' ); is( $today->month, $now->month, 'today->month' ); is( $today->day, $now->day, 'today->day' ); is( $today->hour, 0, 'today->hour' ); is( $today->minute, 0, 'today->hour' ); is( $today->second, 0, 'today->hour' ); } done_testing(); DateTime-1.46/t/46warnings.t0000644000175000017500000000426713240151623015440 0ustar autarchautarchuse strict; use warnings; use Test::More; use Test::Warnings 0.005 ':all'; use DateTime; my $year_5001_epoch = 95649120000; ## no critic (TestingAndDebugging::ProhibitNoWarnings) SKIP: { my $year = ( gmtime($year_5001_epoch) )[5]; skip 'These tests require a 64-bit Perl', 2 unless defined $year && $year == 3101; { like( warning { DateTime->from_epoch( epoch => $year_5001_epoch, time_zone => 'Asia/Taipei', ); }, qr{\QYou are creating a DateTime object with a far future year (5001) and a time zone (Asia/Taipei).}, 'got a warning when calling ->from_epoch with a far future epoch and a time_zone' ); } { no warnings 'DateTime'; is_deeply( warning { DateTime->from_epoch( epoch => $year_5001_epoch, time_zone => 'Asia/Taipei', ); }, [], 'no warning when calling ->from_epoch with a far future epoch and a time_zone with DateTime warnings category suppressed' ); } } { like( warning { DateTime->new( year => 5001, time_zone => 'Asia/Taipei', ); }, qr{\QYou are creating a DateTime object with a far future year (5001) and a time zone (Asia/Taipei).}, 'got a warning when calling ->new with a far future year and a time_zone' ); } { no warnings 'DateTime'; is_deeply( warning { DateTime->new( year => 5001, time_zone => 'Asia/Taipei', ); }, [], 'no warning when calling ->new with a far future epoch and a time_zone with DateTime warnings category suppressed' ); } { no warnings; is_deeply( warning { DateTime->new( year => 5001, time_zone => 'Asia/Taipei', ); }, [], 'no warning when calling ->new with a far future epoch and a time_zone with all warnings suppressed' ); } done_testing(); DateTime-1.46/t/38local-subtract.t0000644000175000017500000004617213240151623016531 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; # These tests should be the final word on dt subtraction involving a # DST-changing time zone { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, time_zone => 'America/Chicago', ); my $dur1 = $dt2->subtract_datetime($dt1); my %deltas1 = $dur1->deltas; is( $deltas1{months}, 6, 'delta_months is 6' ); is( $deltas1{days}, 0, 'delta_days is 0' ); is( $deltas1{minutes}, 0, 'delta_minutes is 0' ); is( $deltas1{seconds}, 0, 'delta_seconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur1), $dt2 ), 0, 'subtract_datetime is reversible from start point' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur1), $dt1 ), 0, 'subtract_datetime is reversible from end point' ); is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' ); my $dur2 = $dt1->subtract_datetime($dt2); my %deltas2 = $dur2->deltas; is( $deltas2{months}, -6, 'delta_months is -6' ); is( $deltas2{days}, 0, 'delta_days is 0' ); is( $deltas2{minutes}, 0, 'delta_minutes is 0' ); is( $deltas2{seconds}, 0, 'delta_seconds is 0' ); is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' ); my $dur3 = $dt2->delta_md($dt1); my %deltas3 = $dur3->deltas; is( $deltas3{months}, 6, 'delta_months is 6' ); is( $deltas3{days}, 0, 'delta_days is 0' ); is( $deltas3{minutes}, 0, 'delta_minutes is 0' ); is( $deltas3{seconds}, 0, 'delta_seconds is 0' ); is( $deltas3{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur3), $dt2 ), 0, 'delta_md is reversible from start point' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur3), $dt1 ), 0, 'delta_md is reversible from end point' ); my $dur4 = $dt2->delta_days($dt1); my %deltas4 = $dur4->deltas; is( $deltas4{months}, 0, 'delta_months is 0' ); is( $deltas4{days}, 184, 'delta_days is 184' ); is( $deltas4{minutes}, 0, 'delta_minutes is 0' ); is( $deltas4{seconds}, 0, 'delta_seconds is 0' ); is( $deltas4{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur3), $dt2 ), 0, 'delta_days is reversible from start point' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur4), $dt1 ), 0, 'delta_days is reversible from end point' ); } # same as above, but now the UTC hour of the earlier datetime is # _greater_ than that of the later one. this checks that overflows # are handled correctly. { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, hour => 18, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, hour => 18, time_zone => 'America/Chicago', ); my $dur1 = $dt2->subtract_datetime($dt1); my %deltas1 = $dur1->deltas; is( $deltas1{months}, 6, 'delta_months is 6' ); is( $deltas1{days}, 0, 'delta_days is 0' ); is( $deltas1{minutes}, 0, 'delta_minutes is 0' ); is( $deltas1{seconds}, 0, 'delta_seconds is 0' ); is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' ); } # make sure delta_md and delta_days work in the face of DST change # where we lose an hour { my $dt1 = DateTime->new( year => 2003, month => 11, day => 6, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2004, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dur1 = $dt2->delta_md($dt1); my %deltas1 = $dur1->deltas; is( $deltas1{months}, 6, 'delta_months is 6' ); is( $deltas1{days}, 0, 'delta_days is 0' ); is( $deltas1{minutes}, 0, 'delta_minutes is 0' ); is( $deltas1{seconds}, 0, 'delta_seconds is 0' ); is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' ); my $dur2 = $dt2->delta_days($dt1); my %deltas2 = $dur2->deltas; is( $deltas2{months}, 0, 'delta_months is 0' ); is( $deltas2{days}, 182, 'delta_days is 182' ); is( $deltas2{minutes}, 0, 'delta_minutes is 0' ); is( $deltas2{seconds}, 0, 'delta_seconds is 0' ); is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' ); } # the docs say use UTC to guarantee reversibility { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, time_zone => 'America/Chicago', ); $dt1->set_time_zone('UTC'); $dt2->set_time_zone('UTC'); my $dur = $dt2->subtract_datetime($dt1); is( DateTime->compare( $dt1->add_duration($dur), $dt2 ), 0, 'subtraction is reversible from start point with UTC' ); is( DateTime->compare( $dt2->subtract_duration($dur), $dt2 ), 0, 'subtraction is reversible from start point with UTC' ); } # The important thing here is that after a subtraction, we can use the # duration to get from one date to the other, regardless of the type # of subtraction done. { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, time_zone => 'America/Chicago', ); my $dur1 = $dt2->subtract_datetime_absolute($dt1); my %deltas1 = $dur1->deltas; is( $deltas1{months}, 0, 'delta_months is 0' ); is( $deltas1{days}, 0, 'delta_days is 0' ); is( $deltas1{minutes}, 0, 'delta_minutes is 0' ); is( $deltas1{seconds}, 15901200, 'delta_seconds is 15901200' ); is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur1), $dt2 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur1), $dt1 ), 0, 'subtraction is doubly reversible' ); my $dur2 = $dt1->subtract_datetime_absolute($dt2); my %deltas2 = $dur2->deltas; is( $deltas2{months}, 0, 'delta_months is 0' ); is( $deltas2{days}, 0, 'delta_days is 0' ); is( $deltas2{minutes}, 0, 'delta_minutes is 0' ); is( $deltas2{seconds}, -15901200, 'delta_seconds is -15901200' ); is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt2->clone->add_duration($dur2), $dt1 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt1->clone->subtract_duration($dur2), $dt2 ), 0, 'subtraction is doubly reversible' ); } { my $dt1 = DateTime->new( year => 2003, month => 4, day => 6, hour => 1, minute => 58, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 4, day => 6, hour => 3, minute => 1, time_zone => 'America/Chicago', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, 'delta_months is 0' ); is( $deltas{days}, 0, 'delta_days is 0' ); is( $deltas{minutes}, 3, 'delta_minutes is 3' ); is( $deltas{seconds}, 0, 'delta_seconds is 0' ); is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, 'subtraction is doubly reversible' ); } { my $dt1 = DateTime->new( year => 2003, month => 4, day => 5, hour => 1, minute => 58, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 4, day => 6, hour => 3, minute => 1, time_zone => 'America/Chicago', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, 'delta_months is 0' ); is( $deltas{days}, 1, 'delta_days is 1' ); is( $deltas{minutes}, 3, 'delta_minutes is 3' ); is( $deltas{seconds}, 0, 'delta_seconds is 0' ); is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'dt1 + dur = dt2' ); # this are two examples from the docs is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1->clone->add( hours => 1 ) ), 0, 'dt2 - dur != dt1 (not reversible)' ); is( DateTime->compare( $dt2->clone->subtract_duration( $dur->clock_duration ) ->subtract_duration( $dur->calendar_duration ), $dt1 ), 0, 'dt2 - dur->clock - dur->cal = dt1 (reversible when componentized)' ); my $dur2 = $dt1->subtract_datetime($dt2); my %deltas2 = $dur2->deltas; is( $deltas2{months}, 0, 'delta_months is 0' ); is( $deltas2{days}, -1, 'delta_days is 1' ); is( $deltas2{minutes}, -3, 'delta_minutes is 3' ); is( $deltas2{seconds}, 0, 'delta_seconds is 0' ); is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( $dt2->clone->add_duration($dur2)->datetime, '2003-04-05T02:58:00', 'dt2 + dur2 != dt1' ); is( DateTime->compare( $dt2->clone->add_duration( $dur2->clock_duration ) ->add_duration( $dur2->calendar_duration ), $dt1 ), 0, 'dt2 + dur2->clock + dur2->cal = dt1' ); is( DateTime->compare( $dt1->clone->subtract_duration($dur2), $dt2 ), 0, 'dt1 - dur2 = dt2' ); } # These tests makes sure that days with DST changes are "normal" when # they're the smaller operand { my $dt1 = DateTime->new( year => 2003, month => 4, day => 6, hour => 3, minute => 1, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 4, day => 7, hour => 3, minute => 2, time_zone => 'America/Chicago', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, 'delta_months is 0' ); is( $deltas{days}, 1, 'delta_days is 1' ); is( $deltas{minutes}, 1, 'delta_minutes is 1' ); is( $deltas{seconds}, 0, 'delta_seconds is 0' ); is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' ); my $dur2 = $dt1->subtract_datetime($dt2); my %deltas2 = $dur2->deltas; is( $deltas2{months}, 0, 'delta_months is 0' ); is( $deltas2{days}, -1, 'delta_days is -1' ); is( $deltas2{minutes}, -1, 'delta_minutes is -1' ); is( $deltas2{seconds}, 0, 'delta_seconds is 0' ); is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' ); } { my $dt1 = DateTime->new( year => 2003, month => 4, day => 5, hour => 1, minute => 58, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 4, day => 7, hour => 2, minute => 1, time_zone => 'America/Chicago', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, 'delta_months is 0' ); is( $deltas{days}, 2, 'delta_days is 2' ); is( $deltas{minutes}, 3, 'delta_minutes is 3' ); is( $deltas{seconds}, 0, 'delta_seconds is 0' ); is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, 'subtraction is doubly reversible' ); } # from example in docs { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, time_zone => 'America/Chicago', ); $dt1->set_time_zone('floating'); $dt2->set_time_zone('floating'); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 6, 'delta_months is 6' ); is( $deltas{days}, 0, 'delta_days is 0' ); is( $deltas{minutes}, 0, 'delta_minutes is 0' ); is( $deltas{seconds}, 0, 'delta_seconds is 0' ); is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'subtraction is reversible from start point' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, 'subtraction is reversible from end point' ); } { my $dt1 = DateTime->new( year => 2005, month => 8, time_zone => 'Europe/London', ); my $dt2 = DateTime->new( year => 2005, month => 11, time_zone => 'Europe/London', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 3, '3 months between two local times over DST change' ); is( $deltas{days}, 0, '0 days between two local times over DST change' ); is( $deltas{minutes}, 0, '0 minutes between two local times over DST change' ); } # same as previous but without hours overflow { my $dt1 = DateTime->new( year => 2005, month => 8, hour => 12, time_zone => 'Europe/London', ); my $dt2 = DateTime->new( year => 2005, month => 11, hour => 12, time_zone => 'Europe/London', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 3, '3 months between two local times over DST change' ); is( $deltas{days}, 0, '0 days between two local times over DST change' ); is( $deltas{minutes}, 0, '0 minutes between two local times over DST change' ); } # another docs example { my $dt2 = DateTime->new( year => 2003, month => 10, day => 26, hour => 1, time_zone => 'America/Chicago', ); my $dt1 = $dt2->clone->subtract( hours => 1 ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, '0 months between two local times over DST change' ); is( $deltas{days}, 0, '0 days between two local times over DST change' ); is( $deltas{minutes}, 60, '60 minutes between two local times over DST change' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, 'subtraction is doubly reversible' ); } { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/New_York', ); my $dt2 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, '0 months between two local times over DST change' ); is( $deltas{days}, 0, '0 days between two local times over DST change' ); is( $deltas{minutes}, 60, '60 minutes between two local times over DST change' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, 'subtraction is doubly reversible' ); } # Fix a bug that occurred when the local time zone had DST and the two # datetime objects were on the same day { my $dt1 = DateTime->new( year => 2005, month => 4, day => 3, hour => 7, minute => 0, time_zone => 'America/New_York' ); my $dt2 = DateTime->new( year => 2005, month => 4, day => 3, hour => 8, minute => 0, time_zone => 'America/New_York' ); my $dur = $dt2->subtract_datetime($dt1); my ( $minutes, $seconds ) = $dur->in_units( 'minutes', 'seconds' ); is( $minutes, 60, 'subtraction of two dates on a DST change date, minutes == 60' ); is( $seconds, 0, 'subtraction of two dates on a DST change date, seconds == 0' ); $dur = $dt1->subtract_datetime($dt1); ok( $dur->is_zero, 'dst change date (no dst) - itself, duration is zero' ); } { my $dt1 = DateTime->new( year => 2005, month => 4, day => 3, hour => 1, minute => 0, time_zone => 'America/New_York' ); my $dur = $dt1->subtract_datetime($dt1); ok( $dur->is_zero, 'dst change date (with dst) - itself, duration is zero' ); } # This tests a bug where one of the datetimes is changing DST, and the # other is not. In this case, no "adjustments" (aka hacks) are made in # subtract_datetime, and it just gives the "UTC difference". { # This is UTC-4 my $dt1 = DateTime->new( year => 2009, month => 3, day => 9, time_zone => 'America/New_York' ); # This is UTC+8 my $dt2 = DateTime->new( year => 2009, month => 3, day => 9, time_zone => 'Asia/Hong_Kong' ); my $dur = $dt1->subtract_datetime($dt2); is( $dur->delta_minutes, 720, 'subtraction the day after a DST change in one zone, where the other datetime is in a different zone' ); } { # This is UTC-5 my $dt1 = DateTime->new( year => 2009, month => 3, day => 8, hour => 1, time_zone => 'America/New_York' ); # This is UTC+8 my $dt2 = DateTime->new( year => 2009, month => 3, day => 8, hour => 1, time_zone => 'Asia/Hong_Kong' ); my $dur = $dt1->subtract_datetime($dt2); is( $dur->delta_minutes, 780, 'subtraction the day of a DST change in one zone (before the change),' . ' where the other datetime is in a different zone' ); } { # This is UTC-4 my $dt1 = DateTime->new( year => 2009, month => 3, day => 8, hour => 4, time_zone => 'America/New_York' ); # This is UTC+8 my $dt2 = DateTime->new( year => 2009, month => 3, day => 8, hour => 4, time_zone => 'Asia/Hong_Kong' ); my $dur = $dt1->subtract_datetime($dt2); is( $dur->delta_minutes, 720, 'subtraction the day of a DST change in one zone (after the change),' . ' where the other datetime is in a different zone' ); } done_testing(); DateTime-1.46/t/14locale.t0000644000175000017500000000371213240151623015034 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; use DateTime::Locale; is( exception { DateTime->new( year => 100, locale => 'en_US' ) }, undef, 'make sure new accepts locale parameter' ); is( exception { DateTime->now( locale => 'en_US' ) }, undef, 'make sure now accepts locale parameter' ); is( exception { DateTime->today( locale => 'en_US' ) }, undef, 'make sure today accepts locale parameter' ); is( exception { DateTime->from_epoch( epoch => 1, locale => 'en_US' ) }, undef, 'make sure from_epoch accepts locale parameter' ); is( exception { DateTime->last_day_of_month( year => 100, month => 2, locale => 'en_US' ); }, undef, 'make sure last_day_of_month accepts locale parameter' ); { package DT::Object; sub utc_rd_values { ( 0, 0 ) } } is( exception { DateTime->from_object( object => ( bless {}, 'DT::Object' ), locale => 'en_US' ); }, undef, , 'make sure constructor accepts locale parameter' ); is( exception { DateTime->new( year => 100, locale => DateTime::Locale->load('en_US') ); }, undef, 'make sure constructor accepts locale parameter as object' ); DateTime->DefaultLocale('it'); is( DateTime->now->locale->id, 'it', 'default locale should now be "it"' ); { my $dt = DateTime->new( year => 2013, month => 10, day => 27, hour => 0, time_zone => 'UTC' ); my $after_zone = $dt->clone()->set_time_zone('Europe/Rome'); is( $after_zone->offset(), '7200', 'offset is 7200 after set_time_zone()' ); my $after_locale = $dt->clone()->set_time_zone('Europe/Rome')->set_locale('en_GB'); is( $after_locale->offset(), '7200', 'offset is 7200 after set_time_zone() and set_locale()' ); } done_testing(); DateTime-1.46/t/30future-tz.t0000644000175000017500000000320513240151623015535 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; # # This test exercises a bug that occurred when date math did not # always make sure to update the utc_year attribute of the given # DateTime. The sympton was that the time zone future span generation # would fail because utc_year was less than the span's max_year, so # span generation wouldn't actually do anything, and it would die with # "Invalid local time". # { # Each iteration needs to use a different zone, because if it # works once, the generated spans are cached. for my $add ( [ years => 50, 1, 'America/New_York' ], [ days => 50, 365, 'America/Chicago' ], [ minutes => 50, 365 * 1440, 'America/Denver', ], [ seconds => 50, 365 * 1440 * 60, 'America/Los_Angeles' ], [ nanoseconds => 50, 365 * 1440 * 60 * 1_000_000_000, 'America/North_Dakota/Center' ], [ years => 750, 1, 'Europe/Paris' ], [ days => 750, 365, 'Europe/London' ], [ minutes => 750, 365 * 1440, 'Europe/Brussels', ], [ seconds => 750, 365 * 1440 * 60, 'Europe/Vienna' ], [ nanoseconds => 750, 365 * 1440 * 60 * 1_000_000_000, 'Europe/Prague' ], ) { my $dt = DateTime->now->set( hour => 12 )->set_time_zone( $add->[3] ); my $new = eval { $dt->clone->add( $add->[0], $add->[1] * $add->[2] ) }; is( $@, q{}, "Make sure we can add $add->[1] years worth of $add->[0] in $add->[3] time zone" ); } } done_testing(); DateTime-1.46/t/24from-object.t0000644000175000017500000000437313240151623016011 0ustar autarchautarch## no critic (Modules::ProhibitMultiplePackages) use strict; use warnings; use Test::More; use DateTime; my $dt1 = DateTime->new( year => 1970, hour => 1, nanosecond => 100 ); my $dt2 = DateTime->from_object( object => $dt1 ); is( $dt1->year, 1970, 'year is 1970' ); is( $dt1->hour, 1, 'hour is 1' ); is( $dt1->nanosecond, 100, 'nanosecond is 100' ); { my $t1 = DateTime::Calendar::_Test::WithoutTZ->new( rd_days => 1, rd_secs => 0 ); # Tests creating objects from other calendars (without time zones) my $t2 = DateTime->from_object( object => $t1 ); isa_ok( $t2, 'DateTime' ); is( $t2->datetime, '0001-01-01T00:00:00', 'convert from object without tz' ); ok( $t2->time_zone->is_floating, 'time_zone is floating' ); } { my $tz = DateTime::TimeZone->new( name => 'America/Chicago' ); my $t1 = DateTime::Calendar::_Test::WithTZ->new( rd_days => 1, rd_secs => 0, time_zone => $tz ); # Tests creating objects from other calendars (with time zones) my $t2 = DateTime->from_object( object => $t1 ); isa_ok( $t2, 'DateTime' ); is( $t2->time_zone->name, 'America/Chicago', 'time_zone is preserved' ); } { my $tz = DateTime::TimeZone->new( name => 'UTC' ); my $t1 = DateTime::Calendar::_Test::WithTZ->new( rd_days => 720258, rd_secs => 86400, time_zone => $tz ); my $t2 = DateTime->from_object( object => $t1 ); isa_ok( $t2, 'DateTime' ); is( $t2->second, 60, 'new DateTime from_object with TZ which is a leap second' ); } { for my $class (qw( DateTime::Infinite::Past DateTime::Infinite::Future )) { isa_ok( DateTime->from_object( object => $class->new ), $class, "from_object($class)" ); } } done_testing(); # Set up two simple test packages package DateTime::Calendar::_Test::WithoutTZ; sub new { my $class = shift; bless {@_}, $class; } sub utc_rd_values { return $_[0]{rd_days}, $_[0]{rd_secs}, 0; } package DateTime::Calendar::_Test::WithTZ; sub new { my $class = shift; bless {@_}, $class; } sub utc_rd_values { return $_[0]{rd_days}, $_[0]{rd_secs}, 0; } sub time_zone { return $_[0]{time_zone}; } DateTime-1.46/t/23storable.t0000644000175000017500000000440113240151623015404 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; unless ( eval { require Storable; 1 } ) { plan skip_all => 'Cannot load Storable'; } { my @dt = ( DateTime->new( year => 1950, hour => 1, nanosecond => 1, time_zone => 'America/Chicago', locale => 'de' ), DateTime::Infinite::Past->new, DateTime::Infinite::Future->new, ); foreach my $dt (@dt) { my $copy = Storable::thaw( Storable::nfreeze($dt) ); is( $copy->time_zone->name, $dt->time_zone->name, 'Storable freeze/thaw preserves tz' ); is( ref $copy->locale, ref $dt->locale, 'Storable freeze/thaw preserves locale' ); is( $copy->year, $dt->year, 'Storable freeze/thaw preserves rd values' ); is( $copy->hour, $dt->hour, 'Storable freeze/thaw preserves rd values' ); is( $copy->nanosecond, $dt->nanosecond, 'Storable freeze/thaw preserves rd values' ); } } { my $dt1 = DateTime->now( locale => 'en-US' ); my $dt2 = Storable::dclone($dt1); my $dt3 = Storable::thaw( Storable::nfreeze($dt2) ); is( $dt1->iso8601, $dt2->iso8601, 'dclone produces date equal to original' ); is( $dt2->iso8601, $dt3->iso8601, 'explicit freeze and thaw produces date equal to original' ); # Back-compat shim for new DateTime::Locale. Remove once DT::Locale based # on CLDR 28+ is released. my $meth = $dt1->locale->can('code') ? 'code' : 'id'; my $orig_code = $dt1->locale->$meth; is( $dt2->locale->$meth, $orig_code, 'check locale id after dclone' ); is( $dt3->locale->$meth, $orig_code, 'check locale id after explicit freeze/thaw' ); } { package Formatter; sub format_datetime { } } { my $dt = DateTime->new( year => 2004, formatter => 'Formatter', ); my $copy = Storable::thaw( Storable::nfreeze($dt) ); is( $dt->formatter, $copy->formatter, 'Storable freeze/thaw preserves formatter' ); } done_testing(); DateTime-1.46/t/43new-params.t0000644000175000017500000000423613240151623015653 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; like( exception { DateTime->new( year => 10.5 ) }, qr/Validation failed for type named Year/, 'year must be an integer' ); like( exception { DateTime->new( year => -10.5 ) }, qr/Validation failed for type named Year/, 'year must be an integer' ); like( exception { DateTime->new( year => 10, month => 2.5 ) }, qr/Validation failed for type named Month/, 'month must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12.4 ) }, qr/Validation failed for type named DayOfMonth/, 'day must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12, hour => 4.1 ); }, qr/Validation failed for type named Hour/, 'hour must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12, hour => 4, minute => 12.2 ); }, qr/Validation failed for type named Minute/, 'minute must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12, hour => 4, minute => 12, second => 51.8 ); }, qr/Validation failed for type named Second/, 'second must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12, hour => 4, minute => 12, second => 51, nanosecond => 124512.12412 ); }, qr/Validation failed for type named Nanosecond/, 'nanosecond must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12 )->today; }, qr/called with reference/, 'today must be called as a class method, not an object method' ); like( exception { DateTime->new( year => 10, month => 2, day => 12 )->now; }, qr/called with reference/, 'now must be called as a class method, not an object method' ); done_testing(); DateTime-1.46/t/19leap-second.t0000644000175000017500000007340313240151623016000 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; use DateTime::LeapSecond; # tests using UTC times { # 1972-06-30T23:58:20 UTC my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); my $t1 = $t->clone; is( $t->year, 1972, 'year is 1972' ); is( $t->minute, 58, 'minute is 58' ); is( $t->second, 20, 'second is 20' ); # 1972-06-30T23:59:20 UTC $t->add( seconds => 60 ); is( $t->year, 1972, 'year is 1972' ); is( $t->minute, 59, 'minute is 59' ); is( $t->second, 20, 'second is 20' ); # 1972-07-01T00:00:19 UTC $t->add( seconds => 60 ); is( $t->year, 1972, 'year is 1972' ); is( $t->minute, 0, 'minute is 0' ); is( $t->second, 19, 'second is 19' ); # 1972-06-30T23:59:60 UTC $t->subtract( seconds => 20 ); is( $t->year, 1972, 'year is 1972' ); is( $t->minute, 59, 'minute is 59' ); is( $t->second, 60, 'second is 60' ); is( $t->{utc_rd_secs}, 86400, 'utc_rd_secs is 86400' ); # subtract_datetime my $t2 = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 0, second => 20, time_zone => 'UTC', ); my $dur = $t2->subtract_datetime_absolute($t1); is( $dur->delta_seconds, 121, 'delta_seconds is 121' ); $dur = $t1->subtract_datetime_absolute($t2); is( $dur->delta_seconds, -121, 'delta_seconds is -121' ); } { # tests using floating times # a floating time has no leap seconds my $t = DateTime->new( year => 1971, month => 12, day => 31, hour => 23, minute => 58, second => 20, time_zone => 'floating', ); my $t1 = $t->clone; $t->add( seconds => 60 ); is( $t->minute, 59, 'min' ); is( $t->second, 20, 'sec' ); $t->add( seconds => 60 ); is( $t->minute, 0, 'min' ); is( $t->second, 20, 'sec' ); # subtract_datetime, using floating times my $t2 = DateTime->new( year => 1972, month => 1, day => 1, hour => 0, minute => 0, second => 20, time_zone => 'floating', ); my $dur = $t2->subtract_datetime_absolute($t1); is( $dur->delta_seconds, 120, 'delta_seconds is 120' ); $dur = $t1->subtract_datetime_absolute($t2); is( $dur->delta_seconds, -120, 'delta_seconds is -120' ); } { # tests using time zones # leap seconds occur during _UTC_ midnight # 1972-06-30 20:58:20 -03:00 = 1972-06-30 23:58:20 UTC my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 58, second => 20, time_zone => 'America/Sao_Paulo', ); $t->add( seconds => 60 ); is( $t->datetime, '1972-06-30T20:59:20', 'normal add' ); is( $t->minute, 59, 'min' ); is( $t->second, 20, 'sec' ); $t->add( seconds => 60 ); is( $t->datetime, '1972-06-30T21:00:19', 'add over a leap second' ); is( $t->minute, 0, 'min' ); is( $t->second, 19, 'sec' ); $t->subtract( seconds => 20 ); is( $t->datetime, '1972-06-30T20:59:60', 'subtract over a leap second' ); is( $t->minute, 59, 'min' ); is( $t->second, 60, 'sec' ); is( $t->{utc_rd_secs}, 86400, 'rd_sec' ); } # test that we can set second to 60 (negative offset) { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 59, second => 60, time_zone => 'America/Sao_Paulo', ); is( $t->second, 60, 'second set to 60 in constructor' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 21, minute => 0, second => 0, time_zone => 'America/Sao_Paulo', ); is( $t->second, 0, 'datetime just after leap second' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 21, minute => 0, second => 1, time_zone => 'America/Sao_Paulo', ); is( $t->second, 1, 'datetime two seconds after leap second' ); } # test that we can set second to 60 (negative offset) { is( exception { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 22, minute => 59, second => 60, time_zone => '-0100', ); is( $t->second, 60, 'second set to 60 in constructor, negative TZ offset' ); }, undef, 'can set second to 60 in constructor' ); } # test that we can set second to 60 (positive offset) { is( exception { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 59, second => 60, time_zone => '+0100', ); is( $t->second, 60, 'second set to 60 in constructor, positive TZ offset' ); }, undef, 'can set second to 60 with positive TZ offset' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 59, second => 59, time_zone => '+0100', ); is( $t->second, 59, 'datetime just before leap second' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 1, minute => 0, second => 0, time_zone => '+0100', ); is( $t->second, 0, 'datetime just after leap second' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 1, minute => 0, second => 1, time_zone => '+0100', ); is( $t->second, 1, 'datetime two seconds after leap second' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 0, second => 29, time_zone => '+00:00:30', ); is( $t->second, 29, 'time zone +00:00:30 and leap seconds, second value' ); is( $t->minute, 0, 'time zone +00:00:30 and leap seconds, minute value' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 59, second => 60, time_zone => 'America/Sao_Paulo', ); $t->set_time_zone('UTC'); is( $t->second, 60, 'second after setting time zone' ); is( $t->hour, 23, 'hour after setting time zone' ); $t->add( days => 1 ); is( $t->datetime, '1972-07-02T00:00:00', 'add 1 day starting on leap second' ); $t->subtract( days => 1 ); is( $t->datetime, '1972-07-01T00:00:00', 'add and subtract 1 day starting on leap second' ); is( $t->leap_seconds, 1, 'datetime has 1 leap second' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 59, second => 59, time_zone => 'UTC', ); is( $t->epoch, 78796799, 'epoch just before first leap second is 78796799' ); $t->add( seconds => 1 ); is( $t->epoch, 78796800, 'epoch of first leap second is 78796800' ); $t->add( seconds => 1 ); is( $t->epoch, 78796800, 'epoch of first second after first leap second is 78796700' ); } { my $dt = DateTime->new( year => 2003, time_zone => 'UTC' ); is( $dt->leap_seconds, 22, 'datetime has 22 leap seconds' ); } { my $dt = DateTime->new( year => 2003, time_zone => 'floating' ); is( $dt->leap_seconds, 0, 'floating datetime has 0 leap seconds' ); } # date math across leap seconds distinguishes between minutes and second { my $t = DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 30, time_zone => 'UTC' ); $t->add( minutes => 1 ); is( $t->year, 1973, '+1 minute, year == 1973' ); is( $t->month, 1, '+1 minute, month == 1' ); is( $t->day, 1, '+1 minute, day == 1' ); is( $t->hour, 0, '+1 minute, hour == 0' ); is( $t->minute, 0, '+1 minute, minute == 0' ); is( $t->second, 30, '+1 minute, second == 30' ); } { my $t = DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 30, time_zone => 'UTC' ); $t->add( seconds => 60 ); is( $t->year, 1973, '+60 seconds, year == 1973' ); is( $t->month, 1, '+60 seconds, month == 1' ); is( $t->day, 1, '+60 seconds, day == 1' ); is( $t->hour, 0, '+60 seconds, hour == 0' ); is( $t->minute, 0, '+60 seconds, minute == 0' ); is( $t->second, 29, '+60 seconds, second == 29' ); } { my $t = DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 30, time_zone => 'UTC' ); $t->add( minutes => 1, seconds => 1 ); is( $t->year, 1973, '+1 minute & 1 second, year == 1973' ); is( $t->month, 1, '+1 minute & 1 second, month == 1' ); is( $t->day, 1, '+1 minute & 1 second, day == 1' ); is( $t->hour, 0, '+1 minute & 1 second, hour == 0' ); is( $t->minute, 0, '+1 minute & 1 second, minute == 0' ); is( $t->second, 31, '+1 minute & 1 second, second == 31' ); } { ok( exception { DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 61, time_zone => 'UTC', ); }, 'Cannot give second of 61 except when it matches a leap second' ); ok( exception { DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 58, second => 60, time_zone => 'UTC', ); }, 'Cannot give second of 60 except when it matches a leap second' ); ok( exception { DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 60, time_zone => 'floating', ); }, 'Cannot give second of 60 with floating time zone' ); } { my $dt1 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 59, second => 60, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 58, second => 50, time_zone => 'UTC', ); my $pos_dur = $dt1 - $dt2; is( $pos_dur->delta_minutes, 1, 'delta_minutes is 1' ); is( $pos_dur->delta_seconds, 10, 'delta_seconds is 10' ); my $neg_dur = $dt2 - $dt1; is( $neg_dur->delta_minutes, -1, 'delta_minutes is -1' ); is( $neg_dur->delta_seconds, -10, 'delta_seconds is -10' ); } { my $dt1 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 59, second => 55, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 58, second => 50, time_zone => 'UTC', ); my $pos_dur = $dt1 - $dt2; is( $pos_dur->delta_minutes, 1, 'delta_minutes is 1' ); is( $pos_dur->delta_seconds, 5, 'delta_seconds is 5' ); my $neg_dur = $dt2 - $dt1; is( $neg_dur->delta_minutes, -1, 'delta_minutes is -1' ); is( $neg_dur->delta_seconds, -5, 'delta_seconds is -5' ); } { my $dt1 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 59, second => 55, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 1999, month => 1, day => 1, hour => 0, minute => 0, second => 30, time_zone => 'UTC', ); my $pos_dur = $dt2 - $dt1; is( $pos_dur->delta_minutes, 0, 'delta_minutes is 0' ); is( $pos_dur->delta_seconds, 36, 'delta_seconds is 36' ); my $neg_dur = $dt1 - $dt2; is( $neg_dur->delta_minutes, 0, 'delta_minutes is 0' ); is( $neg_dur->delta_seconds, -36, 'delta_seconds is -36' ); } # catch off-by-one when carrying a leap second { my $dt1 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 59, second => 0, nanosecond => 1, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 1999, month => 1, day => 1, hour => 0, minute => 0, second => 0, time_zone => 'UTC', ); my $pos_dur = $dt2 - $dt1; is( $pos_dur->delta_minutes, 0, 'delta_minutes is 0' ); is( $pos_dur->delta_seconds, 60, 'delta_seconds is 60' ); is( $pos_dur->delta_nanoseconds, 999999999, 'delta_nanoseconds is 999...' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->add( days => 2 ); is( $dt->datetime, '1972-07-02T23:58:20', 'add two days crossing a leap second (UTC)' ); } # a bunch of tests that math works across a leap second for various time zones { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->add( days => 2 ); is( $dt->datetime, '1972-07-02T20:58:20', 'add two days crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 1, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->add( days => 2 ); is( $dt->datetime, '1972-07-03T02:58:20', 'add two days crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->add( hours => 48 ); is( $dt->datetime, '1972-07-02T23:58:20', 'add 48 hours crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->add( hours => 48 ); is( $dt->datetime, '1972-07-02T20:58:20', 'add 48 hours crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 1, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->add( hours => 48 ); is( $dt->datetime, '1972-07-03T02:58:20', 'add 48 hours crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->add( minutes => 2880 ); is( $dt->datetime, '1972-07-02T23:58:20', 'add 2880 minutes crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->add( minutes => 2880 ); is( $dt->datetime, '1972-07-02T20:58:20', 'add 2880 minutes crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 1, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->add( minutes => 2880 ); is( $dt->datetime, '1972-07-03T02:58:20', 'add 2880 minutes crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->add( seconds => 172801 ); is( $dt->datetime, '1972-07-02T23:58:20', 'add 172801 seconds crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->add( seconds => 172801 ); is( $dt->datetime, '1972-07-02T20:58:20', 'add 172801 seconds crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 1, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->add( seconds => 172801 ); is( $dt->datetime, '1972-07-03T02:58:20', 'add 172801 seconds crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->subtract( days => 2 ); is( $dt->datetime, '1972-06-30T23:58:20', 'subtract two days crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->subtract( days => 2 ); is( $dt->datetime, '1972-06-30T20:58:20', 'subtract two days crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 3, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->subtract( days => 2 ); is( $dt->datetime, '1972-07-01T02:58:20', 'subtract two days crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->subtract( hours => 48 ); is( $dt->datetime, '1972-06-30T23:58:20', 'subtract 48 hours crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->subtract( hours => 48 ); is( $dt->datetime, '1972-06-30T20:58:20', 'subtract 48 hours crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 3, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->subtract( hours => 48 ); is( $dt->datetime, '1972-07-01T02:58:20', 'subtract 48 hours crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->subtract( minutes => 2880 ); is( $dt->datetime, '1972-06-30T23:58:20', 'subtract 2880 minutes crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->subtract( minutes => 2880 ); is( $dt->datetime, '1972-06-30T20:58:20', 'subtract 2880 minutes crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 3, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->subtract( minutes => 2880 ); is( $dt->datetime, '1972-07-01T02:58:20', 'subtract 2880 minutes crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->subtract( seconds => 172801 ); is( $dt->datetime, '1972-06-30T23:58:20', 'subtract 172801 seconds crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->subtract( seconds => 172801 ); is( $dt->datetime, '1972-06-30T20:58:20', 'subtract 172801 seconds crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 3, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->subtract( seconds => 172801 ); is( $dt->datetime, '1972-07-01T02:58:20', 'subtract 172801 seconds crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 1, hour => 12, minute => 58, second => 20, time_zone => '+1200', ); $dt->set_time_zone('-1200'); is( $dt->datetime, '1972-06-30T12:58:20', '24 hour time zone change near leap second' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 12, minute => 58, second => 20, time_zone => '-1200', ); $dt->set_time_zone('+1200'); is( $dt->datetime, '1972-07-01T12:58:20', '24 hour time zone change near leap second' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 0, minute => 59, second => 59, time_zone => '+0100' ); is( $dt->datetime, '1997-07-01T00:59:59', '+0100 time leap second T-1' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-06-30T23:59:59', 'UTC time leap second T-1' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 0, minute => 59, second => 60, time_zone => '+0100' ); is( $dt->datetime, '1997-07-01T00:59:60', 'local time leap second T-0' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-06-30T23:59:60', 'UTC time leap second T-0' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 1, minute => 0, second => 0, time_zone => '+0100' ); is( $dt->datetime, '1997-07-01T01:00:00', 'local time leap second T+1' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-07-01T00:00:00', 'UTC time leap second T+1' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 23, minute => 59, second => 59, time_zone => '+0100' ); is( $dt->datetime, '1997-07-01T23:59:59', 'local time end of leap second day' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-07-01T22:59:59', 'UTC time end of leap second day' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 22, minute => 59, second => 59, time_zone => '-0100' ); is( $dt->datetime, '1997-06-30T22:59:59', '-0100 time leap second T-1' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-06-30T23:59:59', 'UTC time leap second T-1' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 22, minute => 59, second => 60, time_zone => '-0100' ); is( $dt->datetime, '1997-06-30T22:59:60', '-0100 time leap second T-0' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-06-30T23:59:60', 'UTC time leap second T-0' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 0, second => 0, time_zone => '-0100' ); is( $dt->datetime, '1997-06-30T23:00:00', '-0100 time leap second T+1' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-07-01T00:00:00', 'UTC time leap second T+1' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 59, time_zone => 'UTC' ); is( $dt->datetime, '1997-06-30T23:59:59', 'UTC time leap second T-1' ); $dt->set_time_zone('+0100'); is( $dt->datetime, '1997-07-01T00:59:59', '+0100 time leap second T-1' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 60, time_zone => 'UTC' ); is( $dt->datetime, '1997-06-30T23:59:60', 'UTC time leap second T-0' ); $dt->set_time_zone('+0100'); is( $dt->datetime, '1997-07-01T00:59:60', '+0100 time leap second T-0' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 0, minute => 0, second => 0, time_zone => 'UTC' ); is( $dt->datetime, '1997-07-01T00:00:00', 'UTC time leap second T+1' ); $dt->set_time_zone('+0100'); is( $dt->datetime, '1997-07-01T01:00:00', '+0100 time leap second T+1' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 59, time_zone => 'UTC' ); is( $dt->datetime, '1997-06-30T23:59:59', 'UTC time end of leap second day' ); $dt->set_time_zone('+0100'); is( $dt->datetime, '1997-07-01T00:59:59', '+0100 time end of leap second day' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 59, time_zone => 'UTC' ); is( $dt->datetime, '1997-06-30T23:59:59', 'UTC time leap second T-1' ); $dt->set_time_zone('-0100'); is( $dt->datetime, '1997-06-30T22:59:59', '-0100 time leap second T-1' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 60, time_zone => 'UTC' ); is( $dt->datetime, '1997-06-30T23:59:60', 'UTC time leap second T-0' ); $dt->set_time_zone('-0100'); is( $dt->datetime, '1997-06-30T22:59:60', '-0100 time leap second T-0' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 0, minute => 0, second => 0, time_zone => 'UTC' ); is( $dt->datetime, '1997-07-01T00:00:00', 'UTC time leap second T+1' ); $dt->set_time_zone('-0100'); is( $dt->datetime, '1997-06-30T23:00:00', '-0100 time leap second T+1' ); } { my $dt = DateTime->new( year => 2005, month => 12, day => 31, hour => 23, minute => 59, second => 60, time_zone => 'UTC' ); is( $dt->second, 60, 'leap second at end of 2005 is allowed' ); } { my $dt = DateTime->new( year => 2005, month => 12, day => 31, hour => 23, minute => 59, second => 59, time_zone => 'UTC', ); $dt->add( seconds => 1 ); is( $dt->datetime, '2005-12-31T23:59:60', 'dt is 2005-12-31T23:59:60' ); $dt->add( seconds => 1 ); is( $dt->datetime, '2006-01-01T00:00:00', 'dt is 2006-01-01T00:00:00' ); } # bug reported by Mike Schilli - addition got "stuck" at 60 seconds # and never rolled over to the following day { my $dt = DateTime->new( year => 2005, month => 12, day => 31, hour => 23, minute => 59, second => 59, time_zone => 'UTC', ); $dt->add( seconds => 1 ); is( $dt->datetime, '2005-12-31T23:59:60', 'dt is 2005-12-31T23:59:60' ); $dt->add( seconds => 1 ); is( $dt->datetime, '2006-01-01T00:00:00', 'dt is 2006-01-01T00:00:00' ); } # and this makes sure that fix for the above bug didn't break # _non-leapsecond_ second addition { my $dt = DateTime->new( year => 2005, month => 12, day => 30, hour => 23, minute => 59, second => 58, time_zone => 'UTC', ); $dt->add( seconds => 1 ); is( $dt->datetime, '2005-12-30T23:59:59', 'dt is 2005-12-30T23:59:59' ); $dt->add( seconds => 1 ); is( $dt->datetime, '2005-12-31T00:00:00', 'dt is 2005-12-31T00:00:00' ); } { for my $date ( [ 1972, 6, 30 ], [ 1972, 12, 31 ], [ 1973, 12, 31 ], [ 1974, 12, 31 ], [ 1975, 12, 31 ], [ 1976, 12, 31 ], [ 1977, 12, 31 ], [ 1978, 12, 31 ], [ 1979, 12, 31 ], [ 1981, 6, 30 ], [ 1982, 6, 30 ], [ 1983, 6, 30 ], [ 1985, 6, 30 ], [ 1987, 12, 31 ], [ 1989, 12, 31 ], [ 1990, 12, 31 ], [ 1992, 6, 30 ], [ 1993, 6, 30 ], [ 1994, 6, 30 ], [ 1995, 12, 31 ], [ 1997, 6, 30 ], [ 1998, 12, 31 ], [ 2005, 12, 31 ], [ 2008, 12, 31 ], [ 2012, 6, 30 ], [ 2015, 6, 30 ], [ 2016, 12, 31 ], ) { my $formatted = join '-', map { sprintf( '%02d', $_ ) } @{$date}; my $dt; is( exception { $dt = DateTime->new( year => $date->[0], month => $date->[1], day => $date->[2], hour => 23, minute => 59, second => 60, time_zone => 'UTC', ); }, undef, "We can make a DateTime object for the leap second on $formatted" ); is( DateTime::LeapSecond::day_length( ( $dt->utc_rd_values )[0] ), 86401, "DateTime::LeapSecond::day_length returns 86401 for $formatted" ); } } done_testing(); DateTime-1.46/t/33seconds-offset.t0000644000175000017500000000400113240151623016510 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 58, second => 59, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-06-30T23:59:29', '+00:00:30 leap second T-61' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 29, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-06-30T23:59:59', '+00:00:30 leap second T-31' ); } { local $TODO = 'offsets with seconds are broken near leap seconds'; my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 30, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-06-30T23:59:60', '+00:00:30 leap second T-30' ); } { local $TODO = 'offsets with seconds are broken near leap seconds'; my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 31, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-07-01T00:00:00', '+00:00:30 leap second T-29' ); } { local $TODO = 'offsets with seconds are broken near leap seconds'; my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 60, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-07-01T00:00:30', '+00:00:30 leap second T-0' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 0, minute => 0, second => 0, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-07-01T00:00:30', '+00:00:30 leap second T+1' ); } done_testing(); DateTime-1.46/t/28dow.t0000644000175000017500000000277613240151623014404 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 0 ); is( $dt->year, 0, 'year is 0' ); is( $dt->month, 1, 'month is 1' ); is( $dt->day, 1, 'day is 1' ); is( $dt->day_of_week, 6, 'day of week is 6' ); } { my $dt = DateTime->new( year => 0, month => 12, day => 31 ); is( $dt->year, 0, 'year is 0' ); is( $dt->month, 12, 'month is 12' ); is( $dt->day, 31, 'day is 31' ); is( $dt->day_of_week, 7, 'day of week is 7' ); } { my $dt = DateTime->new( year => -1 ); is( $dt->year, -1, 'year is -1' ); is( $dt->month, 1, 'month is 1' ); is( $dt->day, 1, 'day is 1' ); is( $dt->day_of_week, 5, 'day of week is 5' ); } { my $dt = DateTime->new( year => 1 ); is( $dt->year, 1, 'year is 1' ); is( $dt->month, 1, 'month is 1' ); is( $dt->day, 1, 'day is 1' ); is( $dt->day_of_week, 1, 'day of week is 1' ); } { my $dow = 1; for my $year ( 1, 0, -1 ) { my $days_in_year = $year ? 365 : 366; for my $doy ( reverse 1 .. $days_in_year ) { is( DateTime->from_day_of_year( year => $year, day_of_year => $doy, )->day_of_week, $dow, "day of week for day $doy of year $year is $dow" ); $dow--; $dow = 7 if $dow == 0; } } } done_testing(); DateTime-1.46/t/31formatter.t0000644000175000017500000000442313240151623015577 0ustar autarchautarchuse strict; use warnings; use Test::Fatal; use Test::More; use DateTime; { package Formatter; sub new { return bless {}, __PACKAGE__; } sub format_datetime { $_[1]->strftime('%Y%m%d %T'); } } my $formatter = Formatter->new(); { is( exception { DateTime->from_epoch( epoch => time(), formatter => $formatter ) }, undef, 'passed formatter to from_epoch' ); } { is( exception { DateTime->new( year => 2004, month => 9, day => 2, hour => 13, minute => 23, second => 34, formatter => $formatter ); }, undef, 'passed formatter to new' ); } { my $from = DateTime->new( year => 2004, month => 9, day => 2, hour => 13, minute => 23, second => 34, formatter => $formatter ); my $dt; is( exception { $dt = DateTime->from_object( object => $from, formatter => $formatter ); }, undef, 'passed formatter to from_object' ); is( $dt->formatter, $formatter, 'check from_object copies formatter' ); is( $dt->stringify(), '20040902 13:23:34', 'Format datetime' ); # check stringification (with formatter) is( $dt->stringify, "$dt", 'Stringification (with formatter)' ); # check that set() and truncate() don't lose formatter $dt->set( hour => 3 ); is( $dt->stringify, '20040902 03:23:34', 'formatter is preserved after set()' ); $dt->truncate( to => 'minute' ); is( $dt->stringify, '20040902 03:23:00', 'formatter is preserved after truncate()' ); # check if the default behavior works $dt->set_formatter(undef); is( $dt->stringify(), $dt->iso8601, 'Default iso8601 works' ); # check stringification (default) is( $dt->stringify, "$dt", 'Stringification (no formatter -> format_datetime)' ); is( $dt->iso8601, "$dt", 'Stringification (no formatter -> iso8601)' ); } done_testing(); DateTime-1.46/t/25add-subtract.t0000644000175000017500000000160213240151623016150 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; # exercises a bug found in Perl version of _normalize_tai_seconds - # fixed in 0.15 { my $dt = DateTime->new( year => 2000, month => 12 ); $dt->add( months => 1 )->truncate( to => 'month' ) ->subtract( seconds => 1 ); is( $dt->year, 2000, 'year is 2001' ); is( $dt->month, 12, 'month is 12' ); is( $dt->hour, 23, 'hour is 23' ); is( $dt->minute, 59, 'minute is 59' ); is( $dt->second, 59, 'second is 59' ); } { my $dt = DateTime->new( year => 2000, month => 12 ); my $dt2 = $dt->clone->add( months => 1 )->subtract( seconds => 1 ); is( $dt2->year, 2000, 'year is 2001' ); is( $dt2->month, 12, 'month is 12' ); is( $dt2->hour, 23, 'hour is 23' ); is( $dt2->minute, 59, 'minute is 59' ); is( $dt2->second, 59, 'second is 59' ); } done_testing(); DateTime-1.46/inc/0000775000175000017500000000000013240151623013550 5ustar autarchautarchDateTime-1.46/inc/LeapSecondsHeader.pm0000644000175000017500000001131613240151623017417 0ustar autarchautarchpackage LeapSecondsHeader; use strict; use warnings; use autodie; my $VERSION = 0.04; use Dist::Zilla::File::InMemory; use Moose; has _leap_second_data => ( is => 'ro', isa => 'HashRef', lazy => 1, builder => '_build_leap_second_data', ); with 'Dist::Zilla::Role::FileGatherer'; sub gather_files { my $self = shift; $self->add_file( Dist::Zilla::File::InMemory->new( name => 'leap_seconds.h', encoding => 'bytes', content => $self->_header, ), ); } my $x = 1; my %months = map { $_ => $x++ } qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ); sub _build_leap_second_data { my $self = shift; open my $fh, '<', 'leaptab.txt'; my @leap_seconds; my @rd; my %rd_length; my $value = -1; while (<$fh>) { my ( $year, $mon, $day, $leap_seconds ) = split /\s+/; $mon =~ s/\W//; $leap_seconds =~ s/^([+-])//; my $mult = $1 eq '+' ? 1 : -1; my $utc_epoch = _ymd2rd( $year, $months{$mon}, $day ); $value += $leap_seconds * $mult; push @leap_seconds, $value; push @rd, $utc_epoch; $rd_length{ $utc_epoch - 1 } = $leap_seconds; } close $fh; push @leap_seconds, ++$value; return { leap_seconds => \@leap_seconds, rd => \@rd, rd_length => \%rd_length, }; } sub _header { my $self = shift; my ( $leap_seconds, $rd, $rd_length ) = @{ $self->_leap_second_data }{qw( leap_seconds rd rd_length )}; my $set_leap_seconds = <<"EOF"; #define SET_LEAP_SECONDS(utc_rd, ls) \\ { \\ { \\ if (utc_rd < $rd->[0]) { \\ ls = $leap_seconds->[0]; \\ EOF for ( my $x = 1; $x < @{$rd}; $x++ ) { my $condition = $x == @{$rd} ? "utc_rd < $rd->[$x]" : "utc_rd >= $rd->[$x - 1] && utc_rd < $rd->[$x]"; $set_leap_seconds .= <<"EOF" } else if ($condition) { \\ ls = $leap_seconds->[$x]; \\ EOF } $set_leap_seconds .= <<"EOF"; } else { \\ ls = $leap_seconds->[-1]; \\ } \\ } \\ } EOF my $set_extra_seconds = <<"EOF"; #define SET_EXTRA_SECONDS(utc_rd, es) \\ { \\ { \\ es = 0; \\ switch (utc_rd) { \\ EOF my $set_day_length = <<"EOF"; #define SET_DAY_LENGTH(utc_rd, dl) \\ { \\ { \\ dl = 86400; \\ switch (utc_rd) { \\ EOF foreach my $utc_rd ( sort keys %{$rd_length} ) { $set_extra_seconds .= <<"EOF"; case $utc_rd: es = $rd_length->{$utc_rd}; break; \\ EOF $set_day_length .= <<"EOF"; case $utc_rd: dl = 86400 + $rd_length->{$utc_rd}; break; \\ EOF } $set_extra_seconds .= <<"EOF"; } \\ } \\ } EOF $set_day_length .= <<"EOF"; } \\ } \\ } EOF my $generator = ref $self; my $header = <<"EOF"; /* This file is auto-generated by the leap second code generator ($VERSION). This code generator comes with the DateTime.pm module distribution in the tools/ directory Generated $generator. Do not edit this file directly. */ EOF return join q{}, ( $header, $set_leap_seconds, $set_extra_seconds, $set_day_length, ); } # from lib/DateTimePP.pm sub _ymd2rd { use integer; my ( $y, $m, $d ) = @_; my $adj; # make month in range 3..14 (treat Jan & Feb as months 13..14 of # prev year) if ( $m <= 2 ) { $y -= ( $adj = ( 14 - $m ) / 12 ); $m += 12 * $adj; } elsif ( $m > 14 ) { $y += ( $adj = ( $m - 3 ) / 12 ); $m -= 12 * $adj; } # make year positive (oh, for a use integer 'sane_div'!) if ( $y < 0 ) { $d -= 146097 * ( $adj = ( 399 - $y ) / 400 ); $y += 400 * $adj; } # add: day of month, days of previous 0-11 month period that began # w/March, days of previous 0-399 year period that began w/March # of a 400-multiple year), days of any 400-year periods before # that, and 306 days to adjust from Mar 1, year 0-relative to Jan # 1, year 1-relative (whew) $d += ( $m * 367 - 1094 ) / 12 + $y % 100 * 1461 / 4 + ( $y / 100 * 36524 + $y / 400 ) - 306; } 1; DateTime-1.46/leap_seconds.h0000644000175000017500000001377013240151623015615 0ustar autarchautarch/* This file is auto-generated by the leap second code generator (0.04). This code generator comes with the DateTime.pm module distribution in the tools/ directory Generated LeapSecondsHeader. Do not edit this file directly. */ #define SET_LEAP_SECONDS(utc_rd, ls) \ { \ { \ if (utc_rd < 720075) { \ ls = 0; \ } else if (utc_rd >= 720075 && utc_rd < 720259) { \ ls = 1; \ } else if (utc_rd >= 720259 && utc_rd < 720624) { \ ls = 2; \ } else if (utc_rd >= 720624 && utc_rd < 720989) { \ ls = 3; \ } else if (utc_rd >= 720989 && utc_rd < 721354) { \ ls = 4; \ } else if (utc_rd >= 721354 && utc_rd < 721720) { \ ls = 5; \ } else if (utc_rd >= 721720 && utc_rd < 722085) { \ ls = 6; \ } else if (utc_rd >= 722085 && utc_rd < 722450) { \ ls = 7; \ } else if (utc_rd >= 722450 && utc_rd < 722815) { \ ls = 8; \ } else if (utc_rd >= 722815 && utc_rd < 723362) { \ ls = 9; \ } else if (utc_rd >= 723362 && utc_rd < 723727) { \ ls = 10; \ } else if (utc_rd >= 723727 && utc_rd < 724092) { \ ls = 11; \ } else if (utc_rd >= 724092 && utc_rd < 724823) { \ ls = 12; \ } else if (utc_rd >= 724823 && utc_rd < 725737) { \ ls = 13; \ } else if (utc_rd >= 725737 && utc_rd < 726468) { \ ls = 14; \ } else if (utc_rd >= 726468 && utc_rd < 726833) { \ ls = 15; \ } else if (utc_rd >= 726833 && utc_rd < 727380) { \ ls = 16; \ } else if (utc_rd >= 727380 && utc_rd < 727745) { \ ls = 17; \ } else if (utc_rd >= 727745 && utc_rd < 728110) { \ ls = 18; \ } else if (utc_rd >= 728110 && utc_rd < 728659) { \ ls = 19; \ } else if (utc_rd >= 728659 && utc_rd < 729206) { \ ls = 20; \ } else if (utc_rd >= 729206 && utc_rd < 729755) { \ ls = 21; \ } else if (utc_rd >= 729755 && utc_rd < 732312) { \ ls = 22; \ } else if (utc_rd >= 732312 && utc_rd < 733408) { \ ls = 23; \ } else if (utc_rd >= 733408 && utc_rd < 734685) { \ ls = 24; \ } else if (utc_rd >= 734685 && utc_rd < 735780) { \ ls = 25; \ } else if (utc_rd >= 735780 && utc_rd < 736330) { \ ls = 26; \ } else { \ ls = 27; \ } \ } \ } #define SET_EXTRA_SECONDS(utc_rd, es) \ { \ { \ es = 0; \ switch (utc_rd) { \ case 720074: es = 1; break; \ case 720258: es = 1; break; \ case 720623: es = 1; break; \ case 720988: es = 1; break; \ case 721353: es = 1; break; \ case 721719: es = 1; break; \ case 722084: es = 1; break; \ case 722449: es = 1; break; \ case 722814: es = 1; break; \ case 723361: es = 1; break; \ case 723726: es = 1; break; \ case 724091: es = 1; break; \ case 724822: es = 1; break; \ case 725736: es = 1; break; \ case 726467: es = 1; break; \ case 726832: es = 1; break; \ case 727379: es = 1; break; \ case 727744: es = 1; break; \ case 728109: es = 1; break; \ case 728658: es = 1; break; \ case 729205: es = 1; break; \ case 729754: es = 1; break; \ case 732311: es = 1; break; \ case 733407: es = 1; break; \ case 734684: es = 1; break; \ case 735779: es = 1; break; \ case 736329: es = 1; break; \ } \ } \ } #define SET_DAY_LENGTH(utc_rd, dl) \ { \ { \ dl = 86400; \ switch (utc_rd) { \ case 720074: dl = 86400 + 1; break; \ case 720258: dl = 86400 + 1; break; \ case 720623: dl = 86400 + 1; break; \ case 720988: dl = 86400 + 1; break; \ case 721353: dl = 86400 + 1; break; \ case 721719: dl = 86400 + 1; break; \ case 722084: dl = 86400 + 1; break; \ case 722449: dl = 86400 + 1; break; \ case 722814: dl = 86400 + 1; break; \ case 723361: dl = 86400 + 1; break; \ case 723726: dl = 86400 + 1; break; \ case 724091: dl = 86400 + 1; break; \ case 724822: dl = 86400 + 1; break; \ case 725736: dl = 86400 + 1; break; \ case 726467: dl = 86400 + 1; break; \ case 726832: dl = 86400 + 1; break; \ case 727379: dl = 86400 + 1; break; \ case 727744: dl = 86400 + 1; break; \ case 728109: dl = 86400 + 1; break; \ case 728658: dl = 86400 + 1; break; \ case 729205: dl = 86400 + 1; break; \ case 729754: dl = 86400 + 1; break; \ case 732311: dl = 86400 + 1; break; \ case 733407: dl = 86400 + 1; break; \ case 734684: dl = 86400 + 1; break; \ case 735779: dl = 86400 + 1; break; \ case 736329: dl = 86400 + 1; break; \ } \ } \ } DateTime-1.46/ppport.h0000644000175000017500000060553013240151623014503 0ustar autarchautarch#if 0 <<'SKIP'; #endif /* ---------------------------------------------------------------------- ppport.h -- Perl/Pollution/Portability Version 3.36 Automatically created by Devel::PPPort running under perl 5.026001. Do NOT edit this file directly! -- Edit PPPort_pm.PL and the includes in parts/inc/ instead. Use 'perldoc ppport.h' to view the documentation below. ---------------------------------------------------------------------- SKIP =pod =head1 NAME ppport.h - Perl/Pollution/Portability version 3.36 =head1 SYNOPSIS perl ppport.h [options] [source files] Searches current directory for files if no [source files] are given --help show short help --version show version --patch=file write one patch file with changes --copy=suffix write changed copies with suffix --diff=program use diff program and options --compat-version=version provide compatibility with Perl version --cplusplus accept C++ comments --quiet don't output anything except fatal errors --nodiag don't show diagnostics --nohints don't show hints --nochanges don't suggest changes --nofilter don't filter input files --strip strip all script and doc functionality from ppport.h --list-provided list provided API --list-unsupported list unsupported API --api-info=name show Perl API portability information =head1 COMPATIBILITY This version of F is designed to support operation with Perl installations back to 5.003, and has been tested up to 5.20. =head1 OPTIONS =head2 --help Display a brief usage summary. =head2 --version Display the version of F. =head2 --patch=I If this option is given, a single patch file will be created if any changes are suggested. This requires a working diff program to be installed on your system. =head2 --copy=I If this option is given, a copy of each file will be saved with the given suffix that contains the suggested changes. This does not require any external programs. Note that this does not automagically add a dot between the original filename and the suffix. If you want the dot, you have to include it in the option argument. If neither C<--patch> or C<--copy> are given, the default is to simply print the diffs for each file. This requires either C or a C program to be installed. =head2 --diff=I Manually set the diff program and options to use. The default is to use C, when installed, and output unified context diffs. =head2 --compat-version=I Tell F to check for compatibility with the given Perl version. The default is to check for compatibility with Perl version 5.003. You can use this option to reduce the output of F if you intend to be backward compatible only down to a certain Perl version. =head2 --cplusplus Usually, F will detect C++ style comments and replace them with C style comments for portability reasons. Using this option instructs F to leave C++ comments untouched. =head2 --quiet Be quiet. Don't print anything except fatal errors. =head2 --nodiag Don't output any diagnostic messages. Only portability alerts will be printed. =head2 --nohints Don't output any hints. Hints often contain useful portability notes. Warnings will still be displayed. =head2 --nochanges Don't suggest any changes. Only give diagnostic output and hints unless these are also deactivated. =head2 --nofilter Don't filter the list of input files. By default, files not looking like source code (i.e. not *.xs, *.c, *.cc, *.cpp or *.h) are skipped. =head2 --strip Strip all script and documentation functionality from F. This reduces the size of F dramatically and may be useful if you want to include F in smaller modules without increasing their distribution size too much. The stripped F will have a C<--unstrip> option that allows you to undo the stripping, but only if an appropriate C module is installed. =head2 --list-provided Lists the API elements for which compatibility is provided by F. Also lists if it must be explicitly requested, if it has dependencies, and if there are hints or warnings for it. =head2 --list-unsupported Lists the API elements that are known not to be supported by F and below which version of Perl they probably won't be available or work. =head2 --api-info=I Show portability information for API elements matching I. If I is surrounded by slashes, it is interpreted as a regular expression. =head1 DESCRIPTION In order for a Perl extension (XS) module to be as portable as possible across differing versions of Perl itself, certain steps need to be taken. =over 4 =item * Including this header is the first major one. This alone will give you access to a large part of the Perl API that hasn't been available in earlier Perl releases. Use perl ppport.h --list-provided to see which API elements are provided by ppport.h. =item * You should avoid using deprecated parts of the API. For example, using global Perl variables without the C prefix is deprecated. Also, some API functions used to have a C prefix. Using this form is also deprecated. You can safely use the supported API, as F will provide wrappers for older Perl versions. =item * If you use one of a few functions or variables that were not present in earlier versions of Perl, and that can't be provided using a macro, you have to explicitly request support for these functions by adding one or more C<#define>s in your source code before the inclusion of F. These functions or variables will be marked C in the list shown by C<--list-provided>. Depending on whether you module has a single or multiple files that use such functions or variables, you want either C or global variants. For a C function or variable (used only in a single source file), use: #define NEED_function #define NEED_variable For a global function or variable (used in multiple source files), use: #define NEED_function_GLOBAL #define NEED_variable_GLOBAL Note that you mustn't have more than one global request for the same function or variable in your project. Function / Variable Static Request Global Request ----------------------------------------------------------------------------------------- PL_parser NEED_PL_parser NEED_PL_parser_GLOBAL PL_signals NEED_PL_signals NEED_PL_signals_GLOBAL SvRX() NEED_SvRX NEED_SvRX_GLOBAL caller_cx() NEED_caller_cx NEED_caller_cx_GLOBAL eval_pv() NEED_eval_pv NEED_eval_pv_GLOBAL grok_bin() NEED_grok_bin NEED_grok_bin_GLOBAL grok_hex() NEED_grok_hex NEED_grok_hex_GLOBAL grok_number() NEED_grok_number NEED_grok_number_GLOBAL grok_numeric_radix() NEED_grok_numeric_radix NEED_grok_numeric_radix_GLOBAL grok_oct() NEED_grok_oct NEED_grok_oct_GLOBAL gv_fetchpvn_flags() NEED_gv_fetchpvn_flags NEED_gv_fetchpvn_flags_GLOBAL load_module() NEED_load_module NEED_load_module_GLOBAL mg_findext() NEED_mg_findext NEED_mg_findext_GLOBAL my_snprintf() NEED_my_snprintf NEED_my_snprintf_GLOBAL my_sprintf() NEED_my_sprintf NEED_my_sprintf_GLOBAL my_strlcat() NEED_my_strlcat NEED_my_strlcat_GLOBAL my_strlcpy() NEED_my_strlcpy NEED_my_strlcpy_GLOBAL newCONSTSUB() NEED_newCONSTSUB NEED_newCONSTSUB_GLOBAL newRV_noinc() NEED_newRV_noinc NEED_newRV_noinc_GLOBAL newSV_type() NEED_newSV_type NEED_newSV_type_GLOBAL newSVpvn_flags() NEED_newSVpvn_flags NEED_newSVpvn_flags_GLOBAL newSVpvn_share() NEED_newSVpvn_share NEED_newSVpvn_share_GLOBAL pv_display() NEED_pv_display NEED_pv_display_GLOBAL pv_escape() NEED_pv_escape NEED_pv_escape_GLOBAL pv_pretty() NEED_pv_pretty NEED_pv_pretty_GLOBAL sv_2pv_flags() NEED_sv_2pv_flags NEED_sv_2pv_flags_GLOBAL sv_2pvbyte() NEED_sv_2pvbyte NEED_sv_2pvbyte_GLOBAL sv_catpvf_mg() NEED_sv_catpvf_mg NEED_sv_catpvf_mg_GLOBAL sv_catpvf_mg_nocontext() NEED_sv_catpvf_mg_nocontext NEED_sv_catpvf_mg_nocontext_GLOBAL sv_pvn_force_flags() NEED_sv_pvn_force_flags NEED_sv_pvn_force_flags_GLOBAL sv_setpvf_mg() NEED_sv_setpvf_mg NEED_sv_setpvf_mg_GLOBAL sv_setpvf_mg_nocontext() NEED_sv_setpvf_mg_nocontext NEED_sv_setpvf_mg_nocontext_GLOBAL sv_unmagicext() NEED_sv_unmagicext NEED_sv_unmagicext_GLOBAL vload_module() NEED_vload_module NEED_vload_module_GLOBAL vnewSVpvf() NEED_vnewSVpvf NEED_vnewSVpvf_GLOBAL warner() NEED_warner NEED_warner_GLOBAL To avoid namespace conflicts, you can change the namespace of the explicitly exported functions / variables using the C macro. Just C<#define> the macro before including C: #define DPPP_NAMESPACE MyOwnNamespace_ #include "ppport.h" The default namespace is C. =back The good thing is that most of the above can be checked by running F on your source code. See the next section for details. =head1 EXAMPLES To verify whether F is needed for your module, whether you should make any changes to your code, and whether any special defines should be used, F can be run as a Perl script to check your source code. Simply say: perl ppport.h The result will usually be a list of patches suggesting changes that should at least be acceptable, if not necessarily the most efficient solution, or a fix for all possible problems. If you know that your XS module uses features only available in newer Perl releases, if you're aware that it uses C++ comments, and if you want all suggestions as a single patch file, you could use something like this: perl ppport.h --compat-version=5.6.0 --cplusplus --patch=test.diff If you only want your code to be scanned without any suggestions for changes, use: perl ppport.h --nochanges You can specify a different C program or options, using the C<--diff> option: perl ppport.h --diff='diff -C 10' This would output context diffs with 10 lines of context. If you want to create patched copies of your files instead, use: perl ppport.h --copy=.new To display portability information for the C function, use: perl ppport.h --api-info=newSVpvn Since the argument to C<--api-info> can be a regular expression, you can use perl ppport.h --api-info=/_nomg$/ to display portability information for all C<_nomg> functions or perl ppport.h --api-info=/./ to display information for all known API elements. =head1 BUGS If this version of F is causing failure during the compilation of this module, please check if newer versions of either this module or C are available on CPAN before sending a bug report. If F was generated using the latest version of C and is causing failure of this module, please file a bug report here: L Please include the following information: =over 4 =item 1. The complete output from running "perl -V" =item 2. This file. =item 3. The name and version of the module you were trying to build. =item 4. A full log of the build that failed. =item 5. Any other information that you think could be relevant. =back For the latest version of this code, please get the C module from CPAN. =head1 COPYRIGHT Version 3.x, Copyright (c) 2004-2013, Marcus Holland-Moritz. Version 2.x, Copyright (C) 2001, Paul Marquess. Version 1.x, Copyright (C) 1999, Kenneth Albanowski. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO See L. =cut use strict; # Disable broken TRIE-optimization BEGIN { eval '${^RE_TRIE_MAXBUF} = -1' if $] >= 5.009004 && $] <= 5.009005 } my $VERSION = 3.36; my %opt = ( quiet => 0, diag => 1, hints => 1, changes => 1, cplusplus => 0, filter => 1, strip => 0, version => 0, ); my($ppport) = $0 =~ /([\w.]+)$/; my $LF = '(?:\r\n|[\r\n])'; # line feed my $HS = "[ \t]"; # horizontal whitespace # Never use C comments in this file! my $ccs = '/'.'*'; my $cce = '*'.'/'; my $rccs = quotemeta $ccs; my $rcce = quotemeta $cce; eval { require Getopt::Long; Getopt::Long::GetOptions(\%opt, qw( help quiet diag! filter! hints! changes! cplusplus strip version patch=s copy=s diff=s compat-version=s list-provided list-unsupported api-info=s )) or usage(); }; if ($@ and grep /^-/, @ARGV) { usage() if "@ARGV" =~ /^--?h(?:elp)?$/; die "Getopt::Long not found. Please don't use any options.\n"; } if ($opt{version}) { print "This is $0 $VERSION.\n"; exit 0; } usage() if $opt{help}; strip() if $opt{strip}; if (exists $opt{'compat-version'}) { my($r,$v,$s) = eval { parse_version($opt{'compat-version'}) }; if ($@) { die "Invalid version number format: '$opt{'compat-version'}'\n"; } die "Only Perl 5 is supported\n" if $r != 5; die "Invalid version number: $opt{'compat-version'}\n" if $v >= 1000 || $s >= 1000; $opt{'compat-version'} = sprintf "%d.%03d%03d", $r, $v, $s; } else { $opt{'compat-version'} = 5; } my %API = map { /^(\w+)\|([^|]*)\|([^|]*)\|(\w*)$/ ? ( $1 => { ($2 ? ( base => $2 ) : ()), ($3 ? ( todo => $3 ) : ()), (index($4, 'v') >= 0 ? ( varargs => 1 ) : ()), (index($4, 'p') >= 0 ? ( provided => 1 ) : ()), (index($4, 'n') >= 0 ? ( nothxarg => 1 ) : ()), } ) : die "invalid spec: $_" } qw( ASCII_TO_NEED||5.007001|n AvFILLp|5.004050||p AvFILL||| BhkDISABLE||5.024000| BhkENABLE||5.024000| BhkENTRY_set||5.024000| BhkENTRY||| BhkFLAGS||| CALL_BLOCK_HOOKS||| CLASS|||n CPERLscope|5.005000||p CX_CURPAD_SAVE||| CX_CURPAD_SV||| C_ARRAY_END|5.013002||p C_ARRAY_LENGTH|5.008001||p CopFILEAV|5.006000||p CopFILEGV_set|5.006000||p CopFILEGV|5.006000||p CopFILESV|5.006000||p CopFILE_set|5.006000||p CopFILE|5.006000||p CopSTASHPV_set|5.006000||p CopSTASHPV|5.006000||p CopSTASH_eq|5.006000||p CopSTASH_set|5.006000||p CopSTASH|5.006000||p CopyD|5.009002|5.004050|p Copy||| CvPADLIST||5.008001| CvSTASH||| CvWEAKOUTSIDE||| DECLARATION_FOR_LC_NUMERIC_MANIPULATION||5.021010|n DEFSV_set|5.010001||p DEFSV|5.004050||p DO_UTF8||5.006000| END_EXTERN_C|5.005000||p ENTER||| ERRSV|5.004050||p EXTEND||| EXTERN_C|5.005000||p F0convert|||n FREETMPS||| GIMME_V||5.004000|n GIMME|||n GROK_NUMERIC_RADIX|5.007002||p G_ARRAY||| G_DISCARD||| G_EVAL||| G_METHOD|5.006001||p G_NOARGS||| G_SCALAR||| G_VOID||5.004000| GetVars||| GvAV||| GvCV||| GvHV||| GvSV||| Gv_AMupdate||5.011000| HEf_SVKEY|5.003070||p HeHASH||5.003070| HeKEY||5.003070| HeKLEN||5.003070| HePV||5.004000| HeSVKEY_force||5.003070| HeSVKEY_set||5.004000| HeSVKEY||5.003070| HeUTF8|5.010001|5.008000|p HeVAL||5.003070| HvENAMELEN||5.015004| HvENAMEUTF8||5.015004| HvENAME||5.013007| HvNAMELEN_get|5.009003||p HvNAMELEN||5.015004| HvNAMEUTF8||5.015004| HvNAME_get|5.009003||p HvNAME||| INT2PTR|5.006000||p IN_LOCALE_COMPILETIME|5.007002||p IN_LOCALE_RUNTIME|5.007002||p IN_LOCALE|5.007002||p IN_PERL_COMPILETIME|5.008001||p IS_NUMBER_GREATER_THAN_UV_MAX|5.007002||p IS_NUMBER_INFINITY|5.007002||p IS_NUMBER_IN_UV|5.007002||p IS_NUMBER_NAN|5.007003||p IS_NUMBER_NEG|5.007002||p IS_NUMBER_NOT_INT|5.007002||p IVSIZE|5.006000||p IVTYPE|5.006000||p IVdf|5.006000||p LEAVE||| LINKLIST||5.013006| LVRET||| MARK||| MULTICALL||5.024000| MUTABLE_PTR|5.010001||p MUTABLE_SV|5.010001||p MY_CXT_CLONE|5.009002||p MY_CXT_INIT|5.007003||p MY_CXT|5.007003||p MoveD|5.009002|5.004050|p Move||| NATIVE_TO_NEED||5.007001|n NOOP|5.005000||p NUM2PTR|5.006000||p NVTYPE|5.006000||p NVef|5.006001||p NVff|5.006001||p NVgf|5.006001||p Newxc|5.009003||p Newxz|5.009003||p Newx|5.009003||p Nullav||| Nullch||| Nullcv||| Nullhv||| Nullsv||| OP_CLASS||5.013007| OP_DESC||5.007003| OP_NAME||5.007003| OP_TYPE_IS_OR_WAS||5.019010| OP_TYPE_IS||5.019007| ORIGMARK||| OpHAS_SIBLING|5.021007||p OpLASTSIB_set|5.021011||p OpMAYBESIB_set|5.021011||p OpMORESIB_set|5.021011||p OpSIBLING|5.021007||p PAD_BASE_SV||| PAD_CLONE_VARS||| PAD_COMPNAME_FLAGS||| PAD_COMPNAME_GEN_set||| PAD_COMPNAME_GEN||| PAD_COMPNAME_OURSTASH||| PAD_COMPNAME_PV||| PAD_COMPNAME_TYPE||| PAD_RESTORE_LOCAL||| PAD_SAVE_LOCAL||| PAD_SAVE_SETNULLPAD||| PAD_SETSV||| PAD_SET_CUR_NOSAVE||| PAD_SET_CUR||| PAD_SVl||| PAD_SV||| PERLIO_FUNCS_CAST|5.009003||p PERLIO_FUNCS_DECL|5.009003||p PERL_ABS|5.008001||p PERL_BCDVERSION|5.024000||p PERL_GCC_BRACE_GROUPS_FORBIDDEN|5.008001||p PERL_HASH|5.003070||p PERL_INT_MAX|5.003070||p PERL_INT_MIN|5.003070||p PERL_LONG_MAX|5.003070||p PERL_LONG_MIN|5.003070||p PERL_MAGIC_arylen|5.007002||p PERL_MAGIC_backref|5.007002||p PERL_MAGIC_bm|5.007002||p PERL_MAGIC_collxfrm|5.007002||p PERL_MAGIC_dbfile|5.007002||p PERL_MAGIC_dbline|5.007002||p PERL_MAGIC_defelem|5.007002||p PERL_MAGIC_envelem|5.007002||p PERL_MAGIC_env|5.007002||p PERL_MAGIC_ext|5.007002||p PERL_MAGIC_fm|5.007002||p PERL_MAGIC_glob|5.024000||p PERL_MAGIC_isaelem|5.007002||p PERL_MAGIC_isa|5.007002||p PERL_MAGIC_mutex|5.024000||p PERL_MAGIC_nkeys|5.007002||p PERL_MAGIC_overload_elem|5.024000||p PERL_MAGIC_overload_table|5.007002||p PERL_MAGIC_overload|5.024000||p PERL_MAGIC_pos|5.007002||p PERL_MAGIC_qr|5.007002||p PERL_MAGIC_regdata|5.007002||p PERL_MAGIC_regdatum|5.007002||p PERL_MAGIC_regex_global|5.007002||p PERL_MAGIC_shared_scalar|5.007003||p PERL_MAGIC_shared|5.007003||p PERL_MAGIC_sigelem|5.007002||p PERL_MAGIC_sig|5.007002||p PERL_MAGIC_substr|5.007002||p PERL_MAGIC_sv|5.007002||p PERL_MAGIC_taint|5.007002||p PERL_MAGIC_tiedelem|5.007002||p PERL_MAGIC_tiedscalar|5.007002||p PERL_MAGIC_tied|5.007002||p PERL_MAGIC_utf8|5.008001||p PERL_MAGIC_uvar_elem|5.007003||p PERL_MAGIC_uvar|5.007002||p PERL_MAGIC_vec|5.007002||p PERL_MAGIC_vstring|5.008001||p PERL_PV_ESCAPE_ALL|5.009004||p PERL_PV_ESCAPE_FIRSTCHAR|5.009004||p PERL_PV_ESCAPE_NOBACKSLASH|5.009004||p PERL_PV_ESCAPE_NOCLEAR|5.009004||p PERL_PV_ESCAPE_QUOTE|5.009004||p PERL_PV_ESCAPE_RE|5.009005||p PERL_PV_ESCAPE_UNI_DETECT|5.009004||p PERL_PV_ESCAPE_UNI|5.009004||p PERL_PV_PRETTY_DUMP|5.009004||p PERL_PV_PRETTY_ELLIPSES|5.010000||p PERL_PV_PRETTY_LTGT|5.009004||p PERL_PV_PRETTY_NOCLEAR|5.010000||p PERL_PV_PRETTY_QUOTE|5.009004||p PERL_PV_PRETTY_REGPROP|5.009004||p PERL_QUAD_MAX|5.003070||p PERL_QUAD_MIN|5.003070||p PERL_REVISION|5.006000||p PERL_SCAN_ALLOW_UNDERSCORES|5.007003||p PERL_SCAN_DISALLOW_PREFIX|5.007003||p PERL_SCAN_GREATER_THAN_UV_MAX|5.007003||p PERL_SCAN_SILENT_ILLDIGIT|5.008001||p PERL_SHORT_MAX|5.003070||p PERL_SHORT_MIN|5.003070||p PERL_SIGNALS_UNSAFE_FLAG|5.008001||p PERL_SUBVERSION|5.006000||p PERL_SYS_INIT3||5.006000| PERL_SYS_INIT||| PERL_SYS_TERM||5.024000| PERL_UCHAR_MAX|5.003070||p PERL_UCHAR_MIN|5.003070||p PERL_UINT_MAX|5.003070||p PERL_UINT_MIN|5.003070||p PERL_ULONG_MAX|5.003070||p PERL_ULONG_MIN|5.003070||p PERL_UNUSED_ARG|5.009003||p PERL_UNUSED_CONTEXT|5.009004||p PERL_UNUSED_DECL|5.007002||p PERL_UNUSED_RESULT|5.021001||p PERL_UNUSED_VAR|5.007002||p PERL_UQUAD_MAX|5.003070||p PERL_UQUAD_MIN|5.003070||p PERL_USE_GCC_BRACE_GROUPS|5.009004||p PERL_USHORT_MAX|5.003070||p PERL_USHORT_MIN|5.003070||p PERL_VERSION|5.006000||p PL_DBsignal|5.005000||p PL_DBsingle|||pn PL_DBsub|||pn PL_DBtrace|||pn PL_Sv|5.005000||p PL_bufend|5.024000||p PL_bufptr|5.024000||p PL_check||5.006000| PL_compiling|5.004050||p PL_comppad_name||5.017004| PL_comppad||5.008001| PL_copline|5.024000||p PL_curcop|5.004050||p PL_curpad||5.005000| PL_curstash|5.004050||p PL_debstash|5.004050||p PL_defgv|5.004050||p PL_diehook|5.004050||p PL_dirty|5.004050||p PL_dowarn|||pn PL_errgv|5.004050||p PL_error_count|5.024000||p PL_expect|5.024000||p PL_hexdigit|5.005000||p PL_hints|5.005000||p PL_in_my_stash|5.024000||p PL_in_my|5.024000||p PL_keyword_plugin||5.011002| PL_last_in_gv|||n PL_laststatval|5.005000||p PL_lex_state|5.024000||p PL_lex_stuff|5.024000||p PL_linestr|5.024000||p PL_modglobal||5.005000|n PL_na|5.004050||pn PL_no_modify|5.006000||p PL_ofsgv|||n PL_opfreehook||5.011000|n PL_parser|5.009005||p PL_peepp||5.007003|n PL_perl_destruct_level|5.004050||p PL_perldb|5.004050||p PL_ppaddr|5.006000||p PL_rpeepp||5.013005|n PL_rsfp_filters|5.024000||p PL_rsfp|5.024000||p PL_rs|||n PL_signals|5.008001||p PL_stack_base|5.004050||p PL_stack_sp|5.004050||p PL_statcache|5.005000||p PL_stdingv|5.004050||p PL_sv_arenaroot|5.004050||p PL_sv_no|5.004050||pn PL_sv_undef|5.004050||pn PL_sv_yes|5.004050||pn PL_tainted|5.004050||p PL_tainting|5.004050||p PL_tokenbuf|5.024000||p POP_MULTICALL||5.024000| POPi|||n POPl|||n POPn|||n POPpbytex||5.007001|n POPpx||5.005030|n POPp|||n POPs|||n POPul||5.006000|n POPu||5.004000|n PTR2IV|5.006000||p PTR2NV|5.006000||p PTR2UV|5.006000||p PTR2nat|5.009003||p PTR2ul|5.007001||p PTRV|5.006000||p PUSHMARK||| PUSH_MULTICALL||5.024000| PUSHi||| PUSHmortal|5.009002||p PUSHn||| PUSHp||| PUSHs||| PUSHu|5.004000||p PUTBACK||| PadARRAY||5.024000| PadMAX||5.024000| PadlistARRAY||5.024000| PadlistMAX||5.024000| PadlistNAMESARRAY||5.024000| PadlistNAMESMAX||5.024000| PadlistNAMES||5.024000| PadlistREFCNT||5.017004| PadnameIsOUR||| PadnameIsSTATE||| PadnameLEN||5.024000| PadnameOURSTASH||| PadnameOUTER||| PadnamePV||5.024000| PadnameREFCNT_dec||5.024000| PadnameREFCNT||5.024000| PadnameSV||5.024000| PadnameTYPE||| PadnameUTF8||5.021007| PadnamelistARRAY||5.024000| PadnamelistMAX||5.024000| PadnamelistREFCNT_dec||5.024000| PadnamelistREFCNT||5.024000| PerlIO_clearerr||5.007003| PerlIO_close||5.007003| PerlIO_context_layers||5.009004| PerlIO_eof||5.007003| PerlIO_error||5.007003| PerlIO_fileno||5.007003| PerlIO_fill||5.007003| PerlIO_flush||5.007003| PerlIO_get_base||5.007003| PerlIO_get_bufsiz||5.007003| PerlIO_get_cnt||5.007003| PerlIO_get_ptr||5.007003| PerlIO_read||5.007003| PerlIO_restore_errno||| PerlIO_save_errno||| PerlIO_seek||5.007003| PerlIO_set_cnt||5.007003| PerlIO_set_ptrcnt||5.007003| PerlIO_setlinebuf||5.007003| PerlIO_stderr||5.007003| PerlIO_stdin||5.007003| PerlIO_stdout||5.007003| PerlIO_tell||5.007003| PerlIO_unread||5.007003| PerlIO_write||5.007003| Perl_signbit||5.009005|n PoisonFree|5.009004||p PoisonNew|5.009004||p PoisonWith|5.009004||p Poison|5.008000||p READ_XDIGIT||5.017006| RESTORE_LC_NUMERIC||5.024000| RETVAL|||n Renewc||| Renew||| SAVECLEARSV||| SAVECOMPPAD||| SAVEPADSV||| SAVETMPS||| SAVE_DEFSV|5.004050||p SPAGAIN||| SP||| START_EXTERN_C|5.005000||p START_MY_CXT|5.007003||p STMT_END|||p STMT_START|||p STORE_LC_NUMERIC_FORCE_TO_UNDERLYING||5.024000| STORE_LC_NUMERIC_SET_TO_NEEDED||5.024000| STR_WITH_LEN|5.009003||p ST||| SV_CONST_RETURN|5.009003||p SV_COW_DROP_PV|5.008001||p SV_COW_SHARED_HASH_KEYS|5.009005||p SV_GMAGIC|5.007002||p SV_HAS_TRAILING_NUL|5.009004||p SV_IMMEDIATE_UNREF|5.007001||p SV_MUTABLE_RETURN|5.009003||p SV_NOSTEAL|5.009002||p SV_SMAGIC|5.009003||p SV_UTF8_NO_ENCODING|5.008001||p SVfARG|5.009005||p SVf_UTF8|5.006000||p SVf|5.006000||p SVt_INVLIST||5.019002| SVt_IV||| SVt_NULL||| SVt_NV||| SVt_PVAV||| SVt_PVCV||| SVt_PVFM||| SVt_PVGV||| SVt_PVHV||| SVt_PVIO||| SVt_PVIV||| SVt_PVLV||| SVt_PVMG||| SVt_PVNV||| SVt_PV||| SVt_REGEXP||5.011000| Safefree||| Slab_Alloc||| Slab_Free||| Slab_to_ro||| Slab_to_rw||| StructCopy||| SvCUR_set||| SvCUR||| SvEND||| SvGAMAGIC||5.006001| SvGETMAGIC|5.004050||p SvGROW||| SvIOK_UV||5.006000| SvIOK_notUV||5.006000| SvIOK_off||| SvIOK_only_UV||5.006000| SvIOK_only||| SvIOK_on||| SvIOKp||| SvIOK||| SvIVX||| SvIV_nomg|5.009001||p SvIV_set||| SvIVx||| SvIV||| SvIsCOW_shared_hash||5.008003| SvIsCOW||5.008003| SvLEN_set||| SvLEN||| SvLOCK||5.007003| SvMAGIC_set|5.009003||p SvNIOK_off||| SvNIOKp||| SvNIOK||| SvNOK_off||| SvNOK_only||| SvNOK_on||| SvNOKp||| SvNOK||| SvNVX||| SvNV_nomg||5.013002| SvNV_set||| SvNVx||| SvNV||| SvOK||| SvOOK_offset||5.011000| SvOOK||| SvPOK_off||| SvPOK_only_UTF8||5.006000| SvPOK_only||| SvPOK_on||| SvPOKp||| SvPOK||| SvPVX_const|5.009003||p SvPVX_mutable|5.009003||p SvPVX||| SvPV_const|5.009003||p SvPV_flags_const_nolen|5.009003||p SvPV_flags_const|5.009003||p SvPV_flags_mutable|5.009003||p SvPV_flags|5.007002||p SvPV_force_flags_mutable|5.009003||p SvPV_force_flags_nolen|5.009003||p SvPV_force_flags|5.007002||p SvPV_force_mutable|5.009003||p SvPV_force_nolen|5.009003||p SvPV_force_nomg_nolen|5.009003||p SvPV_force_nomg|5.007002||p SvPV_force|||p SvPV_mutable|5.009003||p SvPV_nolen_const|5.009003||p SvPV_nolen|5.006000||p SvPV_nomg_const_nolen|5.009003||p SvPV_nomg_const|5.009003||p SvPV_nomg_nolen|5.013007||p SvPV_nomg|5.007002||p SvPV_renew|5.009003||p SvPV_set||| SvPVbyte_force||5.009002| SvPVbyte_nolen||5.006000| SvPVbytex_force||5.006000| SvPVbytex||5.006000| SvPVbyte|5.006000||p SvPVutf8_force||5.006000| SvPVutf8_nolen||5.006000| SvPVutf8x_force||5.006000| SvPVutf8x||5.006000| SvPVutf8||5.006000| SvPVx||| SvPV||| SvREFCNT_dec_NN||5.017007| SvREFCNT_dec||| SvREFCNT_inc_NN|5.009004||p SvREFCNT_inc_simple_NN|5.009004||p SvREFCNT_inc_simple_void_NN|5.009004||p SvREFCNT_inc_simple_void|5.009004||p SvREFCNT_inc_simple|5.009004||p SvREFCNT_inc_void_NN|5.009004||p SvREFCNT_inc_void|5.009004||p SvREFCNT_inc|||p SvREFCNT||| SvROK_off||| SvROK_on||| SvROK||| SvRV_set|5.009003||p SvRV||| SvRXOK|5.009005||p SvRX|5.009005||p SvSETMAGIC||| SvSHARED_HASH|5.009003||p SvSHARE||5.007003| SvSTASH_set|5.009003||p SvSTASH||| SvSetMagicSV_nosteal||5.004000| SvSetMagicSV||5.004000| SvSetSV_nosteal||5.004000| SvSetSV||| SvTAINTED_off||5.004000| SvTAINTED_on||5.004000| SvTAINTED||5.004000| SvTAINT||| SvTHINKFIRST||| SvTRUE_nomg||5.013006| SvTRUE||| SvTYPE||| SvUNLOCK||5.007003| SvUOK|5.007001|5.006000|p SvUPGRADE||| SvUTF8_off||5.006000| SvUTF8_on||5.006000| SvUTF8||5.006000| SvUVXx|5.004000||p SvUVX|5.004000||p SvUV_nomg|5.009001||p SvUV_set|5.009003||p SvUVx|5.004000||p SvUV|5.004000||p SvVOK||5.008001| SvVSTRING_mg|5.009004||p THIS|||n UNDERBAR|5.009002||p UTF8SKIP||5.006000| UTF8_MAXBYTES|5.009002||p UVCHR_SKIP||5.022000| UVSIZE|5.006000||p UVTYPE|5.006000||p UVXf|5.007001||p UVof|5.006000||p UVuf|5.006000||p UVxf|5.006000||p WARN_ALL|5.006000||p WARN_AMBIGUOUS|5.006000||p WARN_ASSERTIONS|5.024000||p WARN_BAREWORD|5.006000||p WARN_CLOSED|5.006000||p WARN_CLOSURE|5.006000||p WARN_DEBUGGING|5.006000||p WARN_DEPRECATED|5.006000||p WARN_DIGIT|5.006000||p WARN_EXEC|5.006000||p WARN_EXITING|5.006000||p WARN_GLOB|5.006000||p WARN_INPLACE|5.006000||p WARN_INTERNAL|5.006000||p WARN_IO|5.006000||p WARN_LAYER|5.008000||p WARN_MALLOC|5.006000||p WARN_MISC|5.006000||p WARN_NEWLINE|5.006000||p WARN_NUMERIC|5.006000||p WARN_ONCE|5.006000||p WARN_OVERFLOW|5.006000||p WARN_PACK|5.006000||p WARN_PARENTHESIS|5.006000||p WARN_PIPE|5.006000||p WARN_PORTABLE|5.006000||p WARN_PRECEDENCE|5.006000||p WARN_PRINTF|5.006000||p WARN_PROTOTYPE|5.006000||p WARN_QW|5.006000||p WARN_RECURSION|5.006000||p WARN_REDEFINE|5.006000||p WARN_REGEXP|5.006000||p WARN_RESERVED|5.006000||p WARN_SEMICOLON|5.006000||p WARN_SEVERE|5.006000||p WARN_SIGNAL|5.006000||p WARN_SUBSTR|5.006000||p WARN_SYNTAX|5.006000||p WARN_TAINT|5.006000||p WARN_THREADS|5.008000||p WARN_UNINITIALIZED|5.006000||p WARN_UNOPENED|5.006000||p WARN_UNPACK|5.006000||p WARN_UNTIE|5.006000||p WARN_UTF8|5.006000||p WARN_VOID|5.006000||p WIDEST_UTYPE|5.015004||p XCPT_CATCH|5.009002||p XCPT_RETHROW|5.009002||p XCPT_TRY_END|5.009002||p XCPT_TRY_START|5.009002||p XPUSHi||| XPUSHmortal|5.009002||p XPUSHn||| XPUSHp||| XPUSHs||| XPUSHu|5.004000||p XSPROTO|5.010000||p XSRETURN_EMPTY||| XSRETURN_IV||| XSRETURN_NO||| XSRETURN_NV||| XSRETURN_PV||| XSRETURN_UNDEF||| XSRETURN_UV|5.008001||p XSRETURN_YES||| XSRETURN|||p XST_mIV||| XST_mNO||| XST_mNV||| XST_mPV||| XST_mUNDEF||| XST_mUV|5.008001||p XST_mYES||| XS_APIVERSION_BOOTCHECK||5.024000| XS_EXTERNAL||5.024000| XS_INTERNAL||5.024000| XS_VERSION_BOOTCHECK||5.024000| XS_VERSION||| XSprePUSH|5.006000||p XS||| XopDISABLE||5.024000| XopENABLE||5.024000| XopENTRYCUSTOM||5.024000| XopENTRY_set||5.024000| XopENTRY||5.024000| XopFLAGS||5.013007| ZeroD|5.009002||p Zero||| _aMY_CXT|5.007003||p _add_range_to_invlist||| _append_range_to_invlist||| _core_swash_init||| _get_encoding||| _get_regclass_nonbitmap_data||| _get_swash_invlist||| _invlistEQ||| _invlist_array_init|||n _invlist_contains_cp|||n _invlist_dump||| _invlist_intersection_maybe_complement_2nd||| _invlist_intersection||| _invlist_invert||| _invlist_len|||n _invlist_populate_swatch|||n _invlist_search|||n _invlist_subtract||| _invlist_union_maybe_complement_2nd||| _invlist_union||| _is_cur_LC_category_utf8||| _is_in_locale_category||5.021001| _is_uni_FOO||5.017008| _is_uni_perl_idcont||5.017008| _is_uni_perl_idstart||5.017007| _is_utf8_FOO||5.017008| _is_utf8_char_slow||5.021001|n _is_utf8_idcont||5.021001| _is_utf8_idstart||5.021001| _is_utf8_mark||5.017008| _is_utf8_perl_idcont||5.017008| _is_utf8_perl_idstart||5.017007| _is_utf8_xidcont||5.021001| _is_utf8_xidstart||5.021001| _load_PL_utf8_foldclosures||| _make_exactf_invlist||| _new_invlist_C_array||| _new_invlist||| _pMY_CXT|5.007003||p _setlocale_debug_string|||n _setup_canned_invlist||| _swash_inversion_hash||| _swash_to_invlist||| _to_fold_latin1||| _to_uni_fold_flags||5.014000| _to_upper_title_latin1||| _to_utf8_case||| _to_utf8_fold_flags||5.019009| _to_utf8_lower_flags||5.019009| _to_utf8_title_flags||5.019009| _to_utf8_upper_flags||5.019009| _warn_problematic_locale|||n aMY_CXT_|5.007003||p aMY_CXT|5.007003||p aTHXR_|5.024000||p aTHXR|5.024000||p aTHX_|5.006000||p aTHX|5.006000||p add_above_Latin1_folds||| add_cp_to_invlist||| add_data|||n add_multi_match||| add_utf16_textfilter||| adjust_size_and_find_bucket|||n advance_one_LB||| advance_one_SB||| advance_one_WB||| alloc_maybe_populate_EXACT||| alloccopstash||| allocmy||| amagic_call||| amagic_cmp_locale||| amagic_cmp||| amagic_deref_call||5.013007| amagic_i_ncmp||| amagic_is_enabled||| amagic_ncmp||| anonymise_cv_maybe||| any_dup||| ao||| append_utf8_from_native_byte||5.019004|n apply_attrs_my||| apply_attrs_string||5.006001| apply_attrs||| apply||| assert_uft8_cache_coherent||| assignment_type||| atfork_lock||5.007003|n atfork_unlock||5.007003|n av_arylen_p||5.009003| av_clear||| av_create_and_push||5.009005| av_create_and_unshift_one||5.009005| av_delete||5.006000| av_exists||5.006000| av_extend_guts||| av_extend||| av_fetch||| av_fill||| av_iter_p||5.011000| av_len||| av_make||| av_pop||| av_push||| av_reify||| av_shift||| av_store||| av_tindex||5.017009| av_top_index||5.017009| av_undef||| av_unshift||| ax|||n backup_one_LB||| backup_one_SB||| backup_one_WB||| bad_type_gv||| bad_type_pv||| bind_match||| block_end||5.004000| block_gimme||5.004000| block_start||5.004000| blockhook_register||5.013003| boolSV|5.004000||p boot_core_PerlIO||| boot_core_UNIVERSAL||| boot_core_mro||| bytes_cmp_utf8||5.013007| bytes_from_utf8||5.007001| bytes_to_utf8||5.006001| cBOOL|5.013000||p call_argv|5.006000||p call_atexit||5.006000| call_list||5.004000| call_method|5.006000||p call_pv|5.006000||p call_sv|5.006000||p caller_cx|5.013005|5.006000|p calloc||5.007002|n cando||| cast_i32||5.006000|n cast_iv||5.006000|n cast_ulong||5.006000|n cast_uv||5.006000|n check_locale_boundary_crossing||| check_type_and_open||| check_uni||| check_utf8_print||| checkcomma||| ckWARN|5.006000||p ck_entersub_args_core||| ck_entersub_args_list||5.013006| ck_entersub_args_proto_or_list||5.013006| ck_entersub_args_proto||5.013006| ck_warner_d||5.011001|v ck_warner||5.011001|v ckwarn_common||| ckwarn_d||5.009003| ckwarn||5.009003| clear_defarray||5.023008| clear_placeholders||| clear_special_blocks||| clone_params_del|||n clone_params_new|||n closest_cop||| cntrl_to_mnemonic|||n compute_EXACTish|||n construct_ahocorasick_from_trie||| cop_fetch_label||5.015001| cop_free||| cop_hints_2hv||5.013007| cop_hints_fetch_pvn||5.013007| cop_hints_fetch_pvs||5.013007| cop_hints_fetch_pv||5.013007| cop_hints_fetch_sv||5.013007| cop_store_label||5.015001| cophh_2hv||5.013007| cophh_copy||5.013007| cophh_delete_pvn||5.013007| cophh_delete_pvs||5.013007| cophh_delete_pv||5.013007| cophh_delete_sv||5.013007| cophh_fetch_pvn||5.013007| cophh_fetch_pvs||5.013007| cophh_fetch_pv||5.013007| cophh_fetch_sv||5.013007| cophh_free||5.013007| cophh_new_empty||5.024000| cophh_store_pvn||5.013007| cophh_store_pvs||5.013007| cophh_store_pv||5.013007| cophh_store_sv||5.013007| core_prototype||| coresub_op||| cr_textfilter||| create_eval_scope||| croak_memory_wrap||5.019003|n croak_no_mem|||n croak_no_modify||5.013003|n croak_nocontext|||vn croak_popstack|||n croak_sv||5.013001| croak_xs_usage||5.010001|n croak|||v csighandler||5.009003|n current_re_engine||| curse||| custom_op_desc||5.007003| custom_op_get_field||| custom_op_name||5.007003| custom_op_register||5.013007| custom_op_xop||5.013007| cv_ckproto_len_flags||| cv_clone_into||| cv_clone||| cv_const_sv_or_av|||n cv_const_sv||5.003070|n cv_dump||| cv_forget_slab||| cv_get_call_checker||5.013006| cv_name||5.021005| cv_set_call_checker_flags||5.021004| cv_set_call_checker||5.013006| cv_undef_flags||| cv_undef||| cvgv_from_hek||| cvgv_set||| cvstash_set||| cx_dump||5.005000| cx_dup||| cx_popblock||5.023008| cx_popeval||5.023008| cx_popformat||5.023008| cx_popgiven||5.023008| cx_poploop||5.023008| cx_popsub_args||5.023008| cx_popsub_common||5.023008| cx_popsub||5.023008| cx_popwhen||5.023008| cx_pushblock||5.023008| cx_pusheval||5.023008| cx_pushformat||5.023008| cx_pushgiven||5.023008| cx_pushloop_for||5.023008| cx_pushloop_plain||5.023008| cx_pushsub||5.023008| cx_pushwhen||5.023008| cx_topblock||5.023008| cxinc||| dAXMARK|5.009003||p dAX|5.007002||p dITEMS|5.007002||p dMARK||| dMULTICALL||5.009003| dMY_CXT_SV|5.007003||p dMY_CXT|5.007003||p dNOOP|5.006000||p dORIGMARK||| dSP||| dTHR|5.004050||p dTHXR|5.024000||p dTHXa|5.006000||p dTHXoa|5.006000||p dTHX|5.006000||p dUNDERBAR|5.009002||p dVAR|5.009003||p dXCPT|5.009002||p dXSARGS||| dXSI32||| dXSTARG|5.006000||p deb_curcv||| deb_nocontext|||vn deb_stack_all||| deb_stack_n||| debop||5.005000| debprofdump||5.005000| debprof||| debstackptrs||5.007003| debstack||5.007003| debug_start_match||| deb||5.007003|v defelem_target||| del_sv||| delete_eval_scope||| delimcpy||5.004000|n deprecate_commaless_var_list||| despatch_signals||5.007001| destroy_matcher||| die_nocontext|||vn die_sv||5.013001| die_unwind||| die|||v dirp_dup||| div128||| djSP||| do_aexec5||| do_aexec||| do_aspawn||| do_binmode||5.004050| do_chomp||| do_close||| do_delete_local||| do_dump_pad||| do_eof||| do_exec3||| do_execfree||| do_exec||| do_gv_dump||5.006000| do_gvgv_dump||5.006000| do_hv_dump||5.006000| do_ipcctl||| do_ipcget||| do_join||| do_magic_dump||5.006000| do_msgrcv||| do_msgsnd||| do_ncmp||| do_oddball||| do_op_dump||5.006000| do_open6||| do_open9||5.006000| do_open_raw||| do_openn||5.007001| do_open||5.003070| do_pmop_dump||5.006000| do_print||| do_readline||| do_seek||| do_semop||| do_shmio||| do_smartmatch||| do_spawn_nowait||| do_spawn||| do_sprintf||| do_sv_dump||5.006000| do_sysseek||| do_tell||| do_trans_complex_utf8||| do_trans_complex||| do_trans_count_utf8||| do_trans_count||| do_trans_simple_utf8||| do_trans_simple||| do_trans||| do_vecget||| do_vecset||| do_vop||| docatch||| doeval_compile||| dofile||| dofindlabel||| doform||| doing_taint||5.008001|n dooneliner||| doopen_pm||| doparseform||| dopoptoeval||| dopoptogivenfor||| dopoptolabel||| dopoptoloop||| dopoptosub_at||| dopoptowhen||| doref||5.009003| dounwind||| dowantarray||| drand48_init_r|||n drand48_r|||n dtrace_probe_call||| dtrace_probe_load||| dtrace_probe_op||| dtrace_probe_phase||| dump_all_perl||| dump_all||5.006000| dump_c_backtrace||| dump_eval||5.006000| dump_exec_pos||| dump_form||5.006000| dump_indent||5.006000|v dump_mstats||| dump_packsubs_perl||| dump_packsubs||5.006000| dump_sub_perl||| dump_sub||5.006000| dump_sv_child||| dump_trie_interim_list||| dump_trie_interim_table||| dump_trie||| dump_vindent||5.006000| dumpuntil||| dup_attrlist||| edit_distance|||n emulate_cop_io||| eval_pv|5.006000||p eval_sv|5.006000||p exec_failed||| expect_number||| fbm_compile||5.005000| fbm_instr||5.005000| feature_is_enabled||| filter_add||| filter_del||| filter_gets||| filter_read||| finalize_optree||| finalize_op||| find_and_forget_pmops||| find_array_subscript||| find_beginning||| find_byclass||| find_default_stash||| find_hash_subscript||| find_in_my_stash||| find_lexical_cv||| find_runcv_where||| find_runcv||5.008001| find_rundefsvoffset||5.009002| find_rundefsv||5.013002| find_script||| find_uninit_var||| first_symbol|||n fixup_errno_string||| foldEQ_latin1||5.013008|n foldEQ_locale||5.013002|n foldEQ_utf8_flags||5.013010| foldEQ_utf8||5.013002| foldEQ||5.013002|n fold_constants||| forbid_setid||| force_ident_maybe_lex||| force_ident||| force_list||| force_next||| force_strict_version||| force_version||| force_word||| forget_pmop||| form_nocontext|||vn form_short_octal_warning||| form||5.004000|v fp_dup||| fprintf_nocontext|||vn free_c_backtrace||| free_global_struct||| free_tied_hv_pool||| free_tmps||| gen_constant_list||| get_ANYOF_cp_list_for_ssc||| get_and_check_backslash_N_name||| get_aux_mg||| get_av|5.006000||p get_c_backtrace_dump||| get_c_backtrace||| get_context||5.006000|n get_cvn_flags||| get_cvs|5.011000||p get_cv|5.006000||p get_db_sub||| get_debug_opts||| get_hash_seed||| get_hv|5.006000||p get_invlist_iter_addr|||n get_invlist_offset_addr|||n get_invlist_previous_index_addr|||n get_mstats||| get_no_modify||| get_num||| get_op_descs||5.005000| get_op_names||5.005000| get_opargs||| get_ppaddr||5.006000| get_re_arg||| get_sv|5.006000||p get_vtbl||5.005030| getcwd_sv||5.007002| getenv_len||| glob_2number||| glob_assign_glob||| gp_dup||| gp_free||| gp_ref||| grok_atoUV|||n grok_bin|5.007003||p grok_bslash_N||| grok_bslash_c||| grok_bslash_o||| grok_bslash_x||| grok_hex|5.007003||p grok_infnan||5.021004| grok_number_flags||5.021002| grok_number|5.007002||p grok_numeric_radix|5.007002||p grok_oct|5.007003||p group_end||| gv_AVadd||| gv_HVadd||| gv_IOadd||| gv_SVadd||| gv_add_by_type||5.011000| gv_autoload4||5.004000| gv_autoload_pvn||5.015004| gv_autoload_pv||5.015004| gv_autoload_sv||5.015004| gv_check||| gv_const_sv||5.009003| gv_dump||5.006000| gv_efullname3||5.003070| gv_efullname4||5.006001| gv_efullname||| gv_fetchfile_flags||5.009005| gv_fetchfile||| gv_fetchmeth_autoload||5.007003| gv_fetchmeth_internal||| gv_fetchmeth_pv_autoload||5.015004| gv_fetchmeth_pvn_autoload||5.015004| gv_fetchmeth_pvn||5.015004| gv_fetchmeth_pv||5.015004| gv_fetchmeth_sv_autoload||5.015004| gv_fetchmeth_sv||5.015004| gv_fetchmethod_autoload||5.004000| gv_fetchmethod_pv_flags||5.015004| gv_fetchmethod_pvn_flags||5.015004| gv_fetchmethod_sv_flags||5.015004| gv_fetchmethod||| gv_fetchmeth||| gv_fetchpvn_flags|5.009002||p gv_fetchpvs|5.009004||p gv_fetchpv||| gv_fetchsv||| gv_fullname3||5.003070| gv_fullname4||5.006001| gv_fullname||| gv_handler||5.007001| gv_init_pvn||| gv_init_pv||5.015004| gv_init_svtype||| gv_init_sv||5.015004| gv_init||| gv_is_in_main||| gv_magicalize_isa||| gv_magicalize||| gv_name_set||5.009004| gv_override||| gv_setref||| gv_stashpvn_internal||| gv_stashpvn|5.003070||p gv_stashpvs|5.009003||p gv_stashpv||| gv_stashsvpvn_cached||| gv_stashsv||| gv_try_downgrade||| handle_named_backref||| handle_possible_posix||| handle_regex_sets||| he_dup||| hek_dup||| hfree_next_entry||| hfreeentries||| hsplit||| hv_assert||| hv_auxinit_internal|||n hv_auxinit||| hv_backreferences_p||| hv_clear_placeholders||5.009001| hv_clear||| hv_common_key_len||5.010000| hv_common||5.010000| hv_copy_hints_hv||5.009004| hv_delayfree_ent||5.004000| hv_delete_common||| hv_delete_ent||5.003070| hv_delete||| hv_eiter_p||5.009003| hv_eiter_set||5.009003| hv_ename_add||| hv_ename_delete||| hv_exists_ent||5.003070| hv_exists||| hv_fetch_ent||5.003070| hv_fetchs|5.009003||p hv_fetch||| hv_fill||5.013002| hv_free_ent_ret||| hv_free_ent||5.004000| hv_iterinit||| hv_iterkeysv||5.003070| hv_iterkey||| hv_iternext_flags||5.008000| hv_iternextsv||| hv_iternext||| hv_iterval||| hv_kill_backrefs||| hv_ksplit||5.003070| hv_magic_check|||n hv_magic||| hv_name_set||5.009003| hv_notallowed||| hv_placeholders_get||5.009003| hv_placeholders_p||| hv_placeholders_set||5.009003| hv_rand_set||5.018000| hv_riter_p||5.009003| hv_riter_set||5.009003| hv_scalar||5.009001| hv_store_ent||5.003070| hv_store_flags||5.008000| hv_stores|5.009004||p hv_store||| hv_undef_flags||| hv_undef||| ibcmp_locale||5.004000| ibcmp_utf8||5.007003| ibcmp||| incline||| incpush_if_exists||| incpush_use_sep||| incpush||| ingroup||| init_argv_symbols||| init_constants||| init_dbargs||| init_debugger||| init_global_struct||| init_i18nl10n||5.006000| init_i18nl14n||5.006000| init_ids||| init_interp||| init_main_stash||| init_perllib||| init_postdump_symbols||| init_predump_symbols||| init_stacks||5.005000| init_tm||5.007002| inplace_aassign||| instr|||n intro_my||5.004000| intuit_method||| intuit_more||| invert||| invlist_array|||n invlist_clear||| invlist_clone||| invlist_contents||| invlist_extend||| invlist_highest|||n invlist_is_iterating|||n invlist_iterfinish|||n invlist_iterinit|||n invlist_iternext|||n invlist_max|||n invlist_previous_index|||n invlist_replace_list_destroys_src||| invlist_set_len||| invlist_set_previous_index|||n invlist_trim|||n invoke_exception_hook||| io_close||| isALNUMC|5.006000||p isALNUM_lazy||5.021001| isALPHANUMERIC||5.017008| isALPHA||| isASCII|5.006000||p isBLANK|5.006001||p isCNTRL|5.006000||p isDIGIT||| isFOO_lc||| isFOO_utf8_lc||| isGCB|||n isGRAPH|5.006000||p isIDCONT||5.017008| isIDFIRST_lazy||5.021001| isIDFIRST||| isLB||| isLOWER||| isOCTAL||5.013005| isPRINT|5.004000||p isPSXSPC|5.006001||p isPUNCT|5.006000||p isSB||| isSPACE||| isUPPER||| isUTF8_CHAR||5.021001| isWB||| isWORDCHAR||5.013006| isXDIGIT|5.006000||p is_an_int||| is_ascii_string||5.011000| is_handle_constructor|||n is_invariant_string||5.021007|n is_lvalue_sub||5.007001| is_safe_syscall||5.019004| is_ssc_worth_it|||n is_uni_alnum_lc||5.006000| is_uni_alnumc_lc||5.017007| is_uni_alnumc||5.017007| is_uni_alnum||5.006000| is_uni_alpha_lc||5.006000| is_uni_alpha||5.006000| is_uni_ascii_lc||5.006000| is_uni_ascii||5.006000| is_uni_blank_lc||5.017002| is_uni_blank||5.017002| is_uni_cntrl_lc||5.006000| is_uni_cntrl||5.006000| is_uni_digit_lc||5.006000| is_uni_digit||5.006000| is_uni_graph_lc||5.006000| is_uni_graph||5.006000| is_uni_idfirst_lc||5.006000| is_uni_idfirst||5.006000| is_uni_lower_lc||5.006000| is_uni_lower||5.006000| is_uni_print_lc||5.006000| is_uni_print||5.006000| is_uni_punct_lc||5.006000| is_uni_punct||5.006000| is_uni_space_lc||5.006000| is_uni_space||5.006000| is_uni_upper_lc||5.006000| is_uni_upper||5.006000| is_uni_xdigit_lc||5.006000| is_uni_xdigit||5.006000| is_utf8_alnumc||5.017007| is_utf8_alnum||5.006000| is_utf8_alpha||5.006000| is_utf8_ascii||5.006000| is_utf8_blank||5.017002| is_utf8_char_buf||5.015008|n is_utf8_char||5.006000|n is_utf8_cntrl||5.006000| is_utf8_common||| is_utf8_digit||5.006000| is_utf8_graph||5.006000| is_utf8_idcont||5.008000| is_utf8_idfirst||5.006000| is_utf8_lower||5.006000| is_utf8_mark||5.006000| is_utf8_perl_space||5.011001| is_utf8_perl_word||5.011001| is_utf8_posix_digit||5.011001| is_utf8_print||5.006000| is_utf8_punct||5.006000| is_utf8_space||5.006000| is_utf8_string_loclen||5.009003|n is_utf8_string_loc||5.008001|n is_utf8_string||5.006001|n is_utf8_upper||5.006000| is_utf8_xdigit||5.006000| is_utf8_xidcont||5.013010| is_utf8_xidfirst||5.013010| isa_lookup||| isinfnansv||| isinfnan||5.021004|n items|||n ix|||n jmaybe||| join_exact||| keyword_plugin_standard||| keyword||| leave_adjust_stacks||5.023008| leave_scope||| lex_bufutf8||5.011002| lex_discard_to||5.011002| lex_grow_linestr||5.011002| lex_next_chunk||5.011002| lex_peek_unichar||5.011002| lex_read_space||5.011002| lex_read_to||5.011002| lex_read_unichar||5.011002| lex_start||5.009005| lex_stuff_pvn||5.011002| lex_stuff_pvs||5.013005| lex_stuff_pv||5.013006| lex_stuff_sv||5.011002| lex_unstuff||5.011002| listkids||| list||| load_module_nocontext|||vn load_module|5.006000||pv localize||| looks_like_bool||| looks_like_number||| lop||| mPUSHi|5.009002||p mPUSHn|5.009002||p mPUSHp|5.009002||p mPUSHs|5.010001||p mPUSHu|5.009002||p mXPUSHi|5.009002||p mXPUSHn|5.009002||p mXPUSHp|5.009002||p mXPUSHs|5.010001||p mXPUSHu|5.009002||p magic_clear_all_env||| magic_cleararylen_p||| magic_clearenv||| magic_clearhints||| magic_clearhint||| magic_clearisa||| magic_clearpack||| magic_clearsig||| magic_copycallchecker||| magic_dump||5.006000| magic_existspack||| magic_freearylen_p||| magic_freeovrld||| magic_getarylen||| magic_getdebugvar||| magic_getdefelem||| magic_getnkeys||| magic_getpack||| magic_getpos||| magic_getsig||| magic_getsubstr||| magic_gettaint||| magic_getuvar||| magic_getvec||| magic_get||| magic_killbackrefs||| magic_methcall1||| magic_methcall|||v magic_methpack||| magic_nextpack||| magic_regdata_cnt||| magic_regdatum_get||| magic_regdatum_set||| magic_scalarpack||| magic_set_all_env||| magic_setarylen||| magic_setcollxfrm||| magic_setdbline||| magic_setdebugvar||| magic_setdefelem||| magic_setenv||| magic_sethint||| magic_setisa||| magic_setlvref||| magic_setmglob||| magic_setnkeys||| magic_setpack||| magic_setpos||| magic_setregexp||| magic_setsig||| magic_setsubstr||| magic_settaint||| magic_setutf8||| magic_setuvar||| magic_setvec||| magic_set||| magic_sizepack||| magic_wipepack||| make_matcher||| make_trie||| malloc_good_size|||n malloced_size|||n malloc||5.007002|n markstack_grow||5.021001| matcher_matches_sv||| maybe_multimagic_gv||| mayberelocate||| measure_struct||| memEQs|5.009005||p memEQ|5.004000||p memNEs|5.009005||p memNE|5.004000||p mem_collxfrm||| mem_log_alloc|||n mem_log_common|||n mem_log_free|||n mem_log_realloc|||n mess_alloc||| mess_nocontext|||vn mess_sv||5.013001| mess||5.006000|v mfree||5.007002|n mg_clear||| mg_copy||| mg_dup||| mg_find_mglob||| mg_findext|5.013008||pn mg_find|||n mg_free_type||5.013006| mg_free||| mg_get||| mg_length||5.005000| mg_localize||| mg_magical|||n mg_set||| mg_size||5.005000| mini_mktime||5.007002|n minus_v||| missingterm||| mode_from_discipline||| modkids||| more_bodies||| more_sv||| moreswitches||| move_proto_attr||| mro_clean_isarev||| mro_gather_and_rename||| mro_get_from_name||5.010001| mro_get_linear_isa_dfs||| mro_get_linear_isa||5.009005| mro_get_private_data||5.010001| mro_isa_changed_in||| mro_meta_dup||| mro_meta_init||| mro_method_changed_in||5.009005| mro_package_moved||| mro_register||5.010001| mro_set_mro||5.010001| mro_set_private_data||5.010001| mul128||| mulexp10|||n multideref_stringify||| my_atof2||5.007002| my_atof||5.006000| my_attrs||| my_bcopy||5.004050|n my_bytes_to_utf8|||n my_bzero|||n my_chsize||| my_clearenv||| my_cxt_index||| my_cxt_init||| my_dirfd||5.009005|n my_exit_jump||| my_exit||| my_failure_exit||5.004000| my_fflush_all||5.006000| my_fork||5.007003|n my_kid||| my_lstat_flags||| my_lstat||5.024000| my_memcmp|||n my_memset|||n my_pclose||5.003070| my_popen_list||5.007001| my_popen||5.003070| my_setenv||| my_setlocale||| my_snprintf|5.009004||pvn my_socketpair||5.007003|n my_sprintf|5.009003||pvn my_stat_flags||| my_stat||5.024000| my_strerror||5.021001| my_strftime||5.007002| my_strlcat|5.009004||pn my_strlcpy|5.009004||pn my_unexec||| my_vsnprintf||5.009004|n need_utf8|||n newANONATTRSUB||5.006000| newANONHASH||| newANONLIST||| newANONSUB||| newASSIGNOP||| newATTRSUB_x||| newATTRSUB||5.006000| newAVREF||| newAV||| newBINOP||| newCONDOP||| newCONSTSUB_flags||5.015006| newCONSTSUB|5.004050||p newCVREF||| newDEFSVOP||5.021006| newFORM||| newFOROP||5.013007| newGIVENOP||5.009003| newGIVWHENOP||| newGP||| newGVOP||| newGVREF||| newGVgen_flags||5.015004| newGVgen||| newHVREF||| newHVhv||5.005000| newHV||| newIO||| newLISTOP||| newLOGOP||| newLOOPEX||| newLOOPOP||| newMETHOP_internal||| newMETHOP_named||5.021005| newMETHOP||5.021005| newMYSUB||5.017004| newNULLLIST||| newOP||| newPADNAMELIST||5.021007|n newPADNAMEouter||5.021007|n newPADNAMEpvn||5.021007|n newPADOP||| newPMOP||| newPROG||| newPVOP||| newRANGE||| newRV_inc|5.004000||p newRV_noinc|5.004000||p newRV||| newSLICEOP||| newSTATEOP||| newSTUB||| newSUB||| newSVOP||| newSVREF||| newSV_type|5.009005||p newSVavdefelem||| newSVhek||5.009003| newSViv||| newSVnv||| newSVpadname||5.017004| newSVpv_share||5.013006| newSVpvf_nocontext|||vn newSVpvf||5.004000|v newSVpvn_flags|5.010001||p newSVpvn_share|5.007001||p newSVpvn_utf8|5.010001||p newSVpvn|5.004050||p newSVpvs_flags|5.010001||p newSVpvs_share|5.009003||p newSVpvs|5.009003||p newSVpv||| newSVrv||| newSVsv||| newSVuv|5.006000||p newSV||| newUNOP_AUX||5.021007| newUNOP||| newWHENOP||5.009003| newWHILEOP||5.013007| newXS_deffile||| newXS_flags||5.009004| newXS_len_flags||| newXSproto||5.006000| newXS||5.006000| new_collate||5.006000| new_constant||| new_ctype||5.006000| new_he||| new_logop||| new_numeric||5.006000| new_stackinfo||5.005000| new_version||5.009000| new_warnings_bitfield||| next_symbol||| nextargv||| nextchar||| ninstr|||n no_bareword_allowed||| no_fh_allowed||| no_op||| noperl_die|||vn not_a_number||| not_incrementable||| nothreadhook||5.008000| nuke_stacks||| num_overflow|||n oopsAV||| oopsHV||| op_append_elem||5.013006| op_append_list||5.013006| op_clear||| op_contextualize||5.013006| op_convert_list||5.021006| op_dump||5.006000| op_free||| op_integerize||| op_linklist||5.013006| op_lvalue_flags||| op_lvalue||5.013007| op_null||5.007002| op_parent|||n op_prepend_elem||5.013006| op_refcnt_dec||| op_refcnt_inc||| op_refcnt_lock||5.009002| op_refcnt_unlock||5.009002| op_relocate_sv||| op_scope||5.013007| op_sibling_splice||5.021002|n op_std_init||| op_unscope||| open_script||| openn_cleanup||| openn_setup||| opmethod_stash||| opslab_force_free||| opslab_free_nopad||| opslab_free||| output_or_return_posix_warnings||| pMY_CXT_|5.007003||p pMY_CXT|5.007003||p pTHX_|5.006000||p pTHX|5.006000||p packWARN|5.007003||p pack_cat||5.007003| pack_rec||| package_version||| package||| packlist||5.008001| pad_add_anon||5.008001| pad_add_name_pvn||5.015001| pad_add_name_pvs||5.015001| pad_add_name_pv||5.015001| pad_add_name_sv||5.015001| pad_add_weakref||| pad_alloc_name||| pad_alloc||| pad_block_start||| pad_check_dup||| pad_compname_type||5.009003| pad_findlex||| pad_findmy_pvn||5.015001| pad_findmy_pvs||5.015001| pad_findmy_pv||5.015001| pad_findmy_sv||5.015001| pad_fixup_inner_anons||| pad_free||| pad_leavemy||| pad_new||5.008001| pad_push||| pad_reset||| pad_setsv||| pad_sv||| pad_swipe||| pad_tidy||5.008001| padlist_dup||| padlist_store||| padname_dup||| padname_free||| padnamelist_dup||| padnamelist_fetch||5.021007|n padnamelist_free||| padnamelist_store||5.021007| parse_arithexpr||5.013008| parse_barestmt||5.013007| parse_block||5.013007| parse_body||| parse_fullexpr||5.013008| parse_fullstmt||5.013005| parse_gv_stash_name||| parse_ident||| parse_label||5.013007| parse_listexpr||5.013008| parse_lparen_question_flags||| parse_stmtseq||5.013006| parse_subsignature||| parse_termexpr||5.013008| parse_unicode_opts||| parser_dup||| parser_free_nexttoke_ops||| parser_free||| path_is_searchable|||n peep||| pending_ident||| perl_alloc_using|||n perl_alloc|||n perl_clone_using|||n perl_clone|||n perl_construct|||n perl_destruct||5.007003|n perl_free|||n perl_parse||5.006000|n perl_run|||n pidgone||| pm_description||| pmop_dump||5.006000| pmruntime||| pmtrans||| pop_scope||| populate_ANYOF_from_invlist||| populate_isa|||v pregcomp||5.009005| pregexec||| pregfree2||5.011000| pregfree||| prescan_version||5.011004| printbuf||| printf_nocontext|||vn process_special_blocks||| ptr_hash|||n ptr_table_clear||5.009005| ptr_table_fetch||5.009005| ptr_table_find|||n ptr_table_free||5.009005| ptr_table_new||5.009005| ptr_table_split||5.009005| ptr_table_store||5.009005| push_scope||| put_charclass_bitmap_innards_common||| put_charclass_bitmap_innards_invlist||| put_charclass_bitmap_innards||| put_code_point||| put_range||| pv_display|5.006000||p pv_escape|5.009004||p pv_pretty|5.009004||p pv_uni_display||5.007003| qerror||| qsortsvu||| quadmath_format_needed|||n quadmath_format_single|||n re_compile||5.009005| re_croak2||| re_dup_guts||| re_exec_indentf|||v re_indentf|||v re_intuit_start||5.019001| re_intuit_string||5.006000| re_op_compile||| re_printf|||v realloc||5.007002|n reentrant_free||5.024000| reentrant_init||5.024000| reentrant_retry||5.024000|vn reentrant_size||5.024000| ref_array_or_hash||| refcounted_he_chain_2hv||| refcounted_he_fetch_pvn||| refcounted_he_fetch_pvs||| refcounted_he_fetch_pv||| refcounted_he_fetch_sv||| refcounted_he_free||| refcounted_he_inc||| refcounted_he_new_pvn||| refcounted_he_new_pvs||| refcounted_he_new_pv||| refcounted_he_new_sv||| refcounted_he_value||| refkids||| refto||| ref||5.024000| reg2Lanode||| reg_check_named_buff_matched|||n reg_named_buff_all||5.009005| reg_named_buff_exists||5.009005| reg_named_buff_fetch||5.009005| reg_named_buff_firstkey||5.009005| reg_named_buff_iter||| reg_named_buff_nextkey||5.009005| reg_named_buff_scalar||5.009005| reg_named_buff||| reg_node||| reg_numbered_buff_fetch||| reg_numbered_buff_length||| reg_numbered_buff_store||| reg_qr_package||| reg_recode||| reg_scan_name||| reg_skipcomment|||n reg_temp_copy||| reganode||| regatom||| regbranch||| regclass_swash||5.009004| regclass||| regcppop||| regcppush||| regcurly|||n regdump_extflags||| regdump_intflags||| regdump||5.005000| regdupe_internal||| regex_set_precedence|||n regexec_flags||5.005000| regfree_internal||5.009005| reghop3|||n reghop4|||n reghopmaybe3|||n reginclass||| reginitcolors||5.006000| reginsert||| regmatch||| regnext||5.005000| regnode_guts||| regpiece||| regprop||| regrepeat||| regtail_study||| regtail||| regtry||| reg||| repeatcpy|||n report_evil_fh||| report_redefined_cv||| report_uninit||| report_wrongway_fh||| require_pv||5.006000| require_tie_mod||| restore_magic||| rninstr|||n rpeep||| rsignal_restore||| rsignal_save||| rsignal_state||5.004000| rsignal||5.004000| run_body||| run_user_filter||| runops_debug||5.005000| runops_standard||5.005000| rv2cv_op_cv||5.013006| rvpv_dup||| rxres_free||| rxres_restore||| rxres_save||| safesyscalloc||5.006000|n safesysfree||5.006000|n safesysmalloc||5.006000|n safesysrealloc||5.006000|n same_dirent||| save_I16||5.004000| save_I32||| save_I8||5.006000| save_adelete||5.011000| save_aelem_flags||5.011000| save_aelem||5.004050| save_alloc||5.006000| save_aptr||| save_ary||| save_bool||5.008001| save_clearsv||| save_delete||| save_destructor_x||5.006000| save_destructor||5.006000| save_freeop||| save_freepv||| save_freesv||| save_generic_pvref||5.006001| save_generic_svref||5.005030| save_gp||5.004000| save_hash||| save_hdelete||5.011000| save_hek_flags|||n save_helem_flags||5.011000| save_helem||5.004050| save_hints||5.010001| save_hptr||| save_int||| save_item||| save_iv||5.005000| save_lines||| save_list||| save_long||| save_magic_flags||| save_mortalizesv||5.007001| save_nogv||| save_op||5.005000| save_padsv_and_mortalize||5.010001| save_pptr||| save_pushi32ptr||5.010001| save_pushptri32ptr||| save_pushptrptr||5.010001| save_pushptr||5.010001| save_re_context||5.006000| save_scalar_at||| save_scalar||| save_set_svflags||5.009000| save_shared_pvref||5.007003| save_sptr||| save_strlen||| save_svref||| save_vptr||5.006000| savepvn||| savepvs||5.009003| savepv||| savesharedpvn||5.009005| savesharedpvs||5.013006| savesharedpv||5.007003| savesharedsvpv||5.013006| savestack_grow_cnt||5.008001| savestack_grow||| savesvpv||5.009002| savetmps||5.023008| sawparens||| scalar_mod_type|||n scalarboolean||| scalarkids||| scalarseq||| scalarvoid||| scalar||| scan_bin||5.006000| scan_commit||| scan_const||| scan_formline||| scan_heredoc||| scan_hex||| scan_ident||| scan_inputsymbol||| scan_num||5.007001| scan_oct||| scan_pat||| scan_str||| scan_subst||| scan_trans||| scan_version||5.009001| scan_vstring||5.009005| scan_word||| search_const||| seed||5.008001| sequence_num||| set_ANYOF_arg||| set_caret_X||| set_context||5.006000|n set_numeric_local||5.006000| set_numeric_radix||5.006000| set_numeric_standard||5.006000| set_padlist|||n setdefout||| share_hek_flags||| share_hek||5.004000| should_warn_nl|||n si_dup||| sighandler|||n simplify_sort||| skip_to_be_ignored_text||| skipspace_flags||| softref2xv||| sortcv_stacked||| sortcv_xsub||| sortcv||| sortsv_flags||5.009003| sortsv||5.007003| space_join_names_mortal||| ss_dup||| ssc_add_range||| ssc_and||| ssc_anything||| ssc_clear_locale|||n ssc_cp_and||| ssc_finalize||| ssc_init||| ssc_intersection||| ssc_is_anything|||n ssc_is_cp_posixl_init|||n ssc_or||| ssc_union||| stack_grow||| start_glob||| start_subparse||5.004000| stdize_locale||| strEQ||| strGE||| strGT||| strLE||| strLT||| strNE||| str_to_version||5.006000| strip_return||| strnEQ||| strnNE||| study_chunk||| sub_crush_depth||| sublex_done||| sublex_push||| sublex_start||| sv_2bool_flags||5.013006| sv_2bool||| sv_2cv||| sv_2io||| sv_2iuv_common||| sv_2iuv_non_preserve||| sv_2iv_flags||5.009001| sv_2iv||| sv_2mortal||| sv_2num||| sv_2nv_flags||5.013001| sv_2pv_flags|5.007002||p sv_2pv_nolen|5.006000||p sv_2pvbyte_nolen|5.006000||p sv_2pvbyte|5.006000||p sv_2pvutf8_nolen||5.006000| sv_2pvutf8||5.006000| sv_2pv||| sv_2uv_flags||5.009001| sv_2uv|5.004000||p sv_add_arena||| sv_add_backref||| sv_backoff|||n sv_bless||| sv_buf_to_ro||| sv_buf_to_rw||| sv_cat_decode||5.008001| sv_catpv_flags||5.013006| sv_catpv_mg|5.004050||p sv_catpv_nomg||5.013006| sv_catpvf_mg_nocontext|||pvn sv_catpvf_mg|5.006000|5.004000|pv sv_catpvf_nocontext|||vn sv_catpvf||5.004000|v sv_catpvn_flags||5.007002| sv_catpvn_mg|5.004050||p sv_catpvn_nomg|5.007002||p sv_catpvn||| sv_catpvs_flags||5.013006| sv_catpvs_mg||5.013006| sv_catpvs_nomg||5.013006| sv_catpvs|5.009003||p sv_catpv||| sv_catsv_flags||5.007002| sv_catsv_mg|5.004050||p sv_catsv_nomg|5.007002||p sv_catsv||| sv_chop||| sv_clean_all||| sv_clean_objs||| sv_clear||| sv_cmp_flags||5.013006| sv_cmp_locale_flags||5.013006| sv_cmp_locale||5.004000| sv_cmp||| sv_collxfrm_flags||5.013006| sv_collxfrm||| sv_copypv_flags||5.017002| sv_copypv_nomg||5.017002| sv_copypv||| sv_dec_nomg||5.013002| sv_dec||| sv_del_backref||| sv_derived_from_pvn||5.015004| sv_derived_from_pv||5.015004| sv_derived_from_sv||5.015004| sv_derived_from||5.004000| sv_destroyable||5.010000| sv_display||| sv_does_pvn||5.015004| sv_does_pv||5.015004| sv_does_sv||5.015004| sv_does||5.009004| sv_dump||| sv_dup_common||| sv_dup_inc_multiple||| sv_dup_inc||| sv_dup||| sv_eq_flags||5.013006| sv_eq||| sv_exp_grow||| sv_force_normal_flags||5.007001| sv_force_normal||5.006000| sv_free2||| sv_free_arenas||| sv_free||| sv_get_backrefs||5.021008|n sv_gets||5.003070| sv_grow||| sv_i_ncmp||| sv_inc_nomg||5.013002| sv_inc||| sv_insert_flags||5.010001| sv_insert||| sv_isa||| sv_isobject||| sv_iv||5.005000| sv_kill_backrefs||| sv_len_utf8_nomg||| sv_len_utf8||5.006000| sv_len||| sv_magic_portable|5.024000|5.004000|p sv_magicext_mglob||| sv_magicext||5.007003| sv_magic||| sv_mortalcopy_flags||| sv_mortalcopy||| sv_ncmp||| sv_newmortal||| sv_newref||| sv_nolocking||5.007003| sv_nosharing||5.007003| sv_nounlocking||| sv_nv||5.005000| sv_only_taint_gmagic|||n sv_or_pv_pos_u2b||| sv_peek||5.005000| sv_pos_b2u_flags||5.019003| sv_pos_b2u_midway||| sv_pos_b2u||5.006000| sv_pos_u2b_cached||| sv_pos_u2b_flags||5.011005| sv_pos_u2b_forwards|||n sv_pos_u2b_midway|||n sv_pos_u2b||5.006000| sv_pvbyten_force||5.006000| sv_pvbyten||5.006000| sv_pvbyte||5.006000| sv_pvn_force_flags|5.007002||p sv_pvn_force||| sv_pvn_nomg|5.007003|5.005000|p sv_pvn||5.005000| sv_pvutf8n_force||5.006000| sv_pvutf8n||5.006000| sv_pvutf8||5.006000| sv_pv||5.006000| sv_recode_to_utf8||5.007003| sv_reftype||| sv_ref||5.015004| sv_replace||| sv_report_used||| sv_resetpvn||| sv_reset||| sv_rvweaken||5.006000| sv_sethek||| sv_setiv_mg|5.004050||p sv_setiv||| sv_setnv_mg|5.006000||p sv_setnv||| sv_setpv_mg|5.004050||p sv_setpvf_mg_nocontext|||pvn sv_setpvf_mg|5.006000|5.004000|pv sv_setpvf_nocontext|||vn sv_setpvf||5.004000|v sv_setpviv_mg||5.008001| sv_setpviv||5.008001| sv_setpvn_mg|5.004050||p sv_setpvn||| sv_setpvs_mg||5.013006| sv_setpvs|5.009004||p sv_setpv||| sv_setref_iv||| sv_setref_nv||| sv_setref_pvn||| sv_setref_pvs||5.024000| sv_setref_pv||| sv_setref_uv||5.007001| sv_setsv_cow||| sv_setsv_flags||5.007002| sv_setsv_mg|5.004050||p sv_setsv_nomg|5.007002||p sv_setsv||| sv_setuv_mg|5.004050||p sv_setuv|5.004000||p sv_tainted||5.004000| sv_taint||5.004000| sv_true||5.005000| sv_unglob||| sv_uni_display||5.007003| sv_unmagicext|5.013008||p sv_unmagic||| sv_unref_flags||5.007001| sv_unref||| sv_untaint||5.004000| sv_upgrade||| sv_usepvn_flags||5.009004| sv_usepvn_mg|5.004050||p sv_usepvn||| sv_utf8_decode||5.006000| sv_utf8_downgrade||5.006000| sv_utf8_encode||5.006000| sv_utf8_upgrade_flags_grow||5.011000| sv_utf8_upgrade_flags||5.007002| sv_utf8_upgrade_nomg||5.007002| sv_utf8_upgrade||5.007001| sv_uv|5.005000||p sv_vcatpvf_mg|5.006000|5.004000|p sv_vcatpvfn_flags||5.017002| sv_vcatpvfn||5.004000| sv_vcatpvf|5.006000|5.004000|p sv_vsetpvf_mg|5.006000|5.004000|p sv_vsetpvfn||5.004000| sv_vsetpvf|5.006000|5.004000|p svtype||| swallow_bom||| swash_fetch||5.007002| swash_init||5.006000| swash_scan_list_line||| swatch_get||| sync_locale||5.021004| sys_init3||5.010000|n sys_init||5.010000|n sys_intern_clear||| sys_intern_dup||| sys_intern_init||| sys_term||5.010000|n taint_env||| taint_proper||| tied_method|||v tmps_grow_p||| toFOLD_utf8||5.019001| toFOLD_uvchr||5.023009| toFOLD||5.019001| toLOWER_L1||5.019001| toLOWER_LC||5.004000| toLOWER_utf8||5.015007| toLOWER_uvchr||5.023009| toLOWER||| toTITLE_utf8||5.015007| toTITLE_uvchr||5.023009| toTITLE||5.019001| toUPPER_utf8||5.015007| toUPPER_uvchr||5.023009| toUPPER||| to_byte_substr||| to_lower_latin1|||n to_uni_fold||5.007003| to_uni_lower_lc||5.006000| to_uni_lower||5.007003| to_uni_title_lc||5.006000| to_uni_title||5.007003| to_uni_upper_lc||5.006000| to_uni_upper||5.007003| to_utf8_case||5.007003| to_utf8_fold||5.015007| to_utf8_lower||5.015007| to_utf8_substr||| to_utf8_title||5.015007| to_utf8_upper||5.015007| tokenize_use||| tokeq||| tokereport||| too_few_arguments_pv||| too_many_arguments_pv||| translate_substr_offsets|||n try_amagic_bin||| try_amagic_un||| uiv_2buf|||n unlnk||| unpack_rec||| unpack_str||5.007003| unpackstring||5.008001| unreferenced_to_tmp_stack||| unshare_hek_or_pvn||| unshare_hek||| unsharepvn||5.003070| unwind_handler_stack||| update_debugger_info||| upg_version||5.009005| usage||| utf16_textfilter||| utf16_to_utf8_reversed||5.006001| utf16_to_utf8||5.006001| utf8_distance||5.006000| utf8_hop||5.006000|n utf8_length||5.007001| utf8_mg_len_cache_update||| utf8_mg_pos_cache_update||| utf8_to_bytes||5.006001| utf8_to_uvchr_buf||5.015009| utf8_to_uvchr||5.007001| utf8_to_uvuni_buf||5.015009| utf8_to_uvuni||5.007001| utf8n_to_uvchr||5.007001| utf8n_to_uvuni||5.007001| utilize||| uvchr_to_utf8_flags||5.007003| uvchr_to_utf8||5.007001| uvoffuni_to_utf8_flags||5.019004| uvuni_to_utf8_flags||5.007003| uvuni_to_utf8||5.007001| valid_utf8_to_uvchr||5.015009| valid_utf8_to_uvuni||5.015009| validate_proto||| validate_suid||| varname||| vcmp||5.009000| vcroak||5.006000| vdeb||5.007003| vform||5.006000| visit||| vivify_defelem||| vivify_ref||| vload_module|5.006000||p vmess||5.006000| vnewSVpvf|5.006000|5.004000|p vnormal||5.009002| vnumify||5.009000| vstringify||5.009000| vverify||5.009003| vwarner||5.006000| vwarn||5.006000| wait4pid||| warn_nocontext|||vn warn_sv||5.013001| warner_nocontext|||vn warner|5.006000|5.004000|pv warn|||v was_lvalue_sub||| watch||| whichsig_pvn||5.015004| whichsig_pv||5.015004| whichsig_sv||5.015004| whichsig||| win32_croak_not_implemented|||n with_queued_errors||| wrap_op_checker||5.015008| write_to_stderr||| xs_boot_epilog||| xs_handshake|||vn xs_version_bootcheck||| yyerror_pvn||| yyerror_pv||| yyerror||| yylex||| yyparse||| yyunlex||| yywarn||| ); if (exists $opt{'list-unsupported'}) { my $f; for $f (sort { lc $a cmp lc $b } keys %API) { next unless $API{$f}{todo}; print "$f ", '.'x(40-length($f)), " ", format_version($API{$f}{todo}), "\n"; } exit 0; } # Scan for possible replacement candidates my(%replace, %need, %hints, %warnings, %depends); my $replace = 0; my($hint, $define, $function); sub find_api { my $code = shift; $code =~ s{ / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]*) | "[^"\\]*(?:\\.[^"\\]*)*" | '[^'\\]*(?:\\.[^'\\]*)*' }{}egsx; grep { exists $API{$_} } $code =~ /(\w+)/mg; } while () { if ($hint) { my $h = $hint->[0] eq 'Hint' ? \%hints : \%warnings; if (m{^\s*\*\s(.*?)\s*$}) { for (@{$hint->[1]}) { $h->{$_} ||= ''; # suppress warning with older perls $h->{$_} .= "$1\n"; } } else { undef $hint } } $hint = [$1, [split /,?\s+/, $2]] if m{^\s*$rccs\s+(Hint|Warning):\s+(\w+(?:,?\s+\w+)*)\s*$}; if ($define) { if ($define->[1] =~ /\\$/) { $define->[1] .= $_; } else { if (exists $API{$define->[0]} && $define->[1] !~ /^DPPP_\(/) { my @n = find_api($define->[1]); push @{$depends{$define->[0]}}, @n if @n } undef $define; } } $define = [$1, $2] if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(.*)}; if ($function) { if (/^}/) { if (exists $API{$function->[0]}) { my @n = find_api($function->[1]); push @{$depends{$function->[0]}}, @n if @n } undef $function; } else { $function->[1] .= $_; } } $function = [$1, ''] if m{^DPPP_\(my_(\w+)\)}; $replace = $1 if m{^\s*$rccs\s+Replace:\s+(\d+)\s+$rcce\s*$}; $replace{$2} = $1 if $replace and m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+)}; $replace{$2} = $1 if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+).*$rccs\s+Replace\s+$rcce}; $replace{$1} = $2 if m{^\s*$rccs\s+Replace (\w+) with (\w+)\s+$rcce\s*$}; if (m{^\s*$rccs\s+(\w+(\s*,\s*\w+)*)\s+depends\s+on\s+(\w+(\s*,\s*\w+)*)\s+$rcce\s*$}) { my @deps = map { s/\s+//g; $_ } split /,/, $3; my $d; for $d (map { s/\s+//g; $_ } split /,/, $1) { push @{$depends{$d}}, @deps; } } $need{$1} = 1 if m{^#if\s+defined\(NEED_(\w+)(?:_GLOBAL)?\)}; } for (values %depends) { my %s; $_ = [sort grep !$s{$_}++, @$_]; } if (exists $opt{'api-info'}) { my $f; my $count = 0; my $match = $opt{'api-info'} =~ m!^/(.*)/$! ? $1 : "^\Q$opt{'api-info'}\E\$"; for $f (sort { lc $a cmp lc $b } keys %API) { next unless $f =~ /$match/; print "\n=== $f ===\n\n"; my $info = 0; if ($API{$f}{base} || $API{$f}{todo}) { my $base = format_version($API{$f}{base} || $API{$f}{todo}); print "Supported at least starting from perl-$base.\n"; $info++; } if ($API{$f}{provided}) { my $todo = $API{$f}{todo} ? format_version($API{$f}{todo}) : "5.003"; print "Support by $ppport provided back to perl-$todo.\n"; print "Support needs to be explicitly requested by NEED_$f.\n" if exists $need{$f}; print "Depends on: ", join(', ', @{$depends{$f}}), ".\n" if exists $depends{$f}; print "\n$hints{$f}" if exists $hints{$f}; print "\nWARNING:\n$warnings{$f}" if exists $warnings{$f}; $info++; } print "No portability information available.\n" unless $info; $count++; } $count or print "Found no API matching '$opt{'api-info'}'."; print "\n"; exit 0; } if (exists $opt{'list-provided'}) { my $f; for $f (sort { lc $a cmp lc $b } keys %API) { next unless $API{$f}{provided}; my @flags; push @flags, 'explicit' if exists $need{$f}; push @flags, 'depend' if exists $depends{$f}; push @flags, 'hint' if exists $hints{$f}; push @flags, 'warning' if exists $warnings{$f}; my $flags = @flags ? ' ['.join(', ', @flags).']' : ''; print "$f$flags\n"; } exit 0; } my @files; my @srcext = qw( .xs .c .h .cc .cpp -c.inc -xs.inc ); my $srcext = join '|', map { quotemeta $_ } @srcext; if (@ARGV) { my %seen; for (@ARGV) { if (-e) { if (-f) { push @files, $_ unless $seen{$_}++; } else { warn "'$_' is not a file.\n" } } else { my @new = grep { -f } glob $_ or warn "'$_' does not exist.\n"; push @files, grep { !$seen{$_}++ } @new; } } } else { eval { require File::Find; File::Find::find(sub { $File::Find::name =~ /($srcext)$/i and push @files, $File::Find::name; }, '.'); }; if ($@) { @files = map { glob "*$_" } @srcext; } } if (!@ARGV || $opt{filter}) { my(@in, @out); my %xsc = map { /(.*)\.xs$/ ? ("$1.c" => 1, "$1.cc" => 1) : () } @files; for (@files) { my $out = exists $xsc{$_} || /\b\Q$ppport\E$/i || !/($srcext)$/i; push @{ $out ? \@out : \@in }, $_; } if (@ARGV && @out) { warning("Skipping the following files (use --nofilter to avoid this):\n| ", join "\n| ", @out); } @files = @in; } die "No input files given!\n" unless @files; my(%files, %global, %revreplace); %revreplace = reverse %replace; my $filename; my $patch_opened = 0; for $filename (@files) { unless (open IN, "<$filename") { warn "Unable to read from $filename: $!\n"; next; } info("Scanning $filename ..."); my $c = do { local $/; }; close IN; my %file = (orig => $c, changes => 0); # Temporarily remove C/XS comments and strings from the code my @ccom; $c =~ s{ ( ^$HS*\#$HS*include\b[^\r\n]+\b(?:\Q$ppport\E|XSUB\.h)\b[^\r\n]* | ^$HS*\#$HS*(?:define|elif|if(?:def)?)\b[^\r\n]* ) | ( ^$HS*\#[^\r\n]* | "[^"\\]*(?:\\.[^"\\]*)*" | '[^'\\]*(?:\\.[^'\\]*)*' | / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]* ) ) }{ defined $2 and push @ccom, $2; defined $1 ? $1 : "$ccs$#ccom$cce" }mgsex; $file{ccom} = \@ccom; $file{code} = $c; $file{has_inc_ppport} = $c =~ /^$HS*#$HS*include[^\r\n]+\b\Q$ppport\E\b/m; my $func; for $func (keys %API) { my $match = $func; $match .= "|$revreplace{$func}" if exists $revreplace{$func}; if ($c =~ /\b(?:Perl_)?($match)\b/) { $file{uses_replace}{$1}++ if exists $revreplace{$func} && $1 eq $revreplace{$func}; $file{uses_Perl}{$func}++ if $c =~ /\bPerl_$func\b/; if (exists $API{$func}{provided}) { $file{uses_provided}{$func}++; if (!exists $API{$func}{base} || $API{$func}{base} > $opt{'compat-version'}) { $file{uses}{$func}++; my @deps = rec_depend($func); if (@deps) { $file{uses_deps}{$func} = \@deps; for (@deps) { $file{uses}{$_} = 0 unless exists $file{uses}{$_}; } } for ($func, @deps) { $file{needs}{$_} = 'static' if exists $need{$_}; } } } if (exists $API{$func}{todo} && $API{$func}{todo} > $opt{'compat-version'}) { if ($c =~ /\b$func\b/) { $file{uses_todo}{$func}++; } } } } while ($c =~ /^$HS*#$HS*define$HS+(NEED_(\w+?)(_GLOBAL)?)\b/mg) { if (exists $need{$2}) { $file{defined $3 ? 'needed_global' : 'needed_static'}{$2}++; } else { warning("Possibly wrong #define $1 in $filename") } } for (qw(uses needs uses_todo needed_global needed_static)) { for $func (keys %{$file{$_}}) { push @{$global{$_}{$func}}, $filename; } } $files{$filename} = \%file; } # Globally resolve NEED_'s my $need; for $need (keys %{$global{needs}}) { if (@{$global{needs}{$need}} > 1) { my @targets = @{$global{needs}{$need}}; my @t = grep $files{$_}{needed_global}{$need}, @targets; @targets = @t if @t; @t = grep /\.xs$/i, @targets; @targets = @t if @t; my $target = shift @targets; $files{$target}{needs}{$need} = 'global'; for (@{$global{needs}{$need}}) { $files{$_}{needs}{$need} = 'extern' if $_ ne $target; } } } for $filename (@files) { exists $files{$filename} or next; info("=== Analyzing $filename ==="); my %file = %{$files{$filename}}; my $func; my $c = $file{code}; my $warnings = 0; for $func (sort keys %{$file{uses_Perl}}) { if ($API{$func}{varargs}) { unless ($API{$func}{nothxarg}) { my $changes = ($c =~ s{\b(Perl_$func\s*\(\s*)(?!aTHX_?)(\)|[^\s)]*\))} { $1 . ($2 eq ')' ? 'aTHX' : 'aTHX_ ') . $2 }ge); if ($changes) { warning("Doesn't pass interpreter argument aTHX to Perl_$func"); $file{changes} += $changes; } } } else { warning("Uses Perl_$func instead of $func"); $file{changes} += ($c =~ s{\bPerl_$func(\s*)\((\s*aTHX_?)?\s*} {$func$1(}g); } } for $func (sort keys %{$file{uses_replace}}) { warning("Uses $func instead of $replace{$func}"); $file{changes} += ($c =~ s/\b$func\b/$replace{$func}/g); } for $func (sort keys %{$file{uses_provided}}) { if ($file{uses}{$func}) { if (exists $file{uses_deps}{$func}) { diag("Uses $func, which depends on ", join(', ', @{$file{uses_deps}{$func}})); } else { diag("Uses $func"); } } $warnings += hint($func); } unless ($opt{quiet}) { for $func (sort keys %{$file{uses_todo}}) { print "*** WARNING: Uses $func, which may not be portable below perl ", format_version($API{$func}{todo}), ", even with '$ppport'\n"; $warnings++; } } for $func (sort keys %{$file{needed_static}}) { my $message = ''; if (not exists $file{uses}{$func}) { $message = "No need to define NEED_$func if $func is never used"; } elsif (exists $file{needs}{$func} && $file{needs}{$func} ne 'static') { $message = "No need to define NEED_$func when already needed globally"; } if ($message) { diag($message); $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_$func\b.*$LF//mg); } } for $func (sort keys %{$file{needed_global}}) { my $message = ''; if (not exists $global{uses}{$func}) { $message = "No need to define NEED_${func}_GLOBAL if $func is never used"; } elsif (exists $file{needs}{$func}) { if ($file{needs}{$func} eq 'extern') { $message = "No need to define NEED_${func}_GLOBAL when already needed globally"; } elsif ($file{needs}{$func} eq 'static') { $message = "No need to define NEED_${func}_GLOBAL when only used in this file"; } } if ($message) { diag($message); $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_${func}_GLOBAL\b.*$LF//mg); } } $file{needs_inc_ppport} = keys %{$file{uses}}; if ($file{needs_inc_ppport}) { my $pp = ''; for $func (sort keys %{$file{needs}}) { my $type = $file{needs}{$func}; next if $type eq 'extern'; my $suffix = $type eq 'global' ? '_GLOBAL' : ''; unless (exists $file{"needed_$type"}{$func}) { if ($type eq 'global') { diag("Files [@{$global{needs}{$func}}] need $func, adding global request"); } else { diag("File needs $func, adding static request"); } $pp .= "#define NEED_$func$suffix\n"; } } if ($pp && ($c =~ s/^(?=$HS*#$HS*define$HS+NEED_\w+)/$pp/m)) { $pp = ''; $file{changes}++; } unless ($file{has_inc_ppport}) { diag("Needs to include '$ppport'"); $pp .= qq(#include "$ppport"\n) } if ($pp) { $file{changes} += ($c =~ s/^($HS*#$HS*define$HS+NEED_\w+.*?)^/$1$pp/ms) || ($c =~ s/^(?=$HS*#$HS*include.*\Q$ppport\E)/$pp/m) || ($c =~ s/^($HS*#$HS*include.*XSUB.*\s*?)^/$1$pp/m) || ($c =~ s/^/$pp/); } } else { if ($file{has_inc_ppport}) { diag("No need to include '$ppport'"); $file{changes} += ($c =~ s/^$HS*?#$HS*include.*\Q$ppport\E.*?$LF//m); } } # put back in our C comments my $ix; my $cppc = 0; my @ccom = @{$file{ccom}}; for $ix (0 .. $#ccom) { if (!$opt{cplusplus} && $ccom[$ix] =~ s!^//!!) { $cppc++; $file{changes} += $c =~ s/$rccs$ix$rcce/$ccs$ccom[$ix] $cce/; } else { $c =~ s/$rccs$ix$rcce/$ccom[$ix]/; } } if ($cppc) { my $s = $cppc != 1 ? 's' : ''; warning("Uses $cppc C++ style comment$s, which is not portable"); } my $s = $warnings != 1 ? 's' : ''; my $warn = $warnings ? " ($warnings warning$s)" : ''; info("Analysis completed$warn"); if ($file{changes}) { if (exists $opt{copy}) { my $newfile = "$filename$opt{copy}"; if (-e $newfile) { error("'$newfile' already exists, refusing to write copy of '$filename'"); } else { local *F; if (open F, ">$newfile") { info("Writing copy of '$filename' with changes to '$newfile'"); print F $c; close F; } else { error("Cannot open '$newfile' for writing: $!"); } } } elsif (exists $opt{patch} || $opt{changes}) { if (exists $opt{patch}) { unless ($patch_opened) { if (open PATCH, ">$opt{patch}") { $patch_opened = 1; } else { error("Cannot open '$opt{patch}' for writing: $!"); delete $opt{patch}; $opt{changes} = 1; goto fallback; } } mydiff(\*PATCH, $filename, $c); } else { fallback: info("Suggested changes:"); mydiff(\*STDOUT, $filename, $c); } } else { my $s = $file{changes} == 1 ? '' : 's'; info("$file{changes} potentially required change$s detected"); } } else { info("Looks good"); } } close PATCH if $patch_opened; exit 0; sub try_use { eval "use @_;"; return $@ eq '' } sub mydiff { local *F = shift; my($file, $str) = @_; my $diff; if (exists $opt{diff}) { $diff = run_diff($opt{diff}, $file, $str); } if (!defined $diff and try_use('Text::Diff')) { $diff = Text::Diff::diff($file, \$str, { STYLE => 'Unified' }); $diff = <
$tmp") { print F $str; close F; if (open F, "$prog $file $tmp |") { while () { s/\Q$tmp\E/$file.patched/; $diff .= $_; } close F; unlink $tmp; return $diff; } unlink $tmp; } else { error("Cannot open '$tmp' for writing: $!"); } return undef; } sub rec_depend { my($func, $seen) = @_; return () unless exists $depends{$func}; $seen = {%{$seen||{}}}; return () if $seen->{$func}++; my %s; grep !$s{$_}++, map { ($_, rec_depend($_, $seen)) } @{$depends{$func}}; } sub parse_version { my $ver = shift; if ($ver =~ /^(\d+)\.(\d+)\.(\d+)$/) { return ($1, $2, $3); } elsif ($ver !~ /^\d+\.[\d_]+$/) { die "cannot parse version '$ver'\n"; } $ver =~ s/_//g; $ver =~ s/$/000000/; my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/; $v = int $v; $s = int $s; if ($r < 5 || ($r == 5 && $v < 6)) { if ($s % 10) { die "cannot parse version '$ver'\n"; } } return ($r, $v, $s); } sub format_version { my $ver = shift; $ver =~ s/$/000000/; my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/; $v = int $v; $s = int $s; if ($r < 5 || ($r == 5 && $v < 6)) { if ($s % 10) { die "invalid version '$ver'\n"; } $s /= 10; $ver = sprintf "%d.%03d", $r, $v; $s > 0 and $ver .= sprintf "_%02d", $s; return $ver; } return sprintf "%d.%d.%d", $r, $v, $s; } sub info { $opt{quiet} and return; print @_, "\n"; } sub diag { $opt{quiet} and return; $opt{diag} and print @_, "\n"; } sub warning { $opt{quiet} and return; print "*** ", @_, "\n"; } sub error { print "*** ERROR: ", @_, "\n"; } my %given_hints; my %given_warnings; sub hint { $opt{quiet} and return; my $func = shift; my $rv = 0; if (exists $warnings{$func} && !$given_warnings{$func}++) { my $warn = $warnings{$func}; $warn =~ s!^!*** !mg; print "*** WARNING: $func\n", $warn; $rv++; } if ($opt{hints} && exists $hints{$func} && !$given_hints{$func}++) { my $hint = $hints{$func}; $hint =~ s/^/ /mg; print " --- hint for $func ---\n", $hint; } $rv; } sub usage { my($usage) = do { local(@ARGV,$/)=($0); <> } =~ /^=head\d$HS+SYNOPSIS\s*^(.*?)\s*^=/ms; my %M = ( 'I' => '*' ); $usage =~ s/^\s*perl\s+\S+/$^X $0/; $usage =~ s/([A-Z])<([^>]+)>/$M{$1}$2$M{$1}/g; print < }; my($copy) = $self =~ /^=head\d\s+COPYRIGHT\s*^(.*?)^=\w+/ms; $copy =~ s/^(?=\S+)/ /gms; $self =~ s/^$HS+Do NOT edit.*?(?=^-)/$copy/ms; $self =~ s/^SKIP.*(?=^__DATA__)/SKIP if (\@ARGV && \$ARGV[0] eq '--unstrip') { eval { require Devel::PPPort }; \$@ and die "Cannot require Devel::PPPort, please install.\\n"; if (eval \$Devel::PPPort::VERSION < $VERSION) { die "$0 was originally generated with Devel::PPPort $VERSION.\\n" . "Your Devel::PPPort is only version \$Devel::PPPort::VERSION.\\n" . "Please install a newer version, or --unstrip will not work.\\n"; } Devel::PPPort::WriteFile(\$0); exit 0; } print <$0" or die "cannot strip $0: $!\n"; print OUT "$pl$c\n"; exit 0; } __DATA__ */ #ifndef _P_P_PORTABILITY_H_ #define _P_P_PORTABILITY_H_ #ifndef DPPP_NAMESPACE # define DPPP_NAMESPACE DPPP_ #endif #define DPPP_CAT2(x,y) CAT2(x,y) #define DPPP_(name) DPPP_CAT2(DPPP_NAMESPACE, name) #ifndef PERL_REVISION # if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION)) # define PERL_PATCHLEVEL_H_IMPLICIT # include # endif # if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL))) # include # endif # ifndef PERL_REVISION # define PERL_REVISION (5) /* Replace: 1 */ # define PERL_VERSION PATCHLEVEL # define PERL_SUBVERSION SUBVERSION /* Replace PERL_PATCHLEVEL with PERL_VERSION */ /* Replace: 0 */ # endif #endif #define _dpppDEC2BCD(dec) ((((dec)/100)<<8)|((((dec)%100)/10)<<4)|((dec)%10)) #define PERL_BCDVERSION ((_dpppDEC2BCD(PERL_REVISION)<<24)|(_dpppDEC2BCD(PERL_VERSION)<<12)|_dpppDEC2BCD(PERL_SUBVERSION)) /* It is very unlikely that anyone will try to use this with Perl 6 (or greater), but who knows. */ #if PERL_REVISION != 5 # error ppport.h only works with Perl version 5 #endif /* PERL_REVISION != 5 */ #ifndef dTHR # define dTHR dNOOP #endif #ifndef dTHX # define dTHX dNOOP #endif #ifndef dTHXa # define dTHXa(x) dNOOP #endif #ifndef pTHX # define pTHX void #endif #ifndef pTHX_ # define pTHX_ #endif #ifndef aTHX # define aTHX #endif #ifndef aTHX_ # define aTHX_ #endif #if (PERL_BCDVERSION < 0x5006000) # ifdef USE_THREADS # define aTHXR thr # define aTHXR_ thr, # else # define aTHXR # define aTHXR_ # endif # define dTHXR dTHR #else # define aTHXR aTHX # define aTHXR_ aTHX_ # define dTHXR dTHX #endif #ifndef dTHXoa # define dTHXoa(x) dTHXa(x) #endif #ifdef I_LIMITS # include #endif #ifndef PERL_UCHAR_MIN # define PERL_UCHAR_MIN ((unsigned char)0) #endif #ifndef PERL_UCHAR_MAX # ifdef UCHAR_MAX # define PERL_UCHAR_MAX ((unsigned char)UCHAR_MAX) # else # ifdef MAXUCHAR # define PERL_UCHAR_MAX ((unsigned char)MAXUCHAR) # else # define PERL_UCHAR_MAX ((unsigned char)~(unsigned)0) # endif # endif #endif #ifndef PERL_USHORT_MIN # define PERL_USHORT_MIN ((unsigned short)0) #endif #ifndef PERL_USHORT_MAX # ifdef USHORT_MAX # define PERL_USHORT_MAX ((unsigned short)USHORT_MAX) # else # ifdef MAXUSHORT # define PERL_USHORT_MAX ((unsigned short)MAXUSHORT) # else # ifdef USHRT_MAX # define PERL_USHORT_MAX ((unsigned short)USHRT_MAX) # else # define PERL_USHORT_MAX ((unsigned short)~(unsigned)0) # endif # endif # endif #endif #ifndef PERL_SHORT_MAX # ifdef SHORT_MAX # define PERL_SHORT_MAX ((short)SHORT_MAX) # else # ifdef MAXSHORT /* Often used in */ # define PERL_SHORT_MAX ((short)MAXSHORT) # else # ifdef SHRT_MAX # define PERL_SHORT_MAX ((short)SHRT_MAX) # else # define PERL_SHORT_MAX ((short) (PERL_USHORT_MAX >> 1)) # endif # endif # endif #endif #ifndef PERL_SHORT_MIN # ifdef SHORT_MIN # define PERL_SHORT_MIN ((short)SHORT_MIN) # else # ifdef MINSHORT # define PERL_SHORT_MIN ((short)MINSHORT) # else # ifdef SHRT_MIN # define PERL_SHORT_MIN ((short)SHRT_MIN) # else # define PERL_SHORT_MIN (-PERL_SHORT_MAX - ((3 & -1) == 3)) # endif # endif # endif #endif #ifndef PERL_UINT_MAX # ifdef UINT_MAX # define PERL_UINT_MAX ((unsigned int)UINT_MAX) # else # ifdef MAXUINT # define PERL_UINT_MAX ((unsigned int)MAXUINT) # else # define PERL_UINT_MAX (~(unsigned int)0) # endif # endif #endif #ifndef PERL_UINT_MIN # define PERL_UINT_MIN ((unsigned int)0) #endif #ifndef PERL_INT_MAX # ifdef INT_MAX # define PERL_INT_MAX ((int)INT_MAX) # else # ifdef MAXINT /* Often used in */ # define PERL_INT_MAX ((int)MAXINT) # else # define PERL_INT_MAX ((int)(PERL_UINT_MAX >> 1)) # endif # endif #endif #ifndef PERL_INT_MIN # ifdef INT_MIN # define PERL_INT_MIN ((int)INT_MIN) # else # ifdef MININT # define PERL_INT_MIN ((int)MININT) # else # define PERL_INT_MIN (-PERL_INT_MAX - ((3 & -1) == 3)) # endif # endif #endif #ifndef PERL_ULONG_MAX # ifdef ULONG_MAX # define PERL_ULONG_MAX ((unsigned long)ULONG_MAX) # else # ifdef MAXULONG # define PERL_ULONG_MAX ((unsigned long)MAXULONG) # else # define PERL_ULONG_MAX (~(unsigned long)0) # endif # endif #endif #ifndef PERL_ULONG_MIN # define PERL_ULONG_MIN ((unsigned long)0L) #endif #ifndef PERL_LONG_MAX # ifdef LONG_MAX # define PERL_LONG_MAX ((long)LONG_MAX) # else # ifdef MAXLONG # define PERL_LONG_MAX ((long)MAXLONG) # else # define PERL_LONG_MAX ((long) (PERL_ULONG_MAX >> 1)) # endif # endif #endif #ifndef PERL_LONG_MIN # ifdef LONG_MIN # define PERL_LONG_MIN ((long)LONG_MIN) # else # ifdef MINLONG # define PERL_LONG_MIN ((long)MINLONG) # else # define PERL_LONG_MIN (-PERL_LONG_MAX - ((3 & -1) == 3)) # endif # endif #endif #if defined(HAS_QUAD) && (defined(convex) || defined(uts)) # ifndef PERL_UQUAD_MAX # ifdef ULONGLONG_MAX # define PERL_UQUAD_MAX ((unsigned long long)ULONGLONG_MAX) # else # ifdef MAXULONGLONG # define PERL_UQUAD_MAX ((unsigned long long)MAXULONGLONG) # else # define PERL_UQUAD_MAX (~(unsigned long long)0) # endif # endif # endif # ifndef PERL_UQUAD_MIN # define PERL_UQUAD_MIN ((unsigned long long)0L) # endif # ifndef PERL_QUAD_MAX # ifdef LONGLONG_MAX # define PERL_QUAD_MAX ((long long)LONGLONG_MAX) # else # ifdef MAXLONGLONG # define PERL_QUAD_MAX ((long long)MAXLONGLONG) # else # define PERL_QUAD_MAX ((long long) (PERL_UQUAD_MAX >> 1)) # endif # endif # endif # ifndef PERL_QUAD_MIN # ifdef LONGLONG_MIN # define PERL_QUAD_MIN ((long long)LONGLONG_MIN) # else # ifdef MINLONGLONG # define PERL_QUAD_MIN ((long long)MINLONGLONG) # else # define PERL_QUAD_MIN (-PERL_QUAD_MAX - ((3 & -1) == 3)) # endif # endif # endif #endif /* This is based on code from 5.003 perl.h */ #ifdef HAS_QUAD # ifdef cray #ifndef IVTYPE # define IVTYPE int #endif #ifndef IV_MIN # define IV_MIN PERL_INT_MIN #endif #ifndef IV_MAX # define IV_MAX PERL_INT_MAX #endif #ifndef UV_MIN # define UV_MIN PERL_UINT_MIN #endif #ifndef UV_MAX # define UV_MAX PERL_UINT_MAX #endif # ifdef INTSIZE #ifndef IVSIZE # define IVSIZE INTSIZE #endif # endif # else # if defined(convex) || defined(uts) #ifndef IVTYPE # define IVTYPE long long #endif #ifndef IV_MIN # define IV_MIN PERL_QUAD_MIN #endif #ifndef IV_MAX # define IV_MAX PERL_QUAD_MAX #endif #ifndef UV_MIN # define UV_MIN PERL_UQUAD_MIN #endif #ifndef UV_MAX # define UV_MAX PERL_UQUAD_MAX #endif # ifdef LONGLONGSIZE #ifndef IVSIZE # define IVSIZE LONGLONGSIZE #endif # endif # else #ifndef IVTYPE # define IVTYPE long #endif #ifndef IV_MIN # define IV_MIN PERL_LONG_MIN #endif #ifndef IV_MAX # define IV_MAX PERL_LONG_MAX #endif #ifndef UV_MIN # define UV_MIN PERL_ULONG_MIN #endif #ifndef UV_MAX # define UV_MAX PERL_ULONG_MAX #endif # ifdef LONGSIZE #ifndef IVSIZE # define IVSIZE LONGSIZE #endif # endif # endif # endif #ifndef IVSIZE # define IVSIZE 8 #endif #ifndef LONGSIZE # define LONGSIZE 8 #endif #ifndef PERL_QUAD_MIN # define PERL_QUAD_MIN IV_MIN #endif #ifndef PERL_QUAD_MAX # define PERL_QUAD_MAX IV_MAX #endif #ifndef PERL_UQUAD_MIN # define PERL_UQUAD_MIN UV_MIN #endif #ifndef PERL_UQUAD_MAX # define PERL_UQUAD_MAX UV_MAX #endif #else #ifndef IVTYPE # define IVTYPE long #endif #ifndef LONGSIZE # define LONGSIZE 4 #endif #ifndef IV_MIN # define IV_MIN PERL_LONG_MIN #endif #ifndef IV_MAX # define IV_MAX PERL_LONG_MAX #endif #ifndef UV_MIN # define UV_MIN PERL_ULONG_MIN #endif #ifndef UV_MAX # define UV_MAX PERL_ULONG_MAX #endif #endif #ifndef IVSIZE # ifdef LONGSIZE # define IVSIZE LONGSIZE # else # define IVSIZE 4 /* A bold guess, but the best we can make. */ # endif #endif #ifndef UVTYPE # define UVTYPE unsigned IVTYPE #endif #ifndef UVSIZE # define UVSIZE IVSIZE #endif #ifndef sv_setuv # define sv_setuv(sv, uv) \ STMT_START { \ UV TeMpUv = uv; \ if (TeMpUv <= IV_MAX) \ sv_setiv(sv, TeMpUv); \ else \ sv_setnv(sv, (double)TeMpUv); \ } STMT_END #endif #ifndef newSVuv # define newSVuv(uv) ((uv) <= IV_MAX ? newSViv((IV)uv) : newSVnv((NV)uv)) #endif #ifndef sv_2uv # define sv_2uv(sv) ((PL_Sv = (sv)), (UV) (SvNOK(PL_Sv) ? SvNV(PL_Sv) : sv_2nv(PL_Sv))) #endif #ifndef SvUVX # define SvUVX(sv) ((UV)SvIVX(sv)) #endif #ifndef SvUVXx # define SvUVXx(sv) SvUVX(sv) #endif #ifndef SvUV # define SvUV(sv) (SvIOK(sv) ? SvUVX(sv) : sv_2uv(sv)) #endif #ifndef SvUVx # define SvUVx(sv) ((PL_Sv = (sv)), SvUV(PL_Sv)) #endif /* Hint: sv_uv * Always use the SvUVx() macro instead of sv_uv(). */ #ifndef sv_uv # define sv_uv(sv) SvUVx(sv) #endif #if !defined(SvUOK) && defined(SvIOK_UV) # define SvUOK(sv) SvIOK_UV(sv) #endif #ifndef XST_mUV # define XST_mUV(i,v) (ST(i) = sv_2mortal(newSVuv(v)) ) #endif #ifndef XSRETURN_UV # define XSRETURN_UV(v) STMT_START { XST_mUV(0,v); XSRETURN(1); } STMT_END #endif #ifndef PUSHu # define PUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); PUSHTARG; } STMT_END #endif #ifndef XPUSHu # define XPUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); XPUSHTARG; } STMT_END #endif #ifdef HAS_MEMCMP #ifndef memNE # define memNE(s1,s2,l) (memcmp(s1,s2,l)) #endif #ifndef memEQ # define memEQ(s1,s2,l) (!memcmp(s1,s2,l)) #endif #else #ifndef memNE # define memNE(s1,s2,l) (bcmp(s1,s2,l)) #endif #ifndef memEQ # define memEQ(s1,s2,l) (!bcmp(s1,s2,l)) #endif #endif #ifndef memEQs # define memEQs(s1, l, s2) \ (sizeof(s2)-1 == l && memEQ(s1, (s2 ""), (sizeof(s2)-1))) #endif #ifndef memNEs # define memNEs(s1, l, s2) !memEQs(s1, l, s2) #endif #ifndef MoveD # define MoveD(s,d,n,t) memmove((char*)(d),(char*)(s), (n) * sizeof(t)) #endif #ifndef CopyD # define CopyD(s,d,n,t) memcpy((char*)(d),(char*)(s), (n) * sizeof(t)) #endif #ifdef HAS_MEMSET #ifndef ZeroD # define ZeroD(d,n,t) memzero((char*)(d), (n) * sizeof(t)) #endif #else #ifndef ZeroD # define ZeroD(d,n,t) ((void)memzero((char*)(d), (n) * sizeof(t)), d) #endif #endif #ifndef PoisonWith # define PoisonWith(d,n,t,b) (void)memset((char*)(d), (U8)(b), (n) * sizeof(t)) #endif #ifndef PoisonNew # define PoisonNew(d,n,t) PoisonWith(d,n,t,0xAB) #endif #ifndef PoisonFree # define PoisonFree(d,n,t) PoisonWith(d,n,t,0xEF) #endif #ifndef Poison # define Poison(d,n,t) PoisonFree(d,n,t) #endif #ifndef Newx # define Newx(v,n,t) New(0,v,n,t) #endif #ifndef Newxc # define Newxc(v,n,t,c) Newc(0,v,n,t,c) #endif #ifndef Newxz # define Newxz(v,n,t) Newz(0,v,n,t) #endif #ifndef PERL_MAGIC_qr # define PERL_MAGIC_qr 'r' #endif #ifndef cBOOL # define cBOOL(cbool) ((cbool) ? (bool)1 : (bool)0) #endif #ifndef OpHAS_SIBLING # define OpHAS_SIBLING(o) (cBOOL((o)->op_sibling)) #endif #ifndef OpSIBLING # define OpSIBLING(o) (0 + (o)->op_sibling) #endif #ifndef OpMORESIB_set # define OpMORESIB_set(o, sib) ((o)->op_sibling = (sib)) #endif #ifndef OpLASTSIB_set # define OpLASTSIB_set(o, parent) ((o)->op_sibling = NULL) #endif #ifndef OpMAYBESIB_set # define OpMAYBESIB_set(o, sib, parent) ((o)->op_sibling = (sib)) #endif #ifndef SvRX #if defined(NEED_SvRX) static void * DPPP_(my_SvRX)(pTHX_ SV *rv); static #else extern void * DPPP_(my_SvRX)(pTHX_ SV *rv); #endif #ifdef SvRX # undef SvRX #endif #define SvRX(a) DPPP_(my_SvRX)(aTHX_ a) #if defined(NEED_SvRX) || defined(NEED_SvRX_GLOBAL) void * DPPP_(my_SvRX)(pTHX_ SV *rv) { if (SvROK(rv)) { SV *sv = SvRV(rv); if (SvMAGICAL(sv)) { MAGIC *mg = mg_find(sv, PERL_MAGIC_qr); if (mg && mg->mg_obj) { return mg->mg_obj; } } } return 0; } #endif #endif #ifndef SvRXOK # define SvRXOK(sv) (!!SvRX(sv)) #endif #ifndef PERL_UNUSED_DECL # ifdef HASATTRIBUTE # if (defined(__GNUC__) && defined(__cplusplus)) || defined(__INTEL_COMPILER) # define PERL_UNUSED_DECL # else # define PERL_UNUSED_DECL __attribute__((unused)) # endif # else # define PERL_UNUSED_DECL # endif #endif #ifndef PERL_UNUSED_ARG # if defined(lint) && defined(S_SPLINT_S) /* www.splint.org */ # include # define PERL_UNUSED_ARG(x) NOTE(ARGUNUSED(x)) # else # define PERL_UNUSED_ARG(x) ((void)x) # endif #endif #ifndef PERL_UNUSED_VAR # define PERL_UNUSED_VAR(x) ((void)x) #endif #ifndef PERL_UNUSED_CONTEXT # ifdef USE_ITHREADS # define PERL_UNUSED_CONTEXT PERL_UNUSED_ARG(my_perl) # else # define PERL_UNUSED_CONTEXT # endif #endif #ifndef PERL_UNUSED_RESULT # if defined(__GNUC__) && defined(HASATTRIBUTE_WARN_UNUSED_RESULT) # define PERL_UNUSED_RESULT(v) STMT_START { __typeof__(v) z = (v); (void)sizeof(z); } STMT_END # else # define PERL_UNUSED_RESULT(v) ((void)(v)) # endif #endif #ifndef NOOP # define NOOP /*EMPTY*/(void)0 #endif #ifndef dNOOP # define dNOOP extern int /*@unused@*/ Perl___notused PERL_UNUSED_DECL #endif #ifndef NVTYPE # if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) # define NVTYPE long double # else # define NVTYPE double # endif typedef NVTYPE NV; #endif #ifndef INT2PTR # if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE) # define PTRV UV # define INT2PTR(any,d) (any)(d) # else # if PTRSIZE == LONGSIZE # define PTRV unsigned long # else # define PTRV unsigned # endif # define INT2PTR(any,d) (any)(PTRV)(d) # endif #endif #ifndef PTR2ul # if PTRSIZE == LONGSIZE # define PTR2ul(p) (unsigned long)(p) # else # define PTR2ul(p) INT2PTR(unsigned long,p) # endif #endif #ifndef PTR2nat # define PTR2nat(p) (PTRV)(p) #endif #ifndef NUM2PTR # define NUM2PTR(any,d) (any)PTR2nat(d) #endif #ifndef PTR2IV # define PTR2IV(p) INT2PTR(IV,p) #endif #ifndef PTR2UV # define PTR2UV(p) INT2PTR(UV,p) #endif #ifndef PTR2NV # define PTR2NV(p) NUM2PTR(NV,p) #endif #undef START_EXTERN_C #undef END_EXTERN_C #undef EXTERN_C #ifdef __cplusplus # define START_EXTERN_C extern "C" { # define END_EXTERN_C } # define EXTERN_C extern "C" #else # define START_EXTERN_C # define END_EXTERN_C # define EXTERN_C extern #endif #if defined(PERL_GCC_PEDANTIC) # ifndef PERL_GCC_BRACE_GROUPS_FORBIDDEN # define PERL_GCC_BRACE_GROUPS_FORBIDDEN # endif #endif #if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) && !defined(__cplusplus) # ifndef PERL_USE_GCC_BRACE_GROUPS # define PERL_USE_GCC_BRACE_GROUPS # endif #endif #undef STMT_START #undef STMT_END #ifdef PERL_USE_GCC_BRACE_GROUPS # define STMT_START (void)( /* gcc supports ``({ STATEMENTS; })'' */ # define STMT_END ) #else # if defined(VOIDFLAGS) && (VOIDFLAGS) && (defined(sun) || defined(__sun__)) && !defined(__GNUC__) # define STMT_START if (1) # define STMT_END else (void)0 # else # define STMT_START do # define STMT_END while (0) # endif #endif #ifndef boolSV # define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no) #endif /* DEFSV appears first in 5.004_56 */ #ifndef DEFSV # define DEFSV GvSV(PL_defgv) #endif #ifndef SAVE_DEFSV # define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv)) #endif #ifndef DEFSV_set # define DEFSV_set(sv) (DEFSV = (sv)) #endif /* Older perls (<=5.003) lack AvFILLp */ #ifndef AvFILLp # define AvFILLp AvFILL #endif #ifndef ERRSV # define ERRSV get_sv("@",FALSE) #endif /* Hint: gv_stashpvn * This function's backport doesn't support the length parameter, but * rather ignores it. Portability can only be ensured if the length * parameter is used for speed reasons, but the length can always be * correctly computed from the string argument. */ #ifndef gv_stashpvn # define gv_stashpvn(str,len,create) gv_stashpv(str,create) #endif /* Replace: 1 */ #ifndef get_cv # define get_cv perl_get_cv #endif #ifndef get_sv # define get_sv perl_get_sv #endif #ifndef get_av # define get_av perl_get_av #endif #ifndef get_hv # define get_hv perl_get_hv #endif /* Replace: 0 */ #ifndef dUNDERBAR # define dUNDERBAR dNOOP #endif #ifndef UNDERBAR # define UNDERBAR DEFSV #endif #ifndef dAX # define dAX I32 ax = MARK - PL_stack_base + 1 #endif #ifndef dITEMS # define dITEMS I32 items = SP - MARK #endif #ifndef dXSTARG # define dXSTARG SV * targ = sv_newmortal() #endif #ifndef dAXMARK # define dAXMARK I32 ax = POPMARK; \ register SV ** const mark = PL_stack_base + ax++ #endif #ifndef XSprePUSH # define XSprePUSH (sp = PL_stack_base + ax - 1) #endif #if (PERL_BCDVERSION < 0x5005000) # undef XSRETURN # define XSRETURN(off) \ STMT_START { \ PL_stack_sp = PL_stack_base + ax + ((off) - 1); \ return; \ } STMT_END #endif #ifndef XSPROTO # define XSPROTO(name) void name(pTHX_ CV* cv) #endif #ifndef SVfARG # define SVfARG(p) ((void*)(p)) #endif #ifndef PERL_ABS # define PERL_ABS(x) ((x) < 0 ? -(x) : (x)) #endif #ifndef dVAR # define dVAR dNOOP #endif #ifndef SVf # define SVf "_" #endif #ifndef UTF8_MAXBYTES # define UTF8_MAXBYTES UTF8_MAXLEN #endif #ifndef CPERLscope # define CPERLscope(x) x #endif #ifndef PERL_HASH # define PERL_HASH(hash,str,len) \ STMT_START { \ const char *s_PeRlHaSh = str; \ I32 i_PeRlHaSh = len; \ U32 hash_PeRlHaSh = 0; \ while (i_PeRlHaSh--) \ hash_PeRlHaSh = hash_PeRlHaSh * 33 + *s_PeRlHaSh++; \ (hash) = hash_PeRlHaSh; \ } STMT_END #endif #ifndef PERLIO_FUNCS_DECL # ifdef PERLIO_FUNCS_CONST # define PERLIO_FUNCS_DECL(funcs) const PerlIO_funcs funcs # define PERLIO_FUNCS_CAST(funcs) (PerlIO_funcs*)(funcs) # else # define PERLIO_FUNCS_DECL(funcs) PerlIO_funcs funcs # define PERLIO_FUNCS_CAST(funcs) (funcs) # endif #endif /* provide these typedefs for older perls */ #if (PERL_BCDVERSION < 0x5009003) # ifdef ARGSproto typedef OP* (CPERLscope(*Perl_ppaddr_t))(ARGSproto); # else typedef OP* (CPERLscope(*Perl_ppaddr_t))(pTHX); # endif typedef OP* (CPERLscope(*Perl_check_t)) (pTHX_ OP*); #endif #ifndef isPSXSPC # define isPSXSPC(c) (isSPACE(c) || (c) == '\v') #endif #ifndef isBLANK # define isBLANK(c) ((c) == ' ' || (c) == '\t') #endif #ifdef EBCDIC #ifndef isALNUMC # define isALNUMC(c) isalnum(c) #endif #ifndef isASCII # define isASCII(c) isascii(c) #endif #ifndef isCNTRL # define isCNTRL(c) iscntrl(c) #endif #ifndef isGRAPH # define isGRAPH(c) isgraph(c) #endif #ifndef isPRINT # define isPRINT(c) isprint(c) #endif #ifndef isPUNCT # define isPUNCT(c) ispunct(c) #endif #ifndef isXDIGIT # define isXDIGIT(c) isxdigit(c) #endif #else # if (PERL_BCDVERSION < 0x5010000) /* Hint: isPRINT * The implementation in older perl versions includes all of the * isSPACE() characters, which is wrong. The version provided by * Devel::PPPort always overrides a present buggy version. */ # undef isPRINT # endif #ifdef HAS_QUAD # ifdef U64TYPE # define WIDEST_UTYPE U64TYPE # else # define WIDEST_UTYPE Quad_t # endif #else # define WIDEST_UTYPE U32 #endif #ifndef isALNUMC # define isALNUMC(c) (isALPHA(c) || isDIGIT(c)) #endif #ifndef isASCII # define isASCII(c) ((WIDEST_UTYPE) (c) <= 127) #endif #ifndef isCNTRL # define isCNTRL(c) ((WIDEST_UTYPE) (c) < ' ' || (c) == 127) #endif #ifndef isGRAPH # define isGRAPH(c) (isALNUM(c) || isPUNCT(c)) #endif #ifndef isPRINT # define isPRINT(c) (((c) >= 32 && (c) < 127)) #endif #ifndef isPUNCT # define isPUNCT(c) (((c) >= 33 && (c) <= 47) || ((c) >= 58 && (c) <= 64) || ((c) >= 91 && (c) <= 96) || ((c) >= 123 && (c) <= 126)) #endif #ifndef isXDIGIT # define isXDIGIT(c) (isDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) #endif #endif /* Until we figure out how to support this in older perls... */ #if (PERL_BCDVERSION >= 0x5008000) #ifndef HeUTF8 # define HeUTF8(he) ((HeKLEN(he) == HEf_SVKEY) ? \ SvUTF8(HeKEY_sv(he)) : \ (U32)HeKUTF8(he)) #endif #endif #ifndef C_ARRAY_LENGTH # define C_ARRAY_LENGTH(a) (sizeof(a)/sizeof((a)[0])) #endif #ifndef C_ARRAY_END # define C_ARRAY_END(a) ((a) + C_ARRAY_LENGTH(a)) #endif #ifndef PERL_SIGNALS_UNSAFE_FLAG #define PERL_SIGNALS_UNSAFE_FLAG 0x0001 #if (PERL_BCDVERSION < 0x5008000) # define D_PPP_PERL_SIGNALS_INIT PERL_SIGNALS_UNSAFE_FLAG #else # define D_PPP_PERL_SIGNALS_INIT 0 #endif #if defined(NEED_PL_signals) static U32 DPPP_(my_PL_signals) = D_PPP_PERL_SIGNALS_INIT; #elif defined(NEED_PL_signals_GLOBAL) U32 DPPP_(my_PL_signals) = D_PPP_PERL_SIGNALS_INIT; #else extern U32 DPPP_(my_PL_signals); #endif #define PL_signals DPPP_(my_PL_signals) #endif /* Hint: PL_ppaddr * Calling an op via PL_ppaddr requires passing a context argument * for threaded builds. Since the context argument is different for * 5.005 perls, you can use aTHXR (supplied by ppport.h), which will * automatically be defined as the correct argument. */ #if (PERL_BCDVERSION <= 0x5005005) /* Replace: 1 */ # define PL_ppaddr ppaddr # define PL_no_modify no_modify /* Replace: 0 */ #endif #if (PERL_BCDVERSION <= 0x5004005) /* Replace: 1 */ # define PL_DBsignal DBsignal # define PL_DBsingle DBsingle # define PL_DBsub DBsub # define PL_DBtrace DBtrace # define PL_Sv Sv # define PL_bufend bufend # define PL_bufptr bufptr # define PL_compiling compiling # define PL_copline copline # define PL_curcop curcop # define PL_curstash curstash # define PL_debstash debstash # define PL_defgv defgv # define PL_diehook diehook # define PL_dirty dirty # define PL_dowarn dowarn # define PL_errgv errgv # define PL_error_count error_count # define PL_expect expect # define PL_hexdigit hexdigit # define PL_hints hints # define PL_in_my in_my # define PL_laststatval laststatval # define PL_lex_state lex_state # define PL_lex_stuff lex_stuff # define PL_linestr linestr # define PL_na na # define PL_perl_destruct_level perl_destruct_level # define PL_perldb perldb # define PL_rsfp_filters rsfp_filters # define PL_rsfp rsfp # define PL_stack_base stack_base # define PL_stack_sp stack_sp # define PL_statcache statcache # define PL_stdingv stdingv # define PL_sv_arenaroot sv_arenaroot # define PL_sv_no sv_no # define PL_sv_undef sv_undef # define PL_sv_yes sv_yes # define PL_tainted tainted # define PL_tainting tainting # define PL_tokenbuf tokenbuf /* Replace: 0 */ #endif /* Warning: PL_parser * For perl versions earlier than 5.9.5, this is an always * non-NULL dummy. Also, it cannot be dereferenced. Don't * use it if you can avoid is and unless you absolutely know * what you're doing. * If you always check that PL_parser is non-NULL, you can * define DPPP_PL_parser_NO_DUMMY to avoid the creation of * a dummy parser structure. */ #if (PERL_BCDVERSION >= 0x5009005) # ifdef DPPP_PL_parser_NO_DUMMY # define D_PPP_my_PL_parser_var(var) ((PL_parser ? PL_parser : \ (croak("panic: PL_parser == NULL in %s:%d", \ __FILE__, __LINE__), (yy_parser *) NULL))->var) # else # ifdef DPPP_PL_parser_NO_DUMMY_WARNING # define D_PPP_parser_dummy_warning(var) # else # define D_PPP_parser_dummy_warning(var) \ warn("warning: dummy PL_" #var " used in %s:%d", __FILE__, __LINE__), # endif # define D_PPP_my_PL_parser_var(var) ((PL_parser ? PL_parser : \ (D_PPP_parser_dummy_warning(var) &DPPP_(dummy_PL_parser)))->var) #if defined(NEED_PL_parser) static yy_parser DPPP_(dummy_PL_parser); #elif defined(NEED_PL_parser_GLOBAL) yy_parser DPPP_(dummy_PL_parser); #else extern yy_parser DPPP_(dummy_PL_parser); #endif # endif /* PL_expect, PL_copline, PL_rsfp, PL_rsfp_filters, PL_linestr, PL_bufptr, PL_bufend, PL_lex_state, PL_lex_stuff, PL_tokenbuf depends on PL_parser */ /* Warning: PL_expect, PL_copline, PL_rsfp, PL_rsfp_filters, PL_linestr, PL_bufptr, PL_bufend, PL_lex_state, PL_lex_stuff, PL_tokenbuf * Do not use this variable unless you know exactly what you're * doing. It is internal to the perl parser and may change or even * be removed in the future. As of perl 5.9.5, you have to check * for (PL_parser != NULL) for this variable to have any effect. * An always non-NULL PL_parser dummy is provided for earlier * perl versions. * If PL_parser is NULL when you try to access this variable, a * dummy is being accessed instead and a warning is issued unless * you define DPPP_PL_parser_NO_DUMMY_WARNING. * If DPPP_PL_parser_NO_DUMMY is defined, the code trying to access * this variable will croak with a panic message. */ # define PL_expect D_PPP_my_PL_parser_var(expect) # define PL_copline D_PPP_my_PL_parser_var(copline) # define PL_rsfp D_PPP_my_PL_parser_var(rsfp) # define PL_rsfp_filters D_PPP_my_PL_parser_var(rsfp_filters) # define PL_linestr D_PPP_my_PL_parser_var(linestr) # define PL_bufptr D_PPP_my_PL_parser_var(bufptr) # define PL_bufend D_PPP_my_PL_parser_var(bufend) # define PL_lex_state D_PPP_my_PL_parser_var(lex_state) # define PL_lex_stuff D_PPP_my_PL_parser_var(lex_stuff) # define PL_tokenbuf D_PPP_my_PL_parser_var(tokenbuf) # define PL_in_my D_PPP_my_PL_parser_var(in_my) # define PL_in_my_stash D_PPP_my_PL_parser_var(in_my_stash) # define PL_error_count D_PPP_my_PL_parser_var(error_count) #else /* ensure that PL_parser != NULL and cannot be dereferenced */ # define PL_parser ((void *) 1) #endif #ifndef mPUSHs # define mPUSHs(s) PUSHs(sv_2mortal(s)) #endif #ifndef PUSHmortal # define PUSHmortal PUSHs(sv_newmortal()) #endif #ifndef mPUSHp # define mPUSHp(p,l) sv_setpvn(PUSHmortal, (p), (l)) #endif #ifndef mPUSHn # define mPUSHn(n) sv_setnv(PUSHmortal, (NV)(n)) #endif #ifndef mPUSHi # define mPUSHi(i) sv_setiv(PUSHmortal, (IV)(i)) #endif #ifndef mPUSHu # define mPUSHu(u) sv_setuv(PUSHmortal, (UV)(u)) #endif #ifndef mXPUSHs # define mXPUSHs(s) XPUSHs(sv_2mortal(s)) #endif #ifndef XPUSHmortal # define XPUSHmortal XPUSHs(sv_newmortal()) #endif #ifndef mXPUSHp # define mXPUSHp(p,l) STMT_START { EXTEND(sp,1); sv_setpvn(PUSHmortal, (p), (l)); } STMT_END #endif #ifndef mXPUSHn # define mXPUSHn(n) STMT_START { EXTEND(sp,1); sv_setnv(PUSHmortal, (NV)(n)); } STMT_END #endif #ifndef mXPUSHi # define mXPUSHi(i) STMT_START { EXTEND(sp,1); sv_setiv(PUSHmortal, (IV)(i)); } STMT_END #endif #ifndef mXPUSHu # define mXPUSHu(u) STMT_START { EXTEND(sp,1); sv_setuv(PUSHmortal, (UV)(u)); } STMT_END #endif /* Replace: 1 */ #ifndef call_sv # define call_sv perl_call_sv #endif #ifndef call_pv # define call_pv perl_call_pv #endif #ifndef call_argv # define call_argv perl_call_argv #endif #ifndef call_method # define call_method perl_call_method #endif #ifndef eval_sv # define eval_sv perl_eval_sv #endif /* Replace: 0 */ #ifndef PERL_LOADMOD_DENY # define PERL_LOADMOD_DENY 0x1 #endif #ifndef PERL_LOADMOD_NOIMPORT # define PERL_LOADMOD_NOIMPORT 0x2 #endif #ifndef PERL_LOADMOD_IMPORT_OPS # define PERL_LOADMOD_IMPORT_OPS 0x4 #endif #ifndef G_METHOD # define G_METHOD 64 # ifdef call_sv # undef call_sv # endif # if (PERL_BCDVERSION < 0x5006000) # define call_sv(sv, flags) ((flags) & G_METHOD ? perl_call_method((char *) SvPV_nolen_const(sv), \ (flags) & ~G_METHOD) : perl_call_sv(sv, flags)) # else # define call_sv(sv, flags) ((flags) & G_METHOD ? Perl_call_method(aTHX_ (char *) SvPV_nolen_const(sv), \ (flags) & ~G_METHOD) : Perl_call_sv(aTHX_ sv, flags)) # endif #endif /* Replace perl_eval_pv with eval_pv */ #ifndef eval_pv #if defined(NEED_eval_pv) static SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error); static #else extern SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error); #endif #ifdef eval_pv # undef eval_pv #endif #define eval_pv(a,b) DPPP_(my_eval_pv)(aTHX_ a,b) #define Perl_eval_pv DPPP_(my_eval_pv) #if defined(NEED_eval_pv) || defined(NEED_eval_pv_GLOBAL) SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error) { dSP; SV* sv = newSVpv(p, 0); PUSHMARK(sp); eval_sv(sv, G_SCALAR); SvREFCNT_dec(sv); SPAGAIN; sv = POPs; PUTBACK; if (croak_on_error && SvTRUE(GvSV(errgv))) croak(SvPVx(GvSV(errgv), na)); return sv; } #endif #endif #ifndef vload_module #if defined(NEED_vload_module) static void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args); static #else extern void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args); #endif #ifdef vload_module # undef vload_module #endif #define vload_module(a,b,c,d) DPPP_(my_vload_module)(aTHX_ a,b,c,d) #define Perl_vload_module DPPP_(my_vload_module) #if defined(NEED_vload_module) || defined(NEED_vload_module_GLOBAL) void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args) { dTHR; dVAR; OP *veop, *imop; OP * const modname = newSVOP(OP_CONST, 0, name); /* 5.005 has a somewhat hacky force_normal that doesn't croak on SvREADONLY() if PL_compling is true. Current perls take care in ck_require() to correctly turn off SvREADONLY before calling force_normal_flags(). This seems a better fix than fudging PL_compling */ SvREADONLY_off(((SVOP*)modname)->op_sv); modname->op_private |= OPpCONST_BARE; if (ver) { veop = newSVOP(OP_CONST, 0, ver); } else veop = NULL; if (flags & PERL_LOADMOD_NOIMPORT) { imop = sawparens(newNULLLIST()); } else if (flags & PERL_LOADMOD_IMPORT_OPS) { imop = va_arg(*args, OP*); } else { SV *sv; imop = NULL; sv = va_arg(*args, SV*); while (sv) { imop = append_elem(OP_LIST, imop, newSVOP(OP_CONST, 0, sv)); sv = va_arg(*args, SV*); } } { const line_t ocopline = PL_copline; COP * const ocurcop = PL_curcop; const int oexpect = PL_expect; #if (PERL_BCDVERSION >= 0x5004000) utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0), veop, modname, imop); #elif (PERL_BCDVERSION > 0x5003000) utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(), veop, modname, imop); #else utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(), modname, imop); #endif PL_expect = oexpect; PL_copline = ocopline; PL_curcop = ocurcop; } } #endif #endif #ifndef load_module #if defined(NEED_load_module) static void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...); static #else extern void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...); #endif #ifdef load_module # undef load_module #endif #define load_module DPPP_(my_load_module) #define Perl_load_module DPPP_(my_load_module) #if defined(NEED_load_module) || defined(NEED_load_module_GLOBAL) void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...) { va_list args; va_start(args, ver); vload_module(flags, name, ver, &args); va_end(args); } #endif #endif #ifndef newRV_inc # define newRV_inc(sv) newRV(sv) /* Replace */ #endif #ifndef newRV_noinc #if defined(NEED_newRV_noinc) static SV * DPPP_(my_newRV_noinc)(SV *sv); static #else extern SV * DPPP_(my_newRV_noinc)(SV *sv); #endif #ifdef newRV_noinc # undef newRV_noinc #endif #define newRV_noinc(a) DPPP_(my_newRV_noinc)(aTHX_ a) #define Perl_newRV_noinc DPPP_(my_newRV_noinc) #if defined(NEED_newRV_noinc) || defined(NEED_newRV_noinc_GLOBAL) SV * DPPP_(my_newRV_noinc)(SV *sv) { SV *rv = (SV *)newRV(sv); SvREFCNT_dec(sv); return rv; } #endif #endif /* Hint: newCONSTSUB * Returns a CV* as of perl-5.7.1. This return value is not supported * by Devel::PPPort. */ /* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */ #if (PERL_BCDVERSION < 0x5004063) && (PERL_BCDVERSION != 0x5004005) #if defined(NEED_newCONSTSUB) static void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv); static #else extern void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv); #endif #ifdef newCONSTSUB # undef newCONSTSUB #endif #define newCONSTSUB(a,b,c) DPPP_(my_newCONSTSUB)(aTHX_ a,b,c) #define Perl_newCONSTSUB DPPP_(my_newCONSTSUB) #if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL) /* This is just a trick to avoid a dependency of newCONSTSUB on PL_parser */ /* (There's no PL_parser in perl < 5.005, so this is completely safe) */ #define D_PPP_PL_copline PL_copline void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv) { U32 oldhints = PL_hints; HV *old_cop_stash = PL_curcop->cop_stash; HV *old_curstash = PL_curstash; line_t oldline = PL_curcop->cop_line; PL_curcop->cop_line = D_PPP_PL_copline; PL_hints &= ~HINT_BLOCK_SCOPE; if (stash) PL_curstash = PL_curcop->cop_stash = stash; newSUB( #if (PERL_BCDVERSION < 0x5003022) start_subparse(), #elif (PERL_BCDVERSION == 0x5003022) start_subparse(0), #else /* 5.003_23 onwards */ start_subparse(FALSE, 0), #endif newSVOP(OP_CONST, 0, newSVpv((char *) name, 0)), newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */ newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv)) ); PL_hints = oldhints; PL_curcop->cop_stash = old_cop_stash; PL_curstash = old_curstash; PL_curcop->cop_line = oldline; } #endif #endif /* * Boilerplate macros for initializing and accessing interpreter-local * data from C. All statics in extensions should be reworked to use * this, if you want to make the extension thread-safe. See ext/re/re.xs * for an example of the use of these macros. * * Code that uses these macros is responsible for the following: * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts" * 2. Declare a typedef named my_cxt_t that is a structure that contains * all the data that needs to be interpreter-local. * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t. * 4. Use the MY_CXT_INIT macro such that it is called exactly once * (typically put in the BOOT: section). * 5. Use the members of the my_cxt_t structure everywhere as * MY_CXT.member. * 6. Use the dMY_CXT macro (a declaration) in all the functions that * access MY_CXT. */ #if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \ defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT) #ifndef START_MY_CXT /* This must appear in all extensions that define a my_cxt_t structure, * right after the definition (i.e. at file scope). The non-threads * case below uses it to declare the data as static. */ #define START_MY_CXT #if (PERL_BCDVERSION < 0x5004068) /* Fetches the SV that keeps the per-interpreter data. */ #define dMY_CXT_SV \ SV *my_cxt_sv = get_sv(MY_CXT_KEY, FALSE) #else /* >= perl5.004_68 */ #define dMY_CXT_SV \ SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \ sizeof(MY_CXT_KEY)-1, TRUE) #endif /* < perl5.004_68 */ /* This declaration should be used within all functions that use the * interpreter-local data. */ #define dMY_CXT \ dMY_CXT_SV; \ my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv)) /* Creates and zeroes the per-interpreter data. * (We allocate my_cxtp in a Perl SV so that it will be released when * the interpreter goes away.) */ #define MY_CXT_INIT \ dMY_CXT_SV; \ /* newSV() allocates one more than needed */ \ my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ Zero(my_cxtp, 1, my_cxt_t); \ sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) /* This macro must be used to access members of the my_cxt_t structure. * e.g. MYCXT.some_data */ #define MY_CXT (*my_cxtp) /* Judicious use of these macros can reduce the number of times dMY_CXT * is used. Use is similar to pTHX, aTHX etc. */ #define pMY_CXT my_cxt_t *my_cxtp #define pMY_CXT_ pMY_CXT, #define _pMY_CXT ,pMY_CXT #define aMY_CXT my_cxtp #define aMY_CXT_ aMY_CXT, #define _aMY_CXT ,aMY_CXT #endif /* START_MY_CXT */ #ifndef MY_CXT_CLONE /* Clones the per-interpreter data. */ #define MY_CXT_CLONE \ dMY_CXT_SV; \ my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t);\ sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) #endif #else /* single interpreter */ #ifndef START_MY_CXT #define START_MY_CXT static my_cxt_t my_cxt; #define dMY_CXT_SV dNOOP #define dMY_CXT dNOOP #define MY_CXT_INIT NOOP #define MY_CXT my_cxt #define pMY_CXT void #define pMY_CXT_ #define _pMY_CXT #define aMY_CXT #define aMY_CXT_ #define _aMY_CXT #endif /* START_MY_CXT */ #ifndef MY_CXT_CLONE #define MY_CXT_CLONE NOOP #endif #endif #ifndef IVdf # if IVSIZE == LONGSIZE # define IVdf "ld" # define UVuf "lu" # define UVof "lo" # define UVxf "lx" # define UVXf "lX" # elif IVSIZE == INTSIZE # define IVdf "d" # define UVuf "u" # define UVof "o" # define UVxf "x" # define UVXf "X" # else # error "cannot define IV/UV formats" # endif #endif #ifndef NVef # if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \ defined(PERL_PRIfldbl) && (PERL_BCDVERSION != 0x5006000) /* Not very likely, but let's try anyway. */ # define NVef PERL_PRIeldbl # define NVff PERL_PRIfldbl # define NVgf PERL_PRIgldbl # else # define NVef "e" # define NVff "f" # define NVgf "g" # endif #endif #ifndef SvREFCNT_inc # ifdef PERL_USE_GCC_BRACE_GROUPS # define SvREFCNT_inc(sv) \ ({ \ SV * const _sv = (SV*)(sv); \ if (_sv) \ (SvREFCNT(_sv))++; \ _sv; \ }) # else # define SvREFCNT_inc(sv) \ ((PL_Sv=(SV*)(sv)) ? (++(SvREFCNT(PL_Sv)),PL_Sv) : NULL) # endif #endif #ifndef SvREFCNT_inc_simple # ifdef PERL_USE_GCC_BRACE_GROUPS # define SvREFCNT_inc_simple(sv) \ ({ \ if (sv) \ (SvREFCNT(sv))++; \ (SV *)(sv); \ }) # else # define SvREFCNT_inc_simple(sv) \ ((sv) ? (SvREFCNT(sv)++,(SV*)(sv)) : NULL) # endif #endif #ifndef SvREFCNT_inc_NN # ifdef PERL_USE_GCC_BRACE_GROUPS # define SvREFCNT_inc_NN(sv) \ ({ \ SV * const _sv = (SV*)(sv); \ SvREFCNT(_sv)++; \ _sv; \ }) # else # define SvREFCNT_inc_NN(sv) \ (PL_Sv=(SV*)(sv),++(SvREFCNT(PL_Sv)),PL_Sv) # endif #endif #ifndef SvREFCNT_inc_void # ifdef PERL_USE_GCC_BRACE_GROUPS # define SvREFCNT_inc_void(sv) \ ({ \ SV * const _sv = (SV*)(sv); \ if (_sv) \ (void)(SvREFCNT(_sv)++); \ }) # else # define SvREFCNT_inc_void(sv) \ (void)((PL_Sv=(SV*)(sv)) ? ++(SvREFCNT(PL_Sv)) : 0) # endif #endif #ifndef SvREFCNT_inc_simple_void # define SvREFCNT_inc_simple_void(sv) STMT_START { if (sv) SvREFCNT(sv)++; } STMT_END #endif #ifndef SvREFCNT_inc_simple_NN # define SvREFCNT_inc_simple_NN(sv) (++SvREFCNT(sv), (SV*)(sv)) #endif #ifndef SvREFCNT_inc_void_NN # define SvREFCNT_inc_void_NN(sv) (void)(++SvREFCNT((SV*)(sv))) #endif #ifndef SvREFCNT_inc_simple_void_NN # define SvREFCNT_inc_simple_void_NN(sv) (void)(++SvREFCNT((SV*)(sv))) #endif #ifndef newSV_type #if defined(NEED_newSV_type) static SV* DPPP_(my_newSV_type)(pTHX_ svtype const t); static #else extern SV* DPPP_(my_newSV_type)(pTHX_ svtype const t); #endif #ifdef newSV_type # undef newSV_type #endif #define newSV_type(a) DPPP_(my_newSV_type)(aTHX_ a) #define Perl_newSV_type DPPP_(my_newSV_type) #if defined(NEED_newSV_type) || defined(NEED_newSV_type_GLOBAL) SV* DPPP_(my_newSV_type)(pTHX_ svtype const t) { SV* const sv = newSV(0); sv_upgrade(sv, t); return sv; } #endif #endif #if (PERL_BCDVERSION < 0x5006000) # define D_PPP_CONSTPV_ARG(x) ((char *) (x)) #else # define D_PPP_CONSTPV_ARG(x) (x) #endif #ifndef newSVpvn # define newSVpvn(data,len) ((data) \ ? ((len) ? newSVpv((data), (len)) : newSVpv("", 0)) \ : newSV(0)) #endif #ifndef newSVpvn_utf8 # define newSVpvn_utf8(s, len, u) newSVpvn_flags((s), (len), (u) ? SVf_UTF8 : 0) #endif #ifndef SVf_UTF8 # define SVf_UTF8 0 #endif #ifndef newSVpvn_flags #if defined(NEED_newSVpvn_flags) static SV * DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags); static #else extern SV * DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags); #endif #ifdef newSVpvn_flags # undef newSVpvn_flags #endif #define newSVpvn_flags(a,b,c) DPPP_(my_newSVpvn_flags)(aTHX_ a,b,c) #define Perl_newSVpvn_flags DPPP_(my_newSVpvn_flags) #if defined(NEED_newSVpvn_flags) || defined(NEED_newSVpvn_flags_GLOBAL) SV * DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags) { SV *sv = newSVpvn(D_PPP_CONSTPV_ARG(s), len); SvFLAGS(sv) |= (flags & SVf_UTF8); return (flags & SVs_TEMP) ? sv_2mortal(sv) : sv; } #endif #endif /* Backwards compatibility stuff... :-( */ #if !defined(NEED_sv_2pv_flags) && defined(NEED_sv_2pv_nolen) # define NEED_sv_2pv_flags #endif #if !defined(NEED_sv_2pv_flags_GLOBAL) && defined(NEED_sv_2pv_nolen_GLOBAL) # define NEED_sv_2pv_flags_GLOBAL #endif /* Hint: sv_2pv_nolen * Use the SvPV_nolen() or SvPV_nolen_const() macros instead of sv_2pv_nolen(). */ #ifndef sv_2pv_nolen # define sv_2pv_nolen(sv) SvPV_nolen(sv) #endif #ifdef SvPVbyte /* Hint: SvPVbyte * Does not work in perl-5.6.1, ppport.h implements a version * borrowed from perl-5.7.3. */ #if (PERL_BCDVERSION < 0x5007000) #if defined(NEED_sv_2pvbyte) static char * DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp); static #else extern char * DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp); #endif #ifdef sv_2pvbyte # undef sv_2pvbyte #endif #define sv_2pvbyte(a,b) DPPP_(my_sv_2pvbyte)(aTHX_ a,b) #define Perl_sv_2pvbyte DPPP_(my_sv_2pvbyte) #if defined(NEED_sv_2pvbyte) || defined(NEED_sv_2pvbyte_GLOBAL) char * DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp) { sv_utf8_downgrade(sv,0); return SvPV(sv,*lp); } #endif /* Hint: sv_2pvbyte * Use the SvPVbyte() macro instead of sv_2pvbyte(). */ #undef SvPVbyte #define SvPVbyte(sv, lp) \ ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \ ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pvbyte(sv, &lp)) #endif #else # define SvPVbyte SvPV # define sv_2pvbyte sv_2pv #endif #ifndef sv_2pvbyte_nolen # define sv_2pvbyte_nolen(sv) sv_2pv_nolen(sv) #endif /* Hint: sv_pvn * Always use the SvPV() macro instead of sv_pvn(). */ /* Hint: sv_pvn_force * Always use the SvPV_force() macro instead of sv_pvn_force(). */ /* If these are undefined, they're not handled by the core anyway */ #ifndef SV_IMMEDIATE_UNREF # define SV_IMMEDIATE_UNREF 0 #endif #ifndef SV_GMAGIC # define SV_GMAGIC 0 #endif #ifndef SV_COW_DROP_PV # define SV_COW_DROP_PV 0 #endif #ifndef SV_UTF8_NO_ENCODING # define SV_UTF8_NO_ENCODING 0 #endif #ifndef SV_NOSTEAL # define SV_NOSTEAL 0 #endif #ifndef SV_CONST_RETURN # define SV_CONST_RETURN 0 #endif #ifndef SV_MUTABLE_RETURN # define SV_MUTABLE_RETURN 0 #endif #ifndef SV_SMAGIC # define SV_SMAGIC 0 #endif #ifndef SV_HAS_TRAILING_NUL # define SV_HAS_TRAILING_NUL 0 #endif #ifndef SV_COW_SHARED_HASH_KEYS # define SV_COW_SHARED_HASH_KEYS 0 #endif #if (PERL_BCDVERSION < 0x5007002) #if defined(NEED_sv_2pv_flags) static char * DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); static #else extern char * DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); #endif #ifdef sv_2pv_flags # undef sv_2pv_flags #endif #define sv_2pv_flags(a,b,c) DPPP_(my_sv_2pv_flags)(aTHX_ a,b,c) #define Perl_sv_2pv_flags DPPP_(my_sv_2pv_flags) #if defined(NEED_sv_2pv_flags) || defined(NEED_sv_2pv_flags_GLOBAL) char * DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags) { STRLEN n_a = (STRLEN) flags; return sv_2pv(sv, lp ? lp : &n_a); } #endif #if defined(NEED_sv_pvn_force_flags) static char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); static #else extern char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); #endif #ifdef sv_pvn_force_flags # undef sv_pvn_force_flags #endif #define sv_pvn_force_flags(a,b,c) DPPP_(my_sv_pvn_force_flags)(aTHX_ a,b,c) #define Perl_sv_pvn_force_flags DPPP_(my_sv_pvn_force_flags) #if defined(NEED_sv_pvn_force_flags) || defined(NEED_sv_pvn_force_flags_GLOBAL) char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags) { STRLEN n_a = (STRLEN) flags; return sv_pvn_force(sv, lp ? lp : &n_a); } #endif #endif #if (PERL_BCDVERSION < 0x5008008) || ( (PERL_BCDVERSION >= 0x5009000) && (PERL_BCDVERSION < 0x5009003) ) # define DPPP_SVPV_NOLEN_LP_ARG &PL_na #else # define DPPP_SVPV_NOLEN_LP_ARG 0 #endif #ifndef SvPV_const # define SvPV_const(sv, lp) SvPV_flags_const(sv, lp, SV_GMAGIC) #endif #ifndef SvPV_mutable # define SvPV_mutable(sv, lp) SvPV_flags_mutable(sv, lp, SV_GMAGIC) #endif #ifndef SvPV_flags # define SvPV_flags(sv, lp, flags) \ ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pv_flags(sv, &lp, flags)) #endif #ifndef SvPV_flags_const # define SvPV_flags_const(sv, lp, flags) \ ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ ? ((lp = SvCUR(sv)), SvPVX_const(sv)) : \ (const char*) sv_2pv_flags(sv, &lp, flags|SV_CONST_RETURN)) #endif #ifndef SvPV_flags_const_nolen # define SvPV_flags_const_nolen(sv, flags) \ ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ ? SvPVX_const(sv) : \ (const char*) sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, flags|SV_CONST_RETURN)) #endif #ifndef SvPV_flags_mutable # define SvPV_flags_mutable(sv, lp, flags) \ ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) : \ sv_2pv_flags(sv, &lp, flags|SV_MUTABLE_RETURN)) #endif #ifndef SvPV_force # define SvPV_force(sv, lp) SvPV_force_flags(sv, lp, SV_GMAGIC) #endif #ifndef SvPV_force_nolen # define SvPV_force_nolen(sv) SvPV_force_flags_nolen(sv, SV_GMAGIC) #endif #ifndef SvPV_force_mutable # define SvPV_force_mutable(sv, lp) SvPV_force_flags_mutable(sv, lp, SV_GMAGIC) #endif #ifndef SvPV_force_nomg # define SvPV_force_nomg(sv, lp) SvPV_force_flags(sv, lp, 0) #endif #ifndef SvPV_force_nomg_nolen # define SvPV_force_nomg_nolen(sv) SvPV_force_flags_nolen(sv, 0) #endif #ifndef SvPV_force_flags # define SvPV_force_flags(sv, lp, flags) \ ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_pvn_force_flags(sv, &lp, flags)) #endif #ifndef SvPV_force_flags_nolen # define SvPV_force_flags_nolen(sv, flags) \ ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ ? SvPVX(sv) : sv_pvn_force_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, flags)) #endif #ifndef SvPV_force_flags_mutable # define SvPV_force_flags_mutable(sv, lp, flags) \ ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) \ : sv_pvn_force_flags(sv, &lp, flags|SV_MUTABLE_RETURN)) #endif #ifndef SvPV_nolen # define SvPV_nolen(sv) \ ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ ? SvPVX(sv) : sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, SV_GMAGIC)) #endif #ifndef SvPV_nolen_const # define SvPV_nolen_const(sv) \ ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ ? SvPVX_const(sv) : sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, SV_GMAGIC|SV_CONST_RETURN)) #endif #ifndef SvPV_nomg # define SvPV_nomg(sv, lp) SvPV_flags(sv, lp, 0) #endif #ifndef SvPV_nomg_const # define SvPV_nomg_const(sv, lp) SvPV_flags_const(sv, lp, 0) #endif #ifndef SvPV_nomg_const_nolen # define SvPV_nomg_const_nolen(sv) SvPV_flags_const_nolen(sv, 0) #endif #ifndef SvPV_nomg_nolen # define SvPV_nomg_nolen(sv) ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ ? SvPVX(sv) : sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, 0)) #endif #ifndef SvPV_renew # define SvPV_renew(sv,n) STMT_START { SvLEN_set(sv, n); \ SvPV_set((sv), (char *) saferealloc( \ (Malloc_t)SvPVX(sv), (MEM_SIZE)((n)))); \ } STMT_END #endif #ifndef SvMAGIC_set # define SvMAGIC_set(sv, val) \ STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \ (((XPVMG*) SvANY(sv))->xmg_magic = (val)); } STMT_END #endif #if (PERL_BCDVERSION < 0x5009003) #ifndef SvPVX_const # define SvPVX_const(sv) ((const char*) (0 + SvPVX(sv))) #endif #ifndef SvPVX_mutable # define SvPVX_mutable(sv) (0 + SvPVX(sv)) #endif #ifndef SvRV_set # define SvRV_set(sv, val) \ STMT_START { assert(SvTYPE(sv) >= SVt_RV); \ (((XRV*) SvANY(sv))->xrv_rv = (val)); } STMT_END #endif #else #ifndef SvPVX_const # define SvPVX_const(sv) ((const char*)((sv)->sv_u.svu_pv)) #endif #ifndef SvPVX_mutable # define SvPVX_mutable(sv) ((sv)->sv_u.svu_pv) #endif #ifndef SvRV_set # define SvRV_set(sv, val) \ STMT_START { assert(SvTYPE(sv) >= SVt_RV); \ ((sv)->sv_u.svu_rv = (val)); } STMT_END #endif #endif #ifndef SvSTASH_set # define SvSTASH_set(sv, val) \ STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \ (((XPVMG*) SvANY(sv))->xmg_stash = (val)); } STMT_END #endif #if (PERL_BCDVERSION < 0x5004000) #ifndef SvUV_set # define SvUV_set(sv, val) \ STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \ (((XPVIV*) SvANY(sv))->xiv_iv = (IV) (val)); } STMT_END #endif #else #ifndef SvUV_set # define SvUV_set(sv, val) \ STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \ (((XPVUV*) SvANY(sv))->xuv_uv = (val)); } STMT_END #endif #endif #if (PERL_BCDVERSION >= 0x5004000) && !defined(vnewSVpvf) #if defined(NEED_vnewSVpvf) static SV * DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args); static #else extern SV * DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args); #endif #ifdef vnewSVpvf # undef vnewSVpvf #endif #define vnewSVpvf(a,b) DPPP_(my_vnewSVpvf)(aTHX_ a,b) #define Perl_vnewSVpvf DPPP_(my_vnewSVpvf) #if defined(NEED_vnewSVpvf) || defined(NEED_vnewSVpvf_GLOBAL) SV * DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args) { register SV *sv = newSV(0); sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); return sv; } #endif #endif #if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf) # define sv_vcatpvf(sv, pat, args) sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)) #endif #if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf) # define sv_vsetpvf(sv, pat, args) sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)) #endif #if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_catpvf_mg) #if defined(NEED_sv_catpvf_mg) static void DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...); static #else extern void DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...); #endif #define Perl_sv_catpvf_mg DPPP_(my_sv_catpvf_mg) #if defined(NEED_sv_catpvf_mg) || defined(NEED_sv_catpvf_mg_GLOBAL) void DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...) { va_list args; va_start(args, pat); sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); SvSETMAGIC(sv); va_end(args); } #endif #endif #ifdef PERL_IMPLICIT_CONTEXT #if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_catpvf_mg_nocontext) #if defined(NEED_sv_catpvf_mg_nocontext) static void DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...); static #else extern void DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...); #endif #define sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext) #define Perl_sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext) #if defined(NEED_sv_catpvf_mg_nocontext) || defined(NEED_sv_catpvf_mg_nocontext_GLOBAL) void DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...) { dTHX; va_list args; va_start(args, pat); sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); SvSETMAGIC(sv); va_end(args); } #endif #endif #endif /* sv_catpvf_mg depends on sv_catpvf_mg_nocontext */ #ifndef sv_catpvf_mg # ifdef PERL_IMPLICIT_CONTEXT # define sv_catpvf_mg Perl_sv_catpvf_mg_nocontext # else # define sv_catpvf_mg Perl_sv_catpvf_mg # endif #endif #if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf_mg) # define sv_vcatpvf_mg(sv, pat, args) \ STMT_START { \ sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); \ SvSETMAGIC(sv); \ } STMT_END #endif #if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg) #if defined(NEED_sv_setpvf_mg) static void DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...); static #else extern void DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...); #endif #define Perl_sv_setpvf_mg DPPP_(my_sv_setpvf_mg) #if defined(NEED_sv_setpvf_mg) || defined(NEED_sv_setpvf_mg_GLOBAL) void DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...) { va_list args; va_start(args, pat); sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); SvSETMAGIC(sv); va_end(args); } #endif #endif #ifdef PERL_IMPLICIT_CONTEXT #if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg_nocontext) #if defined(NEED_sv_setpvf_mg_nocontext) static void DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...); static #else extern void DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...); #endif #define sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext) #define Perl_sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext) #if defined(NEED_sv_setpvf_mg_nocontext) || defined(NEED_sv_setpvf_mg_nocontext_GLOBAL) void DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...) { dTHX; va_list args; va_start(args, pat); sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); SvSETMAGIC(sv); va_end(args); } #endif #endif #endif /* sv_setpvf_mg depends on sv_setpvf_mg_nocontext */ #ifndef sv_setpvf_mg # ifdef PERL_IMPLICIT_CONTEXT # define sv_setpvf_mg Perl_sv_setpvf_mg_nocontext # else # define sv_setpvf_mg Perl_sv_setpvf_mg # endif #endif #if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf_mg) # define sv_vsetpvf_mg(sv, pat, args) \ STMT_START { \ sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); \ SvSETMAGIC(sv); \ } STMT_END #endif /* Hint: newSVpvn_share * The SVs created by this function only mimic the behaviour of * shared PVs without really being shared. Only use if you know * what you're doing. */ #ifndef newSVpvn_share #if defined(NEED_newSVpvn_share) static SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash); static #else extern SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash); #endif #ifdef newSVpvn_share # undef newSVpvn_share #endif #define newSVpvn_share(a,b,c) DPPP_(my_newSVpvn_share)(aTHX_ a,b,c) #define Perl_newSVpvn_share DPPP_(my_newSVpvn_share) #if defined(NEED_newSVpvn_share) || defined(NEED_newSVpvn_share_GLOBAL) SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash) { SV *sv; if (len < 0) len = -len; if (!hash) PERL_HASH(hash, (char*) src, len); sv = newSVpvn((char *) src, len); sv_upgrade(sv, SVt_PVIV); SvIVX(sv) = hash; SvREADONLY_on(sv); SvPOK_on(sv); return sv; } #endif #endif #ifndef SvSHARED_HASH # define SvSHARED_HASH(sv) (0 + SvUVX(sv)) #endif #ifndef HvNAME_get # define HvNAME_get(hv) HvNAME(hv) #endif #ifndef HvNAMELEN_get # define HvNAMELEN_get(hv) (HvNAME_get(hv) ? (I32)strlen(HvNAME_get(hv)) : 0) #endif #ifndef gv_fetchpvn_flags #if defined(NEED_gv_fetchpvn_flags) static GV* DPPP_(my_gv_fetchpvn_flags)(pTHX_ const char* name, STRLEN len, int flags, int types); static #else extern GV* DPPP_(my_gv_fetchpvn_flags)(pTHX_ const char* name, STRLEN len, int flags, int types); #endif #ifdef gv_fetchpvn_flags # undef gv_fetchpvn_flags #endif #define gv_fetchpvn_flags(a,b,c,d) DPPP_(my_gv_fetchpvn_flags)(aTHX_ a,b,c,d) #define Perl_gv_fetchpvn_flags DPPP_(my_gv_fetchpvn_flags) #if defined(NEED_gv_fetchpvn_flags) || defined(NEED_gv_fetchpvn_flags_GLOBAL) GV* DPPP_(my_gv_fetchpvn_flags)(pTHX_ const char* name, STRLEN len, int flags, int types) { char *namepv = savepvn(name, len); GV* stash = gv_fetchpv(namepv, TRUE, SVt_PVHV); Safefree(namepv); return stash; } #endif #endif #ifndef GvSVn # define GvSVn(gv) GvSV(gv) #endif #ifndef isGV_with_GP # define isGV_with_GP(gv) isGV(gv) #endif #ifndef gv_fetchsv # define gv_fetchsv(name, flags, svt) gv_fetchpv(SvPV_nolen_const(name), flags, svt) #endif #ifndef get_cvn_flags # define get_cvn_flags(name, namelen, flags) get_cv(name, flags) #endif #ifndef gv_init_pvn # define gv_init_pvn(gv, stash, ptr, len, flags) gv_init(gv, stash, ptr, len, flags & GV_ADDMULTI ? TRUE : FALSE) #endif #ifndef WARN_ALL # define WARN_ALL 0 #endif #ifndef WARN_CLOSURE # define WARN_CLOSURE 1 #endif #ifndef WARN_DEPRECATED # define WARN_DEPRECATED 2 #endif #ifndef WARN_EXITING # define WARN_EXITING 3 #endif #ifndef WARN_GLOB # define WARN_GLOB 4 #endif #ifndef WARN_IO # define WARN_IO 5 #endif #ifndef WARN_CLOSED # define WARN_CLOSED 6 #endif #ifndef WARN_EXEC # define WARN_EXEC 7 #endif #ifndef WARN_LAYER # define WARN_LAYER 8 #endif #ifndef WARN_NEWLINE # define WARN_NEWLINE 9 #endif #ifndef WARN_PIPE # define WARN_PIPE 10 #endif #ifndef WARN_UNOPENED # define WARN_UNOPENED 11 #endif #ifndef WARN_MISC # define WARN_MISC 12 #endif #ifndef WARN_NUMERIC # define WARN_NUMERIC 13 #endif #ifndef WARN_ONCE # define WARN_ONCE 14 #endif #ifndef WARN_OVERFLOW # define WARN_OVERFLOW 15 #endif #ifndef WARN_PACK # define WARN_PACK 16 #endif #ifndef WARN_PORTABLE # define WARN_PORTABLE 17 #endif #ifndef WARN_RECURSION # define WARN_RECURSION 18 #endif #ifndef WARN_REDEFINE # define WARN_REDEFINE 19 #endif #ifndef WARN_REGEXP # define WARN_REGEXP 20 #endif #ifndef WARN_SEVERE # define WARN_SEVERE 21 #endif #ifndef WARN_DEBUGGING # define WARN_DEBUGGING 22 #endif #ifndef WARN_INPLACE # define WARN_INPLACE 23 #endif #ifndef WARN_INTERNAL # define WARN_INTERNAL 24 #endif #ifndef WARN_MALLOC # define WARN_MALLOC 25 #endif #ifndef WARN_SIGNAL # define WARN_SIGNAL 26 #endif #ifndef WARN_SUBSTR # define WARN_SUBSTR 27 #endif #ifndef WARN_SYNTAX # define WARN_SYNTAX 28 #endif #ifndef WARN_AMBIGUOUS # define WARN_AMBIGUOUS 29 #endif #ifndef WARN_BAREWORD # define WARN_BAREWORD 30 #endif #ifndef WARN_DIGIT # define WARN_DIGIT 31 #endif #ifndef WARN_PARENTHESIS # define WARN_PARENTHESIS 32 #endif #ifndef WARN_PRECEDENCE # define WARN_PRECEDENCE 33 #endif #ifndef WARN_PRINTF # define WARN_PRINTF 34 #endif #ifndef WARN_PROTOTYPE # define WARN_PROTOTYPE 35 #endif #ifndef WARN_QW # define WARN_QW 36 #endif #ifndef WARN_RESERVED # define WARN_RESERVED 37 #endif #ifndef WARN_SEMICOLON # define WARN_SEMICOLON 38 #endif #ifndef WARN_TAINT # define WARN_TAINT 39 #endif #ifndef WARN_THREADS # define WARN_THREADS 40 #endif #ifndef WARN_UNINITIALIZED # define WARN_UNINITIALIZED 41 #endif #ifndef WARN_UNPACK # define WARN_UNPACK 42 #endif #ifndef WARN_UNTIE # define WARN_UNTIE 43 #endif #ifndef WARN_UTF8 # define WARN_UTF8 44 #endif #ifndef WARN_VOID # define WARN_VOID 45 #endif #ifndef WARN_ASSERTIONS # define WARN_ASSERTIONS 46 #endif #ifndef packWARN # define packWARN(a) (a) #endif #ifndef ckWARN # ifdef G_WARN_ON # define ckWARN(a) (PL_dowarn & G_WARN_ON) # else # define ckWARN(a) PL_dowarn # endif #endif #if (PERL_BCDVERSION >= 0x5004000) && !defined(warner) #if defined(NEED_warner) static void DPPP_(my_warner)(U32 err, const char *pat, ...); static #else extern void DPPP_(my_warner)(U32 err, const char *pat, ...); #endif #define Perl_warner DPPP_(my_warner) #if defined(NEED_warner) || defined(NEED_warner_GLOBAL) void DPPP_(my_warner)(U32 err, const char *pat, ...) { SV *sv; va_list args; PERL_UNUSED_ARG(err); va_start(args, pat); sv = vnewSVpvf(pat, &args); va_end(args); sv_2mortal(sv); warn("%s", SvPV_nolen(sv)); } #define warner Perl_warner #define Perl_warner_nocontext Perl_warner #endif #endif /* concatenating with "" ensures that only literal strings are accepted as argument * note that STR_WITH_LEN() can't be used as argument to macros or functions that * under some configurations might be macros */ #ifndef STR_WITH_LEN # define STR_WITH_LEN(s) (s ""), (sizeof(s)-1) #endif #ifndef newSVpvs # define newSVpvs(str) newSVpvn(str "", sizeof(str) - 1) #endif #ifndef newSVpvs_flags # define newSVpvs_flags(str, flags) newSVpvn_flags(str "", sizeof(str) - 1, flags) #endif #ifndef newSVpvs_share # define newSVpvs_share(str) newSVpvn_share(str "", sizeof(str) - 1, 0) #endif #ifndef sv_catpvs # define sv_catpvs(sv, str) sv_catpvn(sv, str "", sizeof(str) - 1) #endif #ifndef sv_setpvs # define sv_setpvs(sv, str) sv_setpvn(sv, str "", sizeof(str) - 1) #endif #ifndef hv_fetchs # define hv_fetchs(hv, key, lval) hv_fetch(hv, key "", sizeof(key) - 1, lval) #endif #ifndef hv_stores # define hv_stores(hv, key, val) hv_store(hv, key "", sizeof(key) - 1, val, 0) #endif #ifndef gv_fetchpvs # define gv_fetchpvs(name, flags, svt) gv_fetchpvn_flags(name "", sizeof(name) - 1, flags, svt) #endif #ifndef gv_stashpvs # define gv_stashpvs(name, flags) gv_stashpvn(name "", sizeof(name) - 1, flags) #endif #ifndef get_cvs # define get_cvs(name, flags) get_cvn_flags(name "", sizeof(name)-1, flags) #endif #ifndef SvGETMAGIC # define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END #endif /* Some random bits for sv_unmagicext. These should probably be pulled in for real and organized at some point */ #ifndef HEf_SVKEY # define HEf_SVKEY -2 #endif #ifndef MUTABLE_PTR #if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) # define MUTABLE_PTR(p) ({ void *_p = (p); _p; }) #else # define MUTABLE_PTR(p) ((void *) (p)) #endif #endif #ifndef MUTABLE_SV # define MUTABLE_SV(p) ((SV *)MUTABLE_PTR(p)) #endif /* end of random bits */ #ifndef PERL_MAGIC_sv # define PERL_MAGIC_sv '\0' #endif #ifndef PERL_MAGIC_overload # define PERL_MAGIC_overload 'A' #endif #ifndef PERL_MAGIC_overload_elem # define PERL_MAGIC_overload_elem 'a' #endif #ifndef PERL_MAGIC_overload_table # define PERL_MAGIC_overload_table 'c' #endif #ifndef PERL_MAGIC_bm # define PERL_MAGIC_bm 'B' #endif #ifndef PERL_MAGIC_regdata # define PERL_MAGIC_regdata 'D' #endif #ifndef PERL_MAGIC_regdatum # define PERL_MAGIC_regdatum 'd' #endif #ifndef PERL_MAGIC_env # define PERL_MAGIC_env 'E' #endif #ifndef PERL_MAGIC_envelem # define PERL_MAGIC_envelem 'e' #endif #ifndef PERL_MAGIC_fm # define PERL_MAGIC_fm 'f' #endif #ifndef PERL_MAGIC_regex_global # define PERL_MAGIC_regex_global 'g' #endif #ifndef PERL_MAGIC_isa # define PERL_MAGIC_isa 'I' #endif #ifndef PERL_MAGIC_isaelem # define PERL_MAGIC_isaelem 'i' #endif #ifndef PERL_MAGIC_nkeys # define PERL_MAGIC_nkeys 'k' #endif #ifndef PERL_MAGIC_dbfile # define PERL_MAGIC_dbfile 'L' #endif #ifndef PERL_MAGIC_dbline # define PERL_MAGIC_dbline 'l' #endif #ifndef PERL_MAGIC_mutex # define PERL_MAGIC_mutex 'm' #endif #ifndef PERL_MAGIC_shared # define PERL_MAGIC_shared 'N' #endif #ifndef PERL_MAGIC_shared_scalar # define PERL_MAGIC_shared_scalar 'n' #endif #ifndef PERL_MAGIC_collxfrm # define PERL_MAGIC_collxfrm 'o' #endif #ifndef PERL_MAGIC_tied # define PERL_MAGIC_tied 'P' #endif #ifndef PERL_MAGIC_tiedelem # define PERL_MAGIC_tiedelem 'p' #endif #ifndef PERL_MAGIC_tiedscalar # define PERL_MAGIC_tiedscalar 'q' #endif #ifndef PERL_MAGIC_qr # define PERL_MAGIC_qr 'r' #endif #ifndef PERL_MAGIC_sig # define PERL_MAGIC_sig 'S' #endif #ifndef PERL_MAGIC_sigelem # define PERL_MAGIC_sigelem 's' #endif #ifndef PERL_MAGIC_taint # define PERL_MAGIC_taint 't' #endif #ifndef PERL_MAGIC_uvar # define PERL_MAGIC_uvar 'U' #endif #ifndef PERL_MAGIC_uvar_elem # define PERL_MAGIC_uvar_elem 'u' #endif #ifndef PERL_MAGIC_vstring # define PERL_MAGIC_vstring 'V' #endif #ifndef PERL_MAGIC_vec # define PERL_MAGIC_vec 'v' #endif #ifndef PERL_MAGIC_utf8 # define PERL_MAGIC_utf8 'w' #endif #ifndef PERL_MAGIC_substr # define PERL_MAGIC_substr 'x' #endif #ifndef PERL_MAGIC_defelem # define PERL_MAGIC_defelem 'y' #endif #ifndef PERL_MAGIC_glob # define PERL_MAGIC_glob '*' #endif #ifndef PERL_MAGIC_arylen # define PERL_MAGIC_arylen '#' #endif #ifndef PERL_MAGIC_pos # define PERL_MAGIC_pos '.' #endif #ifndef PERL_MAGIC_backref # define PERL_MAGIC_backref '<' #endif #ifndef PERL_MAGIC_ext # define PERL_MAGIC_ext '~' #endif /* That's the best we can do... */ #ifndef sv_catpvn_nomg # define sv_catpvn_nomg sv_catpvn #endif #ifndef sv_catsv_nomg # define sv_catsv_nomg sv_catsv #endif #ifndef sv_setsv_nomg # define sv_setsv_nomg sv_setsv #endif #ifndef sv_pvn_nomg # define sv_pvn_nomg sv_pvn #endif #ifndef SvIV_nomg # define SvIV_nomg SvIV #endif #ifndef SvUV_nomg # define SvUV_nomg SvUV #endif #ifndef sv_catpv_mg # define sv_catpv_mg(sv, ptr) \ STMT_START { \ SV *TeMpSv = sv; \ sv_catpv(TeMpSv,ptr); \ SvSETMAGIC(TeMpSv); \ } STMT_END #endif #ifndef sv_catpvn_mg # define sv_catpvn_mg(sv, ptr, len) \ STMT_START { \ SV *TeMpSv = sv; \ sv_catpvn(TeMpSv,ptr,len); \ SvSETMAGIC(TeMpSv); \ } STMT_END #endif #ifndef sv_catsv_mg # define sv_catsv_mg(dsv, ssv) \ STMT_START { \ SV *TeMpSv = dsv; \ sv_catsv(TeMpSv,ssv); \ SvSETMAGIC(TeMpSv); \ } STMT_END #endif #ifndef sv_setiv_mg # define sv_setiv_mg(sv, i) \ STMT_START { \ SV *TeMpSv = sv; \ sv_setiv(TeMpSv,i); \ SvSETMAGIC(TeMpSv); \ } STMT_END #endif #ifndef sv_setnv_mg # define sv_setnv_mg(sv, num) \ STMT_START { \ SV *TeMpSv = sv; \ sv_setnv(TeMpSv,num); \ SvSETMAGIC(TeMpSv); \ } STMT_END #endif #ifndef sv_setpv_mg # define sv_setpv_mg(sv, ptr) \ STMT_START { \ SV *TeMpSv = sv; \ sv_setpv(TeMpSv,ptr); \ SvSETMAGIC(TeMpSv); \ } STMT_END #endif #ifndef sv_setpvn_mg # define sv_setpvn_mg(sv, ptr, len) \ STMT_START { \ SV *TeMpSv = sv; \ sv_setpvn(TeMpSv,ptr,len); \ SvSETMAGIC(TeMpSv); \ } STMT_END #endif #ifndef sv_setsv_mg # define sv_setsv_mg(dsv, ssv) \ STMT_START { \ SV *TeMpSv = dsv; \ sv_setsv(TeMpSv,ssv); \ SvSETMAGIC(TeMpSv); \ } STMT_END #endif #ifndef sv_setuv_mg # define sv_setuv_mg(sv, i) \ STMT_START { \ SV *TeMpSv = sv; \ sv_setuv(TeMpSv,i); \ SvSETMAGIC(TeMpSv); \ } STMT_END #endif #ifndef sv_usepvn_mg # define sv_usepvn_mg(sv, ptr, len) \ STMT_START { \ SV *TeMpSv = sv; \ sv_usepvn(TeMpSv,ptr,len); \ SvSETMAGIC(TeMpSv); \ } STMT_END #endif #ifndef SvVSTRING_mg # define SvVSTRING_mg(sv) (SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_vstring) : NULL) #endif /* Hint: sv_magic_portable * This is a compatibility function that is only available with * Devel::PPPort. It is NOT in the perl core. * Its purpose is to mimic the 5.8.0 behaviour of sv_magic() when * it is being passed a name pointer with namlen == 0. In that * case, perl 5.8.0 and later store the pointer, not a copy of it. * The compatibility can be provided back to perl 5.004. With * earlier versions, the code will not compile. */ #if (PERL_BCDVERSION < 0x5004000) /* code that uses sv_magic_portable will not compile */ #elif (PERL_BCDVERSION < 0x5008000) # define sv_magic_portable(sv, obj, how, name, namlen) \ STMT_START { \ SV *SvMp_sv = (sv); \ char *SvMp_name = (char *) (name); \ I32 SvMp_namlen = (namlen); \ if (SvMp_name && SvMp_namlen == 0) \ { \ MAGIC *mg; \ sv_magic(SvMp_sv, obj, how, 0, 0); \ mg = SvMAGIC(SvMp_sv); \ mg->mg_len = -42; /* XXX: this is the tricky part */ \ mg->mg_ptr = SvMp_name; \ } \ else \ { \ sv_magic(SvMp_sv, obj, how, SvMp_name, SvMp_namlen); \ } \ } STMT_END #else # define sv_magic_portable(a, b, c, d, e) sv_magic(a, b, c, d, e) #endif #if !defined(mg_findext) #if defined(NEED_mg_findext) static MAGIC * DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl); static #else extern MAGIC * DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl); #endif #define mg_findext DPPP_(my_mg_findext) #define Perl_mg_findext DPPP_(my_mg_findext) #if defined(NEED_mg_findext) || defined(NEED_mg_findext_GLOBAL) MAGIC * DPPP_(my_mg_findext)(SV * sv, int type, const MGVTBL *vtbl) { if (sv) { MAGIC *mg; #ifdef AvPAD_NAMELIST assert(!(SvTYPE(sv) == SVt_PVAV && AvPAD_NAMELIST(sv))); #endif for (mg = SvMAGIC (sv); mg; mg = mg->mg_moremagic) { if (mg->mg_type == type && mg->mg_virtual == vtbl) return mg; } } return NULL; } #endif #endif #if !defined(sv_unmagicext) #if defined(NEED_sv_unmagicext) static int DPPP_(my_sv_unmagicext)(pTHX_ SV * const sv, const int type, MGVTBL * vtbl); static #else extern int DPPP_(my_sv_unmagicext)(pTHX_ SV * const sv, const int type, MGVTBL * vtbl); #endif #ifdef sv_unmagicext # undef sv_unmagicext #endif #define sv_unmagicext(a,b,c) DPPP_(my_sv_unmagicext)(aTHX_ a,b,c) #define Perl_sv_unmagicext DPPP_(my_sv_unmagicext) #if defined(NEED_sv_unmagicext) || defined(NEED_sv_unmagicext_GLOBAL) int DPPP_(my_sv_unmagicext)(pTHX_ SV *const sv, const int type, MGVTBL *vtbl) { MAGIC* mg; MAGIC** mgp; if (SvTYPE(sv) < SVt_PVMG || !SvMAGIC(sv)) return 0; mgp = &(SvMAGIC(sv)); for (mg = *mgp; mg; mg = *mgp) { const MGVTBL* const virt = mg->mg_virtual; if (mg->mg_type == type && virt == vtbl) { *mgp = mg->mg_moremagic; if (virt && virt->svt_free) virt->svt_free(aTHX_ sv, mg); if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) { if (mg->mg_len > 0) Safefree(mg->mg_ptr); else if (mg->mg_len == HEf_SVKEY) /* Questionable on older perls... */ SvREFCNT_dec(MUTABLE_SV(mg->mg_ptr)); else if (mg->mg_type == PERL_MAGIC_utf8) Safefree(mg->mg_ptr); } if (mg->mg_flags & MGf_REFCOUNTED) SvREFCNT_dec(mg->mg_obj); Safefree(mg); } else mgp = &mg->mg_moremagic; } if (SvMAGIC(sv)) { if (SvMAGICAL(sv)) /* if we're under save_magic, wait for restore_magic; */ mg_magical(sv); /* else fix the flags now */ } else { SvMAGICAL_off(sv); SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT; } return 0; } #endif #endif #ifdef USE_ITHREADS #ifndef CopFILE # define CopFILE(c) ((c)->cop_file) #endif #ifndef CopFILEGV # define CopFILEGV(c) (CopFILE(c) ? gv_fetchfile(CopFILE(c)) : Nullgv) #endif #ifndef CopFILE_set # define CopFILE_set(c,pv) ((c)->cop_file = savepv(pv)) #endif #ifndef CopFILESV # define CopFILESV(c) (CopFILE(c) ? GvSV(gv_fetchfile(CopFILE(c))) : Nullsv) #endif #ifndef CopFILEAV # define CopFILEAV(c) (CopFILE(c) ? GvAV(gv_fetchfile(CopFILE(c))) : Nullav) #endif #ifndef CopSTASHPV # define CopSTASHPV(c) ((c)->cop_stashpv) #endif #ifndef CopSTASHPV_set # define CopSTASHPV_set(c,pv) ((c)->cop_stashpv = ((pv) ? savepv(pv) : Nullch)) #endif #ifndef CopSTASH # define CopSTASH(c) (CopSTASHPV(c) ? gv_stashpv(CopSTASHPV(c),GV_ADD) : Nullhv) #endif #ifndef CopSTASH_set # define CopSTASH_set(c,hv) CopSTASHPV_set(c, (hv) ? HvNAME(hv) : Nullch) #endif #ifndef CopSTASH_eq # define CopSTASH_eq(c,hv) ((hv) && (CopSTASHPV(c) == HvNAME(hv) \ || (CopSTASHPV(c) && HvNAME(hv) \ && strEQ(CopSTASHPV(c), HvNAME(hv))))) #endif #else #ifndef CopFILEGV # define CopFILEGV(c) ((c)->cop_filegv) #endif #ifndef CopFILEGV_set # define CopFILEGV_set(c,gv) ((c)->cop_filegv = (GV*)SvREFCNT_inc(gv)) #endif #ifndef CopFILE_set # define CopFILE_set(c,pv) CopFILEGV_set((c), gv_fetchfile(pv)) #endif #ifndef CopFILESV # define CopFILESV(c) (CopFILEGV(c) ? GvSV(CopFILEGV(c)) : Nullsv) #endif #ifndef CopFILEAV # define CopFILEAV(c) (CopFILEGV(c) ? GvAV(CopFILEGV(c)) : Nullav) #endif #ifndef CopFILE # define CopFILE(c) (CopFILESV(c) ? SvPVX(CopFILESV(c)) : Nullch) #endif #ifndef CopSTASH # define CopSTASH(c) ((c)->cop_stash) #endif #ifndef CopSTASH_set # define CopSTASH_set(c,hv) ((c)->cop_stash = (hv)) #endif #ifndef CopSTASHPV # define CopSTASHPV(c) (CopSTASH(c) ? HvNAME(CopSTASH(c)) : Nullch) #endif #ifndef CopSTASHPV_set # define CopSTASHPV_set(c,pv) CopSTASH_set((c), gv_stashpv(pv,GV_ADD)) #endif #ifndef CopSTASH_eq # define CopSTASH_eq(c,hv) (CopSTASH(c) == (hv)) #endif #endif /* USE_ITHREADS */ #if (PERL_BCDVERSION >= 0x5006000) #ifndef caller_cx # if defined(NEED_caller_cx) || defined(NEED_caller_cx_GLOBAL) static I32 DPPP_dopoptosub_at(const PERL_CONTEXT *cxstk, I32 startingblock) { I32 i; for (i = startingblock; i >= 0; i--) { register const PERL_CONTEXT * const cx = &cxstk[i]; switch (CxTYPE(cx)) { default: continue; case CXt_EVAL: case CXt_SUB: case CXt_FORMAT: return i; } } return i; } # endif # if defined(NEED_caller_cx) static const PERL_CONTEXT * DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp); static #else extern const PERL_CONTEXT * DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp); #endif #ifdef caller_cx # undef caller_cx #endif #define caller_cx(a,b) DPPP_(my_caller_cx)(aTHX_ a,b) #define Perl_caller_cx DPPP_(my_caller_cx) #if defined(NEED_caller_cx) || defined(NEED_caller_cx_GLOBAL) const PERL_CONTEXT * DPPP_(my_caller_cx)(pTHX_ I32 count, const PERL_CONTEXT **dbcxp) { register I32 cxix = DPPP_dopoptosub_at(cxstack, cxstack_ix); register const PERL_CONTEXT *cx; register const PERL_CONTEXT *ccstack = cxstack; const PERL_SI *top_si = PL_curstackinfo; for (;;) { /* we may be in a higher stacklevel, so dig down deeper */ while (cxix < 0 && top_si->si_type != PERLSI_MAIN) { top_si = top_si->si_prev; ccstack = top_si->si_cxstack; cxix = DPPP_dopoptosub_at(ccstack, top_si->si_cxix); } if (cxix < 0) return NULL; /* caller() should not report the automatic calls to &DB::sub */ if (PL_DBsub && GvCV(PL_DBsub) && cxix >= 0 && ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub)) count++; if (!count--) break; cxix = DPPP_dopoptosub_at(ccstack, cxix - 1); } cx = &ccstack[cxix]; if (dbcxp) *dbcxp = cx; if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) { const I32 dbcxix = DPPP_dopoptosub_at(ccstack, cxix - 1); /* We expect that ccstack[dbcxix] is CXt_SUB, anyway, the field below is defined for any cx. */ /* caller() should not report the automatic calls to &DB::sub */ if (PL_DBsub && GvCV(PL_DBsub) && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) cx = &ccstack[dbcxix]; } return cx; } # endif #endif /* caller_cx */ #endif /* 5.6.0 */ #ifndef IN_PERL_COMPILETIME # define IN_PERL_COMPILETIME (PL_curcop == &PL_compiling) #endif #ifndef IN_LOCALE_RUNTIME # define IN_LOCALE_RUNTIME (PL_curcop->op_private & HINT_LOCALE) #endif #ifndef IN_LOCALE_COMPILETIME # define IN_LOCALE_COMPILETIME (PL_hints & HINT_LOCALE) #endif #ifndef IN_LOCALE # define IN_LOCALE (IN_PERL_COMPILETIME ? IN_LOCALE_COMPILETIME : IN_LOCALE_RUNTIME) #endif #ifndef IS_NUMBER_IN_UV # define IS_NUMBER_IN_UV 0x01 #endif #ifndef IS_NUMBER_GREATER_THAN_UV_MAX # define IS_NUMBER_GREATER_THAN_UV_MAX 0x02 #endif #ifndef IS_NUMBER_NOT_INT # define IS_NUMBER_NOT_INT 0x04 #endif #ifndef IS_NUMBER_NEG # define IS_NUMBER_NEG 0x08 #endif #ifndef IS_NUMBER_INFINITY # define IS_NUMBER_INFINITY 0x10 #endif #ifndef IS_NUMBER_NAN # define IS_NUMBER_NAN 0x20 #endif #ifndef GROK_NUMERIC_RADIX # define GROK_NUMERIC_RADIX(sp, send) grok_numeric_radix(sp, send) #endif #ifndef PERL_SCAN_GREATER_THAN_UV_MAX # define PERL_SCAN_GREATER_THAN_UV_MAX 0x02 #endif #ifndef PERL_SCAN_SILENT_ILLDIGIT # define PERL_SCAN_SILENT_ILLDIGIT 0x04 #endif #ifndef PERL_SCAN_ALLOW_UNDERSCORES # define PERL_SCAN_ALLOW_UNDERSCORES 0x01 #endif #ifndef PERL_SCAN_DISALLOW_PREFIX # define PERL_SCAN_DISALLOW_PREFIX 0x02 #endif #ifndef grok_numeric_radix #if defined(NEED_grok_numeric_radix) static bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send); static #else extern bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send); #endif #ifdef grok_numeric_radix # undef grok_numeric_radix #endif #define grok_numeric_radix(a,b) DPPP_(my_grok_numeric_radix)(aTHX_ a,b) #define Perl_grok_numeric_radix DPPP_(my_grok_numeric_radix) #if defined(NEED_grok_numeric_radix) || defined(NEED_grok_numeric_radix_GLOBAL) bool DPPP_(my_grok_numeric_radix)(pTHX_ const char **sp, const char *send) { #ifdef USE_LOCALE_NUMERIC #ifdef PL_numeric_radix_sv if (PL_numeric_radix_sv && IN_LOCALE) { STRLEN len; char* radix = SvPV(PL_numeric_radix_sv, len); if (*sp + len <= send && memEQ(*sp, radix, len)) { *sp += len; return TRUE; } } #else /* older perls don't have PL_numeric_radix_sv so the radix * must manually be requested from locale.h */ #include dTHR; /* needed for older threaded perls */ struct lconv *lc = localeconv(); char *radix = lc->decimal_point; if (radix && IN_LOCALE) { STRLEN len = strlen(radix); if (*sp + len <= send && memEQ(*sp, radix, len)) { *sp += len; return TRUE; } } #endif #endif /* USE_LOCALE_NUMERIC */ /* always try "." if numeric radix didn't match because * we may have data from different locales mixed */ if (*sp < send && **sp == '.') { ++*sp; return TRUE; } return FALSE; } #endif #endif #ifndef grok_number #if defined(NEED_grok_number) static int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep); static #else extern int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep); #endif #ifdef grok_number # undef grok_number #endif #define grok_number(a,b,c) DPPP_(my_grok_number)(aTHX_ a,b,c) #define Perl_grok_number DPPP_(my_grok_number) #if defined(NEED_grok_number) || defined(NEED_grok_number_GLOBAL) int DPPP_(my_grok_number)(pTHX_ const char *pv, STRLEN len, UV *valuep) { const char *s = pv; const char *send = pv + len; const UV max_div_10 = UV_MAX / 10; const char max_mod_10 = UV_MAX % 10; int numtype = 0; int sawinf = 0; int sawnan = 0; while (s < send && isSPACE(*s)) s++; if (s == send) { return 0; } else if (*s == '-') { s++; numtype = IS_NUMBER_NEG; } else if (*s == '+') s++; if (s == send) return 0; /* next must be digit or the radix separator or beginning of infinity */ if (isDIGIT(*s)) { /* UVs are at least 32 bits, so the first 9 decimal digits cannot overflow. */ UV value = *s - '0'; /* This construction seems to be more optimiser friendly. (without it gcc does the isDIGIT test and the *s - '0' separately) With it gcc on arm is managing 6 instructions (6 cycles) per digit. In theory the optimiser could deduce how far to unroll the loop before checking for overflow. */ if (++s < send) { int digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { /* Now got 9 digits, so need to check each time for overflow. */ digit = *s - '0'; while (digit >= 0 && digit <= 9 && (value < max_div_10 || (value == max_div_10 && digit <= max_mod_10))) { value = value * 10 + digit; if (++s < send) digit = *s - '0'; else break; } if (digit >= 0 && digit <= 9 && (s < send)) { /* value overflowed. skip the remaining digits, don't worry about setting *valuep. */ do { s++; } while (s < send && isDIGIT(*s)); numtype |= IS_NUMBER_GREATER_THAN_UV_MAX; goto skip_value; } } } } } } } } } } } } } } } } } } numtype |= IS_NUMBER_IN_UV; if (valuep) *valuep = value; skip_value: if (GROK_NUMERIC_RADIX(&s, send)) { numtype |= IS_NUMBER_NOT_INT; while (s < send && isDIGIT(*s)) /* optional digits after the radix */ s++; } } else if (GROK_NUMERIC_RADIX(&s, send)) { numtype |= IS_NUMBER_NOT_INT | IS_NUMBER_IN_UV; /* valuep assigned below */ /* no digits before the radix means we need digits after it */ if (s < send && isDIGIT(*s)) { do { s++; } while (s < send && isDIGIT(*s)); if (valuep) { /* integer approximation is valid - it's 0. */ *valuep = 0; } } else return 0; } else if (*s == 'I' || *s == 'i') { s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; s++; if (s == send || (*s != 'F' && *s != 'f')) return 0; s++; if (s < send && (*s == 'I' || *s == 'i')) { s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; s++; if (s == send || (*s != 'I' && *s != 'i')) return 0; s++; if (s == send || (*s != 'T' && *s != 't')) return 0; s++; if (s == send || (*s != 'Y' && *s != 'y')) return 0; s++; } sawinf = 1; } else if (*s == 'N' || *s == 'n') { /* XXX TODO: There are signaling NaNs and quiet NaNs. */ s++; if (s == send || (*s != 'A' && *s != 'a')) return 0; s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; s++; sawnan = 1; } else return 0; if (sawinf) { numtype &= IS_NUMBER_NEG; /* Keep track of sign */ numtype |= IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT; } else if (sawnan) { numtype &= IS_NUMBER_NEG; /* Keep track of sign */ numtype |= IS_NUMBER_NAN | IS_NUMBER_NOT_INT; } else if (s < send) { /* we can have an optional exponent part */ if (*s == 'e' || *s == 'E') { /* The only flag we keep is sign. Blow away any "it's UV" */ numtype &= IS_NUMBER_NEG; numtype |= IS_NUMBER_NOT_INT; s++; if (s < send && (*s == '-' || *s == '+')) s++; if (s < send && isDIGIT(*s)) { do { s++; } while (s < send && isDIGIT(*s)); } else return 0; } } while (s < send && isSPACE(*s)) s++; if (s >= send) return numtype; if (len == 10 && memEQ(pv, "0 but true", 10)) { if (valuep) *valuep = 0; return IS_NUMBER_IN_UV; } return 0; } #endif #endif /* * The grok_* routines have been modified to use warn() instead of * Perl_warner(). Also, 'hexdigit' was the former name of PL_hexdigit, * which is why the stack variable has been renamed to 'xdigit'. */ #ifndef grok_bin #if defined(NEED_grok_bin) static UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); static #else extern UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); #endif #ifdef grok_bin # undef grok_bin #endif #define grok_bin(a,b,c,d) DPPP_(my_grok_bin)(aTHX_ a,b,c,d) #define Perl_grok_bin DPPP_(my_grok_bin) #if defined(NEED_grok_bin) || defined(NEED_grok_bin_GLOBAL) UV DPPP_(my_grok_bin)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) { const char *s = start; STRLEN len = *len_p; UV value = 0; NV value_nv = 0; const UV max_div_2 = UV_MAX / 2; bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; bool overflowed = FALSE; if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) { /* strip off leading b or 0b. for compatibility silently suffer "b" and "0b" as valid binary numbers. */ if (len >= 1) { if (s[0] == 'b') { s++; len--; } else if (len >= 2 && s[0] == '0' && s[1] == 'b') { s+=2; len-=2; } } } for (; len-- && *s; s++) { char bit = *s; if (bit == '0' || bit == '1') { /* Write it in this wonky order with a goto to attempt to get the compiler to make the common case integer-only loop pretty tight. With gcc seems to be much straighter code than old scan_bin. */ redo: if (!overflowed) { if (value <= max_div_2) { value = (value << 1) | (bit - '0'); continue; } /* Bah. We're just overflowed. */ warn("Integer overflow in binary number"); overflowed = TRUE; value_nv = (NV) value; } value_nv *= 2.0; /* If an NV has not enough bits in its mantissa to * represent a UV this summing of small low-order numbers * is a waste of time (because the NV cannot preserve * the low-order bits anyway): we could just remember when * did we overflow and in the end just multiply value_nv by the * right amount. */ value_nv += (NV)(bit - '0'); continue; } if (bit == '_' && len && allow_underscores && (bit = s[1]) && (bit == '0' || bit == '1')) { --len; ++s; goto redo; } if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) warn("Illegal binary digit '%c' ignored", *s); break; } if ( ( overflowed && value_nv > 4294967295.0) #if UVSIZE > 4 || (!overflowed && value > 0xffffffff ) #endif ) { warn("Binary number > 0b11111111111111111111111111111111 non-portable"); } *len_p = s - start; if (!overflowed) { *flags = 0; return value; } *flags = PERL_SCAN_GREATER_THAN_UV_MAX; if (result) *result = value_nv; return UV_MAX; } #endif #endif #ifndef grok_hex #if defined(NEED_grok_hex) static UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); static #else extern UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); #endif #ifdef grok_hex # undef grok_hex #endif #define grok_hex(a,b,c,d) DPPP_(my_grok_hex)(aTHX_ a,b,c,d) #define Perl_grok_hex DPPP_(my_grok_hex) #if defined(NEED_grok_hex) || defined(NEED_grok_hex_GLOBAL) UV DPPP_(my_grok_hex)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) { const char *s = start; STRLEN len = *len_p; UV value = 0; NV value_nv = 0; const UV max_div_16 = UV_MAX / 16; bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; bool overflowed = FALSE; const char *xdigit; if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) { /* strip off leading x or 0x. for compatibility silently suffer "x" and "0x" as valid hex numbers. */ if (len >= 1) { if (s[0] == 'x') { s++; len--; } else if (len >= 2 && s[0] == '0' && s[1] == 'x') { s+=2; len-=2; } } } for (; len-- && *s; s++) { xdigit = strchr((char *) PL_hexdigit, *s); if (xdigit) { /* Write it in this wonky order with a goto to attempt to get the compiler to make the common case integer-only loop pretty tight. With gcc seems to be much straighter code than old scan_hex. */ redo: if (!overflowed) { if (value <= max_div_16) { value = (value << 4) | ((xdigit - PL_hexdigit) & 15); continue; } warn("Integer overflow in hexadecimal number"); overflowed = TRUE; value_nv = (NV) value; } value_nv *= 16.0; /* If an NV has not enough bits in its mantissa to * represent a UV this summing of small low-order numbers * is a waste of time (because the NV cannot preserve * the low-order bits anyway): we could just remember when * did we overflow and in the end just multiply value_nv by the * right amount of 16-tuples. */ value_nv += (NV)((xdigit - PL_hexdigit) & 15); continue; } if (*s == '_' && len && allow_underscores && s[1] && (xdigit = strchr((char *) PL_hexdigit, s[1]))) { --len; ++s; goto redo; } if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) warn("Illegal hexadecimal digit '%c' ignored", *s); break; } if ( ( overflowed && value_nv > 4294967295.0) #if UVSIZE > 4 || (!overflowed && value > 0xffffffff ) #endif ) { warn("Hexadecimal number > 0xffffffff non-portable"); } *len_p = s - start; if (!overflowed) { *flags = 0; return value; } *flags = PERL_SCAN_GREATER_THAN_UV_MAX; if (result) *result = value_nv; return UV_MAX; } #endif #endif #ifndef grok_oct #if defined(NEED_grok_oct) static UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); static #else extern UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); #endif #ifdef grok_oct # undef grok_oct #endif #define grok_oct(a,b,c,d) DPPP_(my_grok_oct)(aTHX_ a,b,c,d) #define Perl_grok_oct DPPP_(my_grok_oct) #if defined(NEED_grok_oct) || defined(NEED_grok_oct_GLOBAL) UV DPPP_(my_grok_oct)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) { const char *s = start; STRLEN len = *len_p; UV value = 0; NV value_nv = 0; const UV max_div_8 = UV_MAX / 8; bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; bool overflowed = FALSE; for (; len-- && *s; s++) { /* gcc 2.95 optimiser not smart enough to figure that this subtraction out front allows slicker code. */ int digit = *s - '0'; if (digit >= 0 && digit <= 7) { /* Write it in this wonky order with a goto to attempt to get the compiler to make the common case integer-only loop pretty tight. */ redo: if (!overflowed) { if (value <= max_div_8) { value = (value << 3) | digit; continue; } /* Bah. We're just overflowed. */ warn("Integer overflow in octal number"); overflowed = TRUE; value_nv = (NV) value; } value_nv *= 8.0; /* If an NV has not enough bits in its mantissa to * represent a UV this summing of small low-order numbers * is a waste of time (because the NV cannot preserve * the low-order bits anyway): we could just remember when * did we overflow and in the end just multiply value_nv by the * right amount of 8-tuples. */ value_nv += (NV)digit; continue; } if (digit == ('_' - '0') && len && allow_underscores && (digit = s[1] - '0') && (digit >= 0 && digit <= 7)) { --len; ++s; goto redo; } /* Allow \octal to work the DWIM way (that is, stop scanning * as soon as non-octal characters are seen, complain only iff * someone seems to want to use the digits eight and nine). */ if (digit == 8 || digit == 9) { if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) warn("Illegal octal digit '%c' ignored", *s); } break; } if ( ( overflowed && value_nv > 4294967295.0) #if UVSIZE > 4 || (!overflowed && value > 0xffffffff ) #endif ) { warn("Octal number > 037777777777 non-portable"); } *len_p = s - start; if (!overflowed) { *flags = 0; return value; } *flags = PERL_SCAN_GREATER_THAN_UV_MAX; if (result) *result = value_nv; return UV_MAX; } #endif #endif #if !defined(my_snprintf) #if defined(NEED_my_snprintf) static int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...); static #else extern int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...); #endif #define my_snprintf DPPP_(my_my_snprintf) #define Perl_my_snprintf DPPP_(my_my_snprintf) #if defined(NEED_my_snprintf) || defined(NEED_my_snprintf_GLOBAL) int DPPP_(my_my_snprintf)(char *buffer, const Size_t len, const char *format, ...) { dTHX; int retval; va_list ap; va_start(ap, format); #ifdef HAS_VSNPRINTF retval = vsnprintf(buffer, len, format, ap); #else retval = vsprintf(buffer, format, ap); #endif va_end(ap); if (retval < 0 || (len > 0 && (Size_t)retval >= len)) Perl_croak(aTHX_ "panic: my_snprintf buffer overflow"); return retval; } #endif #endif #if !defined(my_sprintf) #if defined(NEED_my_sprintf) static int DPPP_(my_my_sprintf)(char * buffer, const char * pat, ...); static #else extern int DPPP_(my_my_sprintf)(char * buffer, const char * pat, ...); #endif #define my_sprintf DPPP_(my_my_sprintf) #define Perl_my_sprintf DPPP_(my_my_sprintf) #if defined(NEED_my_sprintf) || defined(NEED_my_sprintf_GLOBAL) int DPPP_(my_my_sprintf)(char *buffer, const char* pat, ...) { va_list args; va_start(args, pat); vsprintf(buffer, pat, args); va_end(args); return strlen(buffer); } #endif #endif #ifdef NO_XSLOCKS # ifdef dJMPENV # define dXCPT dJMPENV; int rEtV = 0 # define XCPT_TRY_START JMPENV_PUSH(rEtV); if (rEtV == 0) # define XCPT_TRY_END JMPENV_POP; # define XCPT_CATCH if (rEtV != 0) # define XCPT_RETHROW JMPENV_JUMP(rEtV) # else # define dXCPT Sigjmp_buf oldTOP; int rEtV = 0 # define XCPT_TRY_START Copy(top_env, oldTOP, 1, Sigjmp_buf); rEtV = Sigsetjmp(top_env, 1); if (rEtV == 0) # define XCPT_TRY_END Copy(oldTOP, top_env, 1, Sigjmp_buf); # define XCPT_CATCH if (rEtV != 0) # define XCPT_RETHROW Siglongjmp(top_env, rEtV) # endif #endif #if !defined(my_strlcat) #if defined(NEED_my_strlcat) static Size_t DPPP_(my_my_strlcat)(char * dst, const char * src, Size_t size); static #else extern Size_t DPPP_(my_my_strlcat)(char * dst, const char * src, Size_t size); #endif #define my_strlcat DPPP_(my_my_strlcat) #define Perl_my_strlcat DPPP_(my_my_strlcat) #if defined(NEED_my_strlcat) || defined(NEED_my_strlcat_GLOBAL) Size_t DPPP_(my_my_strlcat)(char *dst, const char *src, Size_t size) { Size_t used, length, copy; used = strlen(dst); length = strlen(src); if (size > 0 && used < size - 1) { copy = (length >= size - used) ? size - used - 1 : length; memcpy(dst + used, src, copy); dst[used + copy] = '\0'; } return used + length; } #endif #endif #if !defined(my_strlcpy) #if defined(NEED_my_strlcpy) static Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size); static #else extern Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size); #endif #define my_strlcpy DPPP_(my_my_strlcpy) #define Perl_my_strlcpy DPPP_(my_my_strlcpy) #if defined(NEED_my_strlcpy) || defined(NEED_my_strlcpy_GLOBAL) Size_t DPPP_(my_my_strlcpy)(char *dst, const char *src, Size_t size) { Size_t length, copy; length = strlen(src); if (size > 0) { copy = (length >= size) ? size - 1 : length; memcpy(dst, src, copy); dst[copy] = '\0'; } return length; } #endif #endif #ifndef PERL_PV_ESCAPE_QUOTE # define PERL_PV_ESCAPE_QUOTE 0x0001 #endif #ifndef PERL_PV_PRETTY_QUOTE # define PERL_PV_PRETTY_QUOTE PERL_PV_ESCAPE_QUOTE #endif #ifndef PERL_PV_PRETTY_ELLIPSES # define PERL_PV_PRETTY_ELLIPSES 0x0002 #endif #ifndef PERL_PV_PRETTY_LTGT # define PERL_PV_PRETTY_LTGT 0x0004 #endif #ifndef PERL_PV_ESCAPE_FIRSTCHAR # define PERL_PV_ESCAPE_FIRSTCHAR 0x0008 #endif #ifndef PERL_PV_ESCAPE_UNI # define PERL_PV_ESCAPE_UNI 0x0100 #endif #ifndef PERL_PV_ESCAPE_UNI_DETECT # define PERL_PV_ESCAPE_UNI_DETECT 0x0200 #endif #ifndef PERL_PV_ESCAPE_ALL # define PERL_PV_ESCAPE_ALL 0x1000 #endif #ifndef PERL_PV_ESCAPE_NOBACKSLASH # define PERL_PV_ESCAPE_NOBACKSLASH 0x2000 #endif #ifndef PERL_PV_ESCAPE_NOCLEAR # define PERL_PV_ESCAPE_NOCLEAR 0x4000 #endif #ifndef PERL_PV_ESCAPE_RE # define PERL_PV_ESCAPE_RE 0x8000 #endif #ifndef PERL_PV_PRETTY_NOCLEAR # define PERL_PV_PRETTY_NOCLEAR PERL_PV_ESCAPE_NOCLEAR #endif #ifndef PERL_PV_PRETTY_DUMP # define PERL_PV_PRETTY_DUMP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_QUOTE #endif #ifndef PERL_PV_PRETTY_REGPROP # define PERL_PV_PRETTY_REGPROP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_LTGT|PERL_PV_ESCAPE_RE #endif /* Hint: pv_escape * Note that unicode functionality is only backported to * those perl versions that support it. For older perl * versions, the implementation will fall back to bytes. */ #ifndef pv_escape #if defined(NEED_pv_escape) static char * DPPP_(my_pv_escape)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, STRLEN * const escaped, const U32 flags); static #else extern char * DPPP_(my_pv_escape)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, STRLEN * const escaped, const U32 flags); #endif #ifdef pv_escape # undef pv_escape #endif #define pv_escape(a,b,c,d,e,f) DPPP_(my_pv_escape)(aTHX_ a,b,c,d,e,f) #define Perl_pv_escape DPPP_(my_pv_escape) #if defined(NEED_pv_escape) || defined(NEED_pv_escape_GLOBAL) char * DPPP_(my_pv_escape)(pTHX_ SV *dsv, char const * const str, const STRLEN count, const STRLEN max, STRLEN * const escaped, const U32 flags) { const char esc = flags & PERL_PV_ESCAPE_RE ? '%' : '\\'; const char dq = flags & PERL_PV_ESCAPE_QUOTE ? '"' : esc; char octbuf[32] = "%123456789ABCDF"; STRLEN wrote = 0; STRLEN chsize = 0; STRLEN readsize = 1; #if defined(is_utf8_string) && defined(utf8_to_uvchr) bool isuni = flags & PERL_PV_ESCAPE_UNI ? 1 : 0; #endif const char *pv = str; const char * const end = pv + count; octbuf[0] = esc; if (!(flags & PERL_PV_ESCAPE_NOCLEAR)) sv_setpvs(dsv, ""); #if defined(is_utf8_string) && defined(utf8_to_uvchr) if ((flags & PERL_PV_ESCAPE_UNI_DETECT) && is_utf8_string((U8*)pv, count)) isuni = 1; #endif for (; pv < end && (!max || wrote < max) ; pv += readsize) { const UV u = #if defined(is_utf8_string) && defined(utf8_to_uvchr) isuni ? utf8_to_uvchr((U8*)pv, &readsize) : #endif (U8)*pv; const U8 c = (U8)u & 0xFF; if (u > 255 || (flags & PERL_PV_ESCAPE_ALL)) { if (flags & PERL_PV_ESCAPE_FIRSTCHAR) chsize = my_snprintf(octbuf, sizeof octbuf, "%" UVxf, u); else chsize = my_snprintf(octbuf, sizeof octbuf, "%cx{%" UVxf "}", esc, u); } else if (flags & PERL_PV_ESCAPE_NOBACKSLASH) { chsize = 1; } else { if (c == dq || c == esc || !isPRINT(c)) { chsize = 2; switch (c) { case '\\' : /* fallthrough */ case '%' : if (c == esc) octbuf[1] = esc; else chsize = 1; break; case '\v' : octbuf[1] = 'v'; break; case '\t' : octbuf[1] = 't'; break; case '\r' : octbuf[1] = 'r'; break; case '\n' : octbuf[1] = 'n'; break; case '\f' : octbuf[1] = 'f'; break; case '"' : if (dq == '"') octbuf[1] = '"'; else chsize = 1; break; default: chsize = my_snprintf(octbuf, sizeof octbuf, pv < end && isDIGIT((U8)*(pv+readsize)) ? "%c%03o" : "%c%o", esc, c); } } else { chsize = 1; } } if (max && wrote + chsize > max) { break; } else if (chsize > 1) { sv_catpvn(dsv, octbuf, chsize); wrote += chsize; } else { char tmp[2]; my_snprintf(tmp, sizeof tmp, "%c", c); sv_catpvn(dsv, tmp, 1); wrote++; } if (flags & PERL_PV_ESCAPE_FIRSTCHAR) break; } if (escaped != NULL) *escaped= pv - str; return SvPVX(dsv); } #endif #endif #ifndef pv_pretty #if defined(NEED_pv_pretty) static char * DPPP_(my_pv_pretty)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, char const * const start_color, char const * const end_color, const U32 flags); static #else extern char * DPPP_(my_pv_pretty)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, char const * const start_color, char const * const end_color, const U32 flags); #endif #ifdef pv_pretty # undef pv_pretty #endif #define pv_pretty(a,b,c,d,e,f,g) DPPP_(my_pv_pretty)(aTHX_ a,b,c,d,e,f,g) #define Perl_pv_pretty DPPP_(my_pv_pretty) #if defined(NEED_pv_pretty) || defined(NEED_pv_pretty_GLOBAL) char * DPPP_(my_pv_pretty)(pTHX_ SV *dsv, char const * const str, const STRLEN count, const STRLEN max, char const * const start_color, char const * const end_color, const U32 flags) { const U8 dq = (flags & PERL_PV_PRETTY_QUOTE) ? '"' : '%'; STRLEN escaped; if (!(flags & PERL_PV_PRETTY_NOCLEAR)) sv_setpvs(dsv, ""); if (dq == '"') sv_catpvs(dsv, "\""); else if (flags & PERL_PV_PRETTY_LTGT) sv_catpvs(dsv, "<"); if (start_color != NULL) sv_catpv(dsv, D_PPP_CONSTPV_ARG(start_color)); pv_escape(dsv, str, count, max, &escaped, flags | PERL_PV_ESCAPE_NOCLEAR); if (end_color != NULL) sv_catpv(dsv, D_PPP_CONSTPV_ARG(end_color)); if (dq == '"') sv_catpvs(dsv, "\""); else if (flags & PERL_PV_PRETTY_LTGT) sv_catpvs(dsv, ">"); if ((flags & PERL_PV_PRETTY_ELLIPSES) && escaped < count) sv_catpvs(dsv, "..."); return SvPVX(dsv); } #endif #endif #ifndef pv_display #if defined(NEED_pv_display) static char * DPPP_(my_pv_display)(pTHX_ SV * dsv, const char * pv, STRLEN cur, STRLEN len, STRLEN pvlim); static #else extern char * DPPP_(my_pv_display)(pTHX_ SV * dsv, const char * pv, STRLEN cur, STRLEN len, STRLEN pvlim); #endif #ifdef pv_display # undef pv_display #endif #define pv_display(a,b,c,d,e) DPPP_(my_pv_display)(aTHX_ a,b,c,d,e) #define Perl_pv_display DPPP_(my_pv_display) #if defined(NEED_pv_display) || defined(NEED_pv_display_GLOBAL) char * DPPP_(my_pv_display)(pTHX_ SV *dsv, const char *pv, STRLEN cur, STRLEN len, STRLEN pvlim) { pv_pretty(dsv, pv, cur, pvlim, NULL, NULL, PERL_PV_PRETTY_DUMP); if (len > cur && pv[cur] == '\0') sv_catpvs(dsv, "\\0"); return SvPVX(dsv); } #endif #endif #endif /* _P_P_PORTABILITY_H_ */ /* End of File ppport.h */ DateTime-1.46/xt/0000775000175000017500000000000013240151623013432 5ustar autarchautarchDateTime-1.46/xt/release/0000775000175000017500000000000013240151623015052 5ustar autarchautarchDateTime-1.46/xt/release/cpan-changes.t0000644000175000017500000000034413240151623017565 0ustar autarchautarchuse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::CPAN::Changes 0.012 use Test::More 0.96 tests => 1; use Test::CPAN::Changes; subtest 'changes_ok' => sub { changes_file_ok('Changes'); }; DateTime-1.46/xt/release/meta-json.t0000644000175000017500000000006413240151623017132 0ustar autarchautarch#!perl use Test::CPAN::Meta::JSON; meta_json_ok(); DateTime-1.46/xt/author/0000775000175000017500000000000013240151623014734 5ustar autarchautarchDateTime-1.46/xt/author/pp-18today.t0000644000175000017500000000074113240151623017027 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; { my $now = DateTime->now; my $today = DateTime->today; is( $today->year, $now->year, 'today->year' ); is( $today->month, $now->month, 'today->month' ); is( $today->day, $now->day, 'today->day' ); is( $today->hour, 0, 'today->hour' ); is( $today->minute, 0, 'today->hour' ); is( $today->second, 0, 'today->hour' ); } done_testing(); DateTime-1.46/xt/author/clean-namespaces.t0000644000175000017500000000056613240151623020325 0ustar autarchautarchuse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::CleanNamespaces 0.006 use Test::More 0.94; use Test::CleanNamespaces 0.15; subtest all_namespaces_clean => sub { namespaces_clean( grep { my $mod = $_; not grep { $mod =~ $_ } qr/DateTime::Conflicts/ } Test::CleanNamespaces->find_modules ); }; done_testing; DateTime-1.46/xt/author/pp-15jd.t0000644000175000017500000000350713240151623016304 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; # Borrowed from Matt Sergeant's Time::Piece # A table of MJD and components my @mjd = ( '51603.524' => { year => 2000, month => 2, day => 29, hour => 12, minute => 34, second => 56, }, '40598.574' => { year => 1970, month => 1, day => 12, hour => 13, minute => 46, second => 51, }, '52411.140' => { year => 2002, month => 5, day => 17, hour => 3, minute => 21, second => 43, }, '53568.547' => { year => 2005, month => 7, day => 17, hour => 13, minute => 8, second => 23, }, '52295.218' => { year => 2002, month => 1, day => 21, hour => 5, minute => 13, second => 20, }, '52295.399' => { year => 2002, month => 1, day => 21, hour => 9, minute => 35, second => 3, }, # beginning of MJD '0.000' => { year => 1858, month => 11, day => 17, hour => 0, minute => 0, second => 0, }, # beginning of JD '-2400000.500' => { year => -4713, month => 11, day => 24, hour => 12, minute => 0, second => 0, }, ); while ( my ( $mjd, $comps ) = splice @mjd, 0, 2 ) { my $dt = DateTime->new( %$comps, time_zone => 'UTC', ); is( sprintf( '%.3f', $dt->mjd ), $mjd, "MJD should be $mjd" ); my $jd = sprintf( '%.3f', $mjd + 2_400_000.5 ); is( sprintf( '%.3f', $dt->jd ), $jd, "JD should be $jd" ); } done_testing(); DateTime-1.46/xt/author/pp-41cldr-format.t0000644000175000017500000001522113240151623020114 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use utf8; use Test::More; use DateTime; for my $o ( Test::Builder->new->output, Test::Builder->new->failure_output, Test::Builder->new->todo_output ) { binmode $o, ':encoding(UTF-8)' or die $!; } { my $dt = DateTime->new( year => 1976, month => 10, day => 20, hour => 18, minute => 34, second => 55, nanosecond => 1_000_000, locale => 'en', time_zone => 'America/Chicago', ); my %tests = ( 'GGGGG' => 'A', 'GGGG' => 'Anno Domini', 'GGG' => 'AD', 'GG' => 'AD', 'G' => 'AD', 'yyyyy' => '01976', 'yyyy' => '1976', 'yyy' => '1976', 'yy' => '76', 'y' => '1976', 'uuuuuu' => '001976', 'uuuuu' => '01976', 'uuuu' => '1976', 'uuu' => '1976', 'uu' => '1976', 'u' => '1976', 'YYYYY' => '01976', 'YYYY' => '1976', 'YYY' => '1976', 'YY' => '1976', 'Y' => '1976', 'QQQQ' => '4th quarter', 'QQQ' => 'Q4', 'QQ' => '04', 'Q' => '4', 'qqqq' => '4th quarter', 'qqq' => 'Q4', 'qq' => '04', 'q' => '4', 'MMMMM' => 'O', 'MMMM' => 'October', 'MMM' => 'Oct', 'MM' => '10', 'M' => '10', 'LLLLL' => 'O', 'LLLL' => 'October', 'LLL' => 'Oct', 'LL' => '10', 'L' => '10', 'ww' => '43', 'w' => '43', 'W' => '3', 'dd' => '20', 'd' => '20', 'DDD' => '294', 'DD' => '294', 'D' => '294', 'F' => '3', 'gggggg' => '043071', 'g' => '43071', 'EEEEE' => 'W', 'EEEE' => 'Wednesday', 'EEE' => 'Wed', 'EE' => 'Wed', 'E' => 'Wed', 'eeeee' => 'W', 'eeee' => 'Wednesday', 'eee' => 'Wed', 'ee' => '03', 'e' => '3', 'ccccc' => 'W', 'cccc' => 'Wednesday', 'ccc' => 'Wed', 'cc' => '03', 'c' => '3', 'a' => 'PM', 'hh' => '06', 'h' => '6', 'HH' => '18', 'H' => '18', 'KK' => '06', 'K' => '6', 'kk' => '18', 'j' => '6', 'jj' => '06', 'mm' => '34', 'm' => '34', 'ss' => '55', 's' => '55', 'SS' => '00', 'SSSSSS' => '001000', 'A' => '66895001', 'zzzz' => 'America/Chicago', 'zzz' => 'CDT', 'ZZZZ' => 'CDT-0500', 'ZZZ' => '-0500', 'vvvv' => 'America/Chicago', 'vvv' => 'CDT', 'VVVV' => 'America/Chicago', 'VVV' => 'CDT', 'ZZZZZ' => '-05:00', q{'one fine day'} => 'one fine day', q{'yy''yy' yyyy} => q{yy'yy 1976}, q{'yy''yy' 'hello' yyyy} => q{yy'yy hello 1976}, # Non-pattern text should pass through unchanged 'd日' => '20日', ); for my $k ( sort keys %tests ) { is( $dt->format_cldr($k), $tests{$k}, "format_cldr for $k" ); } } { my $dt = DateTime->new( year => 2008, month => 10, day => 20, hour => 18, minute => 34, second => 55, nanosecond => 1_000_000, locale => 'en', time_zone => 'America/Chicago', ); is( $dt->format_cldr('yy'), '08', 'format_cldr for yy in 2008 should be 08' ); } { my $dt = DateTime->new( year => 2008, month => 10, day => 20, hour => 18, minute => 34, second => 55, nanosecond => 1_000_000, locale => 'en_US', time_zone => 'America/Chicago', ); is( $dt->format_cldr('j'), '6', 'format_cldr for j in en_US should be 6 (at 18:34)' ); } { my $dt = DateTime->new( year => 2008, month => 10, day => 20, hour => 18, minute => 34, second => 55, nanosecond => 1_000_000, locale => 'fr', time_zone => 'America/Chicago', ); is( $dt->format_cldr('j'), '18', 'format_cldr for j in fr should be 18 (at 18:34)' ); } { my $dt = DateTime->new( year => 2009, month => 4, day => 13, locale => 'en_US', ); is( $dt->format_cldr('e'), '2', 'format_cldr for e in en_US should be 2 (for Monday, 2009-04-13)' ); is( $dt->format_cldr('c'), '1', 'format_cldr for c in en_US should be 1 (for Monday, 2009-04-13)' ); } { my $dt = DateTime->new( year => 2009, month => 4, day => 13, locale => 'fr_FR', ); is( $dt->format_cldr('e'), '1', 'format_cldr for e in fr_FR should be 1 (for Monday, 2009-04-13)' ); is( $dt->format_cldr('c'), '1', 'format_cldr for c in fr_FR should be 1 (for Monday, 2009-04-13)' ); } { my $dt = DateTime->new( year => -10 ); my %tests = ( 'y' => '-10', 'yy' => '-10', 'yyy' => '-10', 'yyyy' => '-010', 'yyyyy' => '-0010', 'u' => '-10', 'uu' => '-10', 'uuu' => '-10', 'uuuu' => '-010', 'uuuuu' => '-0010', ); for my $k ( sort keys %tests ) { is( $dt->format_cldr($k), $tests{$k}, "format_cldr for $k" ); } } { my $dt = DateTime->new( year => -1976 ); my %tests = ( 'y' => '-1976', 'yy' => '-76', 'yyy' => '-1976', 'yyyy' => '-1976', 'yyyyy' => '-1976', 'u' => '-1976', 'uu' => '-1976', 'uuu' => '-1976', 'uuuu' => '-1976', 'uuuuu' => '-1976', ); for my $k ( sort keys %tests ) { is( $dt->format_cldr($k), $tests{$k}, "format_cldr for $k" ); } } { my $dt = DateTime->new( year => 1976, month => 10, day => 20, hour => 18, minute => 34, second => 55, nanosecond => 999_999_999, locale => 'en', time_zone => 'UTC', ); is( $dt->format_cldr('ss,SSS'), '55,999', 'milliseconds are rounded down', ); } done_testing(); DateTime-1.46/xt/author/pp-38local-subtract.t0000644000175000017500000004624613240151623020642 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; # These tests should be the final word on dt subtraction involving a # DST-changing time zone { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, time_zone => 'America/Chicago', ); my $dur1 = $dt2->subtract_datetime($dt1); my %deltas1 = $dur1->deltas; is( $deltas1{months}, 6, 'delta_months is 6' ); is( $deltas1{days}, 0, 'delta_days is 0' ); is( $deltas1{minutes}, 0, 'delta_minutes is 0' ); is( $deltas1{seconds}, 0, 'delta_seconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur1), $dt2 ), 0, 'subtract_datetime is reversible from start point' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur1), $dt1 ), 0, 'subtract_datetime is reversible from end point' ); is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' ); my $dur2 = $dt1->subtract_datetime($dt2); my %deltas2 = $dur2->deltas; is( $deltas2{months}, -6, 'delta_months is -6' ); is( $deltas2{days}, 0, 'delta_days is 0' ); is( $deltas2{minutes}, 0, 'delta_minutes is 0' ); is( $deltas2{seconds}, 0, 'delta_seconds is 0' ); is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' ); my $dur3 = $dt2->delta_md($dt1); my %deltas3 = $dur3->deltas; is( $deltas3{months}, 6, 'delta_months is 6' ); is( $deltas3{days}, 0, 'delta_days is 0' ); is( $deltas3{minutes}, 0, 'delta_minutes is 0' ); is( $deltas3{seconds}, 0, 'delta_seconds is 0' ); is( $deltas3{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur3), $dt2 ), 0, 'delta_md is reversible from start point' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur3), $dt1 ), 0, 'delta_md is reversible from end point' ); my $dur4 = $dt2->delta_days($dt1); my %deltas4 = $dur4->deltas; is( $deltas4{months}, 0, 'delta_months is 0' ); is( $deltas4{days}, 184, 'delta_days is 184' ); is( $deltas4{minutes}, 0, 'delta_minutes is 0' ); is( $deltas4{seconds}, 0, 'delta_seconds is 0' ); is( $deltas4{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur3), $dt2 ), 0, 'delta_days is reversible from start point' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur4), $dt1 ), 0, 'delta_days is reversible from end point' ); } # same as above, but now the UTC hour of the earlier datetime is # _greater_ than that of the later one. this checks that overflows # are handled correctly. { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, hour => 18, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, hour => 18, time_zone => 'America/Chicago', ); my $dur1 = $dt2->subtract_datetime($dt1); my %deltas1 = $dur1->deltas; is( $deltas1{months}, 6, 'delta_months is 6' ); is( $deltas1{days}, 0, 'delta_days is 0' ); is( $deltas1{minutes}, 0, 'delta_minutes is 0' ); is( $deltas1{seconds}, 0, 'delta_seconds is 0' ); is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' ); } # make sure delta_md and delta_days work in the face of DST change # where we lose an hour { my $dt1 = DateTime->new( year => 2003, month => 11, day => 6, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2004, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dur1 = $dt2->delta_md($dt1); my %deltas1 = $dur1->deltas; is( $deltas1{months}, 6, 'delta_months is 6' ); is( $deltas1{days}, 0, 'delta_days is 0' ); is( $deltas1{minutes}, 0, 'delta_minutes is 0' ); is( $deltas1{seconds}, 0, 'delta_seconds is 0' ); is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' ); my $dur2 = $dt2->delta_days($dt1); my %deltas2 = $dur2->deltas; is( $deltas2{months}, 0, 'delta_months is 0' ); is( $deltas2{days}, 182, 'delta_days is 182' ); is( $deltas2{minutes}, 0, 'delta_minutes is 0' ); is( $deltas2{seconds}, 0, 'delta_seconds is 0' ); is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' ); } # the docs say use UTC to guarantee reversibility { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, time_zone => 'America/Chicago', ); $dt1->set_time_zone('UTC'); $dt2->set_time_zone('UTC'); my $dur = $dt2->subtract_datetime($dt1); is( DateTime->compare( $dt1->add_duration($dur), $dt2 ), 0, 'subtraction is reversible from start point with UTC' ); is( DateTime->compare( $dt2->subtract_duration($dur), $dt2 ), 0, 'subtraction is reversible from start point with UTC' ); } # The important thing here is that after a subtraction, we can use the # duration to get from one date to the other, regardless of the type # of subtraction done. { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, time_zone => 'America/Chicago', ); my $dur1 = $dt2->subtract_datetime_absolute($dt1); my %deltas1 = $dur1->deltas; is( $deltas1{months}, 0, 'delta_months is 0' ); is( $deltas1{days}, 0, 'delta_days is 0' ); is( $deltas1{minutes}, 0, 'delta_minutes is 0' ); is( $deltas1{seconds}, 15901200, 'delta_seconds is 15901200' ); is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur1), $dt2 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur1), $dt1 ), 0, 'subtraction is doubly reversible' ); my $dur2 = $dt1->subtract_datetime_absolute($dt2); my %deltas2 = $dur2->deltas; is( $deltas2{months}, 0, 'delta_months is 0' ); is( $deltas2{days}, 0, 'delta_days is 0' ); is( $deltas2{minutes}, 0, 'delta_minutes is 0' ); is( $deltas2{seconds}, -15901200, 'delta_seconds is -15901200' ); is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt2->clone->add_duration($dur2), $dt1 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt1->clone->subtract_duration($dur2), $dt2 ), 0, 'subtraction is doubly reversible' ); } { my $dt1 = DateTime->new( year => 2003, month => 4, day => 6, hour => 1, minute => 58, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 4, day => 6, hour => 3, minute => 1, time_zone => 'America/Chicago', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, 'delta_months is 0' ); is( $deltas{days}, 0, 'delta_days is 0' ); is( $deltas{minutes}, 3, 'delta_minutes is 3' ); is( $deltas{seconds}, 0, 'delta_seconds is 0' ); is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, 'subtraction is doubly reversible' ); } { my $dt1 = DateTime->new( year => 2003, month => 4, day => 5, hour => 1, minute => 58, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 4, day => 6, hour => 3, minute => 1, time_zone => 'America/Chicago', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, 'delta_months is 0' ); is( $deltas{days}, 1, 'delta_days is 1' ); is( $deltas{minutes}, 3, 'delta_minutes is 3' ); is( $deltas{seconds}, 0, 'delta_seconds is 0' ); is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'dt1 + dur = dt2' ); # this are two examples from the docs is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1->clone->add( hours => 1 ) ), 0, 'dt2 - dur != dt1 (not reversible)' ); is( DateTime->compare( $dt2->clone->subtract_duration( $dur->clock_duration ) ->subtract_duration( $dur->calendar_duration ), $dt1 ), 0, 'dt2 - dur->clock - dur->cal = dt1 (reversible when componentized)' ); my $dur2 = $dt1->subtract_datetime($dt2); my %deltas2 = $dur2->deltas; is( $deltas2{months}, 0, 'delta_months is 0' ); is( $deltas2{days}, -1, 'delta_days is 1' ); is( $deltas2{minutes}, -3, 'delta_minutes is 3' ); is( $deltas2{seconds}, 0, 'delta_seconds is 0' ); is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( $dt2->clone->add_duration($dur2)->datetime, '2003-04-05T02:58:00', 'dt2 + dur2 != dt1' ); is( DateTime->compare( $dt2->clone->add_duration( $dur2->clock_duration ) ->add_duration( $dur2->calendar_duration ), $dt1 ), 0, 'dt2 + dur2->clock + dur2->cal = dt1' ); is( DateTime->compare( $dt1->clone->subtract_duration($dur2), $dt2 ), 0, 'dt1 - dur2 = dt2' ); } # These tests makes sure that days with DST changes are "normal" when # they're the smaller operand { my $dt1 = DateTime->new( year => 2003, month => 4, day => 6, hour => 3, minute => 1, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 4, day => 7, hour => 3, minute => 2, time_zone => 'America/Chicago', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, 'delta_months is 0' ); is( $deltas{days}, 1, 'delta_days is 1' ); is( $deltas{minutes}, 1, 'delta_minutes is 1' ); is( $deltas{seconds}, 0, 'delta_seconds is 0' ); is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' ); my $dur2 = $dt1->subtract_datetime($dt2); my %deltas2 = $dur2->deltas; is( $deltas2{months}, 0, 'delta_months is 0' ); is( $deltas2{days}, -1, 'delta_days is -1' ); is( $deltas2{minutes}, -1, 'delta_minutes is -1' ); is( $deltas2{seconds}, 0, 'delta_seconds is 0' ); is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' ); } { my $dt1 = DateTime->new( year => 2003, month => 4, day => 5, hour => 1, minute => 58, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 4, day => 7, hour => 2, minute => 1, time_zone => 'America/Chicago', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, 'delta_months is 0' ); is( $deltas{days}, 2, 'delta_days is 2' ); is( $deltas{minutes}, 3, 'delta_minutes is 3' ); is( $deltas{seconds}, 0, 'delta_seconds is 0' ); is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, 'subtraction is doubly reversible' ); } # from example in docs { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, time_zone => 'America/Chicago', ); $dt1->set_time_zone('floating'); $dt2->set_time_zone('floating'); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 6, 'delta_months is 6' ); is( $deltas{days}, 0, 'delta_days is 0' ); is( $deltas{minutes}, 0, 'delta_minutes is 0' ); is( $deltas{seconds}, 0, 'delta_seconds is 0' ); is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'subtraction is reversible from start point' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, 'subtraction is reversible from end point' ); } { my $dt1 = DateTime->new( year => 2005, month => 8, time_zone => 'Europe/London', ); my $dt2 = DateTime->new( year => 2005, month => 11, time_zone => 'Europe/London', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 3, '3 months between two local times over DST change' ); is( $deltas{days}, 0, '0 days between two local times over DST change' ); is( $deltas{minutes}, 0, '0 minutes between two local times over DST change' ); } # same as previous but without hours overflow { my $dt1 = DateTime->new( year => 2005, month => 8, hour => 12, time_zone => 'Europe/London', ); my $dt2 = DateTime->new( year => 2005, month => 11, hour => 12, time_zone => 'Europe/London', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 3, '3 months between two local times over DST change' ); is( $deltas{days}, 0, '0 days between two local times over DST change' ); is( $deltas{minutes}, 0, '0 minutes between two local times over DST change' ); } # another docs example { my $dt2 = DateTime->new( year => 2003, month => 10, day => 26, hour => 1, time_zone => 'America/Chicago', ); my $dt1 = $dt2->clone->subtract( hours => 1 ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, '0 months between two local times over DST change' ); is( $deltas{days}, 0, '0 days between two local times over DST change' ); is( $deltas{minutes}, 60, '60 minutes between two local times over DST change' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, 'subtraction is doubly reversible' ); } { my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/New_York', ); my $dt2 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/Chicago', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, '0 months between two local times over DST change' ); is( $deltas{days}, 0, '0 days between two local times over DST change' ); is( $deltas{minutes}, 60, '60 minutes between two local times over DST change' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, 'subtraction is reversible' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, 'subtraction is doubly reversible' ); } # Fix a bug that occurred when the local time zone had DST and the two # datetime objects were on the same day { my $dt1 = DateTime->new( year => 2005, month => 4, day => 3, hour => 7, minute => 0, time_zone => 'America/New_York' ); my $dt2 = DateTime->new( year => 2005, month => 4, day => 3, hour => 8, minute => 0, time_zone => 'America/New_York' ); my $dur = $dt2->subtract_datetime($dt1); my ( $minutes, $seconds ) = $dur->in_units( 'minutes', 'seconds' ); is( $minutes, 60, 'subtraction of two dates on a DST change date, minutes == 60' ); is( $seconds, 0, 'subtraction of two dates on a DST change date, seconds == 0' ); $dur = $dt1->subtract_datetime($dt1); ok( $dur->is_zero, 'dst change date (no dst) - itself, duration is zero' ); } { my $dt1 = DateTime->new( year => 2005, month => 4, day => 3, hour => 1, minute => 0, time_zone => 'America/New_York' ); my $dur = $dt1->subtract_datetime($dt1); ok( $dur->is_zero, 'dst change date (with dst) - itself, duration is zero' ); } # This tests a bug where one of the datetimes is changing DST, and the # other is not. In this case, no "adjustments" (aka hacks) are made in # subtract_datetime, and it just gives the "UTC difference". { # This is UTC-4 my $dt1 = DateTime->new( year => 2009, month => 3, day => 9, time_zone => 'America/New_York' ); # This is UTC+8 my $dt2 = DateTime->new( year => 2009, month => 3, day => 9, time_zone => 'Asia/Hong_Kong' ); my $dur = $dt1->subtract_datetime($dt2); is( $dur->delta_minutes, 720, 'subtraction the day after a DST change in one zone, where the other datetime is in a different zone' ); } { # This is UTC-5 my $dt1 = DateTime->new( year => 2009, month => 3, day => 8, hour => 1, time_zone => 'America/New_York' ); # This is UTC+8 my $dt2 = DateTime->new( year => 2009, month => 3, day => 8, hour => 1, time_zone => 'Asia/Hong_Kong' ); my $dur = $dt1->subtract_datetime($dt2); is( $dur->delta_minutes, 780, 'subtraction the day of a DST change in one zone (before the change),' . ' where the other datetime is in a different zone' ); } { # This is UTC-4 my $dt1 = DateTime->new( year => 2009, month => 3, day => 8, hour => 4, time_zone => 'America/New_York' ); # This is UTC+8 my $dt2 = DateTime->new( year => 2009, month => 3, day => 8, hour => 4, time_zone => 'Asia/Hong_Kong' ); my $dur = $dt1->subtract_datetime($dt2); is( $dur->delta_minutes, 720, 'subtraction the day of a DST change in one zone (after the change),' . ' where the other datetime is in a different zone' ); } done_testing(); DateTime-1.46/xt/author/pp-06add.t0000644000175000017500000003003013240151623016426 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use Test::Fatal; use DateTime; { my $dt = DateTime->new( year => 1996, month => 11, day => 22, hour => 18, minute => 30, second => 20, time_zone => 'UTC', ); $dt->add( weeks => 8 ); is( $dt->year, 1997, 'year rollover' ); is( $dt->month, 1, 'month set on year rollover' ); is( $dt->datetime, '1997-01-17T18:30:20', 'okay on year rollover' ); $dt->add( weeks => 2 ); is( $dt->datetime, '1997-01-31T18:30:20', 'Adding weeks' ); $dt->add( seconds => 15 ); is( $dt->datetime, '1997-01-31T18:30:35', 'Adding seconds' ); $dt->add( minutes => 12 ); is( $dt->datetime, '1997-01-31T18:42:35', 'Adding minutes' ); $dt->add( minutes => 25, hours => 3, seconds => 7 ); is( $dt->datetime, '1997-01-31T22:07:42', 'Adding h,m,s' ); } { # Now, test the adding of durations my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( minutes => 1, seconds => 12 ); is( $dt->datetime, '1986-01-28T16:39:12', 'Adding durations with minutes and seconds works' ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( seconds => 30 ); is( $dt->datetime, '1986-01-28T16:38:30', 'Adding durations with seconds only works' ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( hours => 1, minutes => 10 ); is( $dt->datetime, '1986-01-28T17:48:00', 'Adding durations with hours and minutes works' ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( days => 3 ); is( $dt->datetime, '1986-01-31T16:38:00', 'Adding durations with days only works' ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( days => 3, hours => 2 ); is( $dt->datetime, '1986-01-31T18:38:00', 'Adding durations with days and hours works' ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( days => 3, hours => 2, minutes => 20, seconds => 15 ); is( $dt->datetime, '1986-01-31T18:58:15', 'Adding durations with days, hours, minutes, and seconds works' ); } { # Add 15M - this test failed at one point in N::I::Time my $dt = DateTime->new( year => 2001, month => 4, day => 5, hour => 16, time_zone => 'UTC' ); $dt->add( minutes => 15 ); is( $dt->datetime, '2001-04-05T16:15:00', 'Adding minutes to an ical string' ); # Subtract a duration $dt->add( minutes => -15 ); is( $dt->datetime, '2001-04-05T16:00:00', 'Back where we started' ); } { # Syntactic sugar works as well my $dt = DateTime->new( year => 2016, month => 11, day => 11, hour => 17, time_zone => 'UTC' ); my $duration = DateTime::Duration->new( years => 1 ); $dt->add($duration); is( $dt->datetime, '2017-11-11T17:00:00', 'Adding a Duration object via ->add works', ); $duration = DateTime::Duration->new( months => 5, days => 1 ); $dt->subtract($duration); is( $dt->datetime, '2017-06-10T17:00:00', 'Subtracting a Duration object via ->subtract works', ); } { my $dt = DateTime->new( year => 1986, month => 1, day => 28, hour => 16, minute => 38, time_zone => 'UTC' ); $dt->add( seconds => 60 ); is( $dt->datetime, '1986-01-28T16:39:00', 'adding positive seconds with seconds works' ); $dt->add( seconds => -120 ); is( $dt->datetime, '1986-01-28T16:37:00', 'adding negative seconds with seconds works' ); } { # test sub months my $dt = DateTime->new( year => 2001, month => 1, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-02-01', 'february 1st' ); } { my $dt = DateTime->new( year => 2001, month => 2, day => 28, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-03-01', 'march 1st' ); } { my $dt = DateTime->new( year => 2001, month => 3, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-04-01', 'april 1st' ); } { my $dt = DateTime->new( year => 2001, month => 4, day => 30, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-05-01', 'may 1st' ); } { my $dt = DateTime->new( year => 2001, month => 5, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-06-01', 'june 1st' ); } { my $dt = DateTime->new( year => 2001, month => 6, day => 30, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-07-01', 'july 1st' ); } { my $dt = DateTime->new( year => 2001, month => 7, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-08-01', 'august 1st' ); } { my $dt = DateTime->new( year => 2001, month => 8, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-09-01', 'september 1st' ); } { my $dt = DateTime->new( year => 2001, month => 9, day => 30, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-10-01', 'october 1st' ); } { my $dt = DateTime->new( year => 2001, month => 10, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-11-01', 'november 1st' ); } { my $dt = DateTime->new( year => 2001, month => 11, day => 30, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2001-12-01', 'december 1st' ); } { my $dt = DateTime->new( year => 2001, month => 12, day => 31, time_zone => 'UTC', ); $dt->add( days => 1 ); is( $dt->date, '2002-01-01', 'january 1st' ); } { # Before leap day, not a leap year ... my $dt = DateTime->new( year => 2001, month => 2, day => 28, time_zone => 'UTC', ); $dt->add( years => 1 ); is( $dt->date, '2002-02-28', 'Adding a year' ); $dt->add( years => 17 ); is( $dt->date, '2019-02-28', 'Adding 17 years' ); } { # After leap day, not a leap year ... my $dt = DateTime->new( year => 2001, month => 3, day => 28, time_zone => 'UTC', ); $dt->add( years => 1 ); is( $dt->date, '2002-03-28', 'Adding a year' ); $dt->add( years => 17 ); is( $dt->date, '2019-03-28', 'Adding 17 years' ); } { # On leap day, in a leap year ... my $dt = DateTime->new( year => 2000, month => 2, day => 29, time_zone => 'UTC', ); $dt->add( years => 1 ); is( $dt->date, '2001-03-01', 'Adding a year' ); $dt->add( years => 17 ); is( $dt->date, '2018-03-01', 'Adding 17 years' ); } { # Before leap day, in a leap year ... my $dt = DateTime->new( year => 2000, month => 2, day => 28, time_zone => 'UTC', ); $dt->add( years => 1 ); is( $dt->date, '2001-02-28', 'Adding a year' ); $dt->add( years => 17 ); is( $dt->date, '2018-02-28', 'Adding 17 years' ); } { # After leap day, in a leap year ... my $dt = DateTime->new( year => 2000, month => 3, day => 28, time_zone => 'UTC', ); $dt->add( years => 1 ); is( $dt->date, '2001-03-28', 'Adding a year' ); $dt->add( years => 17 ); is( $dt->date, '2018-03-28', 'Adding 17 years' ); } { # Test a bunch of years, before leap day for ( 1 .. 99 ) { my $dt = DateTime->new( year => 2000, month => 2, day => 28, time_zone => 'UTC', ); $dt->add( years => $_ ); my $x = sprintf '%02d', $_; is( $dt->date, "20${x}-02-28", "Adding $_ years" ); } # Test a bunch of years, after leap day for ( 1 .. 99 ) { my $dt = DateTime->new( year => 2000, month => 3, day => 28, time_zone => 'UTC', ); $dt->add( years => $_ ); my $x = sprintf '%02d', $_; is( $dt->date, "20${x}-03-28", "Adding $_ years" ); } } # And more of the same, starting on a non-leap year { # Test a bunch of years, before leap day for ( 1 .. 97 ) { my $dt = DateTime->new( year => 2002, month => 2, day => 28, time_zone => 'UTC', ); $dt->add( years => $_ ); my $x = sprintf '%02d', $_ + 2; is( $dt->date, "20${x}-02-28", "Adding $_ years" ); } # Test a bunch of years, after leap day for ( 1 .. 97 ) { my $dt = DateTime->new( year => 2002, month => 3, day => 28, time_zone => 'UTC', ); $dt->add( years => $_ ); my $x = sprintf '%02d', $_ + 2; is( $dt->date, "20${x}-03-28", "Adding $_ years" ); } } { # subtract years for ( 1 .. 97 ) { my $dt = DateTime->new( year => 1999, month => 3, day => 1, time_zone => 'UTC', ); $dt->add( years => -$_ ); my $x = sprintf '%02d', 99 - $_; is( $dt->date, "19${x}-03-01", "Subtracting $_ years" ); } } # test some old bugs { # bug adding months where current month + months added were > 25 my $dt = DateTime->new( year => 1997, month => 12, day => 1, time_zone => 'UTC', ); $dt->add( months => 14 ); is( $dt->date, '1999-02-01', 'Adding months--rollover year' ); } { # bug subtracting months with year rollover my $dt = DateTime->new( year => 1997, month => 1, day => 1, time_zone => 'UTC', ); $dt->add( months => -1 ); is( $dt->date, '1996-12-01', 'Subtracting months--rollover year' ); my $new = $dt + DateTime::Duration->new( years => 2 ); is( $new->date, '1998-12-01', 'test + overloading' ); } { my $dt = DateTime->new( year => 1997, month => 1, day => 1, hour => 1, minute => 1, second => 59, nanosecond => 500000000, time_zone => 'UTC', ); $dt->add( nanoseconds => 500000000 ); is( $dt->second, 0, 'fractional second rollover' ); $dt->add( nanoseconds => 123000000 ); is( $dt->fractional_second, 0.123, 'as fractional_second' ); } { my $dt = DateTime->new( year => 2003, month => 2, day => 28 ); $dt->add( months => 1, days => 1 ); is( $dt->ymd, '2003-04-01', 'order of units in date math' ); } { my $dt = DateTime->new( year => 2003, hour => 12, minute => 1 ); $dt->add( minutes => 30, seconds => -1 ); is( $dt->hour, 12, 'hour is 12' ); is( $dt->minute, 30, 'minute is 30' ); is( $dt->second, 59, 'second is 59' ); } { my $dt = DateTime->new( year => 2014, month => 7, day => 1, time_zone => 'floating', ); $dt->add( days => 2 ); is( $dt->date, '2014-07-03', 'adding 2 days to a floating datetime' ); } { my $dt = DateTime->new( year => 0, month => 1, day => 1 ); my $dt2; is( exception { $dt2 = $dt->clone->add( days => 268_526_345 ) }, undef, 'no exception adding 268,526,345 days to 0000-01-01' ); if ($dt2) { is( $dt2->ymd(), '735200-02-29', 'adding 268,526,345 days produces 735200-02-29' ); } } done_testing(); DateTime-1.46/xt/author/pp-31formatter.t0000644000175000017500000000447713240151623017717 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; { package Formatter; sub new { return bless {}, __PACKAGE__; } sub format_datetime { $_[1]->strftime('%Y%m%d %T'); } } my $formatter = Formatter->new(); { is( exception { DateTime->from_epoch( epoch => time(), formatter => $formatter ) }, undef, 'passed formatter to from_epoch' ); } { is( exception { DateTime->new( year => 2004, month => 9, day => 2, hour => 13, minute => 23, second => 34, formatter => $formatter ); }, undef, 'passed formatter to new' ); } { my $from = DateTime->new( year => 2004, month => 9, day => 2, hour => 13, minute => 23, second => 34, formatter => $formatter ); my $dt; is( exception { $dt = DateTime->from_object( object => $from, formatter => $formatter ); }, undef, 'passed formatter to from_object' ); is( $dt->formatter, $formatter, 'check from_object copies formatter' ); is( $dt->stringify(), '20040902 13:23:34', 'Format datetime' ); # check stringification (with formatter) is( $dt->stringify, "$dt", 'Stringification (with formatter)' ); # check that set() and truncate() don't lose formatter $dt->set( hour => 3 ); is( $dt->stringify, '20040902 03:23:34', 'formatter is preserved after set()' ); $dt->truncate( to => 'minute' ); is( $dt->stringify, '20040902 03:23:00', 'formatter is preserved after truncate()' ); # check if the default behavior works $dt->set_formatter(undef); is( $dt->stringify(), $dt->iso8601, 'Default iso8601 works' ); # check stringification (default) is( $dt->stringify, "$dt", 'Stringification (no formatter -> format_datetime)' ); is( $dt->iso8601, "$dt", 'Stringification (no formatter -> iso8601)' ); } done_testing(); DateTime-1.46/xt/author/pp-10subtract.t0000644000175000017500000003402513240151623017530 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 4, minute => 3, second => 2, nanosecond => 12, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 6, day => 12, hour => 5, minute => 7, second => 23, nanosecond => 7, time_zone => 'UTC' ); my $dur = $date2 - $date1; is( $dur->delta_months, 1, 'delta_months should be 1' ); is( $dur->delta_days, 2, 'delta_days should be 2' ); is( $dur->delta_minutes, 64, 'delta_minutes should be 64' ); is( $dur->delta_seconds, 20, 'delta_seconds should be 20' ); is( $dur->delta_nanoseconds, 999_999_995, 'delta_nanoseconds should be 999,999,995' ); is( $dur->years, 0, 'Years' ); is( $dur->months, 1, 'Months' ); is( $dur->weeks, 0, 'Weeks' ); is( $dur->days, 2, 'Days' ); is( $dur->hours, 1, 'Hours' ); is( $dur->minutes, 4, 'Minutes' ); is( $dur->seconds, 20, 'Seconds' ); is( $dur->nanoseconds, 999_999_995, 'Nanoseconds' ); } { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 4, minute => 3, second => 2, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 6, day => 12, hour => 5, minute => 7, second => 23, time_zone => 'UTC' ); my $dur = $date1 - $date2; is( $dur->delta_months, -1, 'delta_months should be -1' ); is( $dur->delta_days, -2, 'delta_days should be -2' ); is( $dur->delta_minutes, -64, 'delta_minutes should be 64' ); is( $dur->delta_seconds, -21, 'delta_seconds should be 20' ); is( $dur->delta_nanoseconds, 0, 'delta_nanoseconds should be 0' ); is( $dur->years, 0, 'Years' ); is( $dur->months, 1, 'Months' ); is( $dur->weeks, 0, 'Weeks' ); is( $dur->days, 2, 'Days' ); is( $dur->hours, 1, 'Hours' ); is( $dur->minutes, 4, 'Minutes' ); is( $dur->seconds, 21, 'Seconds' ); is( $dur->nanoseconds, 0, 'Nanoseconds' ); $dur = $date1 - $date1; is( $dur->delta_days, 0, 'date minus itself should have no delta days' ); is( $dur->delta_seconds, 0, 'date minus itself should have no delta seconds' ); my $new = $date1 - DateTime::Duration->new( years => 2 ); is( $new->datetime, '1999-05-10T04:03:02', 'test - overloading' ); } { my $d = DateTime->new( year => 2001, month => 10, day => 19, hour => 5, minute => 1, second => 1, time_zone => 'UTC' ); my $d2 = $d->clone; $d2->subtract( weeks => 1, days => 1, hours => 1, minutes => 1, seconds => 1, ); ok( defined $d2, 'Defined' ); is( $d2->datetime, '2001-10-11T04:00:00', 'Subtract and get the right thing' ); } # based on bug report from Eric Cholet { my $dt1 = DateTime->new( year => 2003, month => 2, day => 9, hour => 0, minute => 0, second => 1, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2003, month => 2, day => 7, hour => 23, minute => 59, second => 59, time_zone => 'UTC', ); my $dur1 = $dt1->subtract_datetime($dt2); is( $dur1->delta_days, 1, 'delta_days should be 1' ); is( $dur1->delta_seconds, 2, 'delta_seconds should be 2' ); my $dt3 = $dt2 + $dur1; is( DateTime->compare( $dt1, $dt3 ), 0, 'adding difference back to dt1 should give same datetime' ); my $dur2 = $dt2->subtract_datetime($dt1); is( $dur2->delta_days, -1, 'delta_days should be -1' ); is( $dur2->delta_seconds, -2, 'delta_seconds should be -2' ); my $dt4 = $dt1 + $dur2; is( DateTime->compare( $dt2, $dt4 ), 0, 'adding difference back to dt2 should give same datetime' ); } # test if the day changes because of a nanosecond subtract { my $dt = DateTime->new( year => 2001, month => 6, day => 12, hour => 0, minute => 0, second => 0, time_zone => 'UTC' ); $dt->subtract( nanoseconds => 1 ); is( $dt->nanosecond, 999999999, 'negative nanoseconds normalize ok' ); is( $dt->second, 59, 'seconds normalize ok' ); is( $dt->minute, 59, 'minutes normalize ok' ); is( $dt->hour, 23, 'hours normalize ok' ); is( $dt->day, 11, 'days normalize ok' ); } # test for a bug when nanoseconds were greater in earlier datetime { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 1, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2000, month => 1, day => 6, hour => 0, minute => 10, second => 0, nanosecond => 0, time_zone => 'UTC', ); my $dur = $dt2 - $dt1; is( $dur->delta_days, 0, 'delta_days is 0' ); is( $dur->delta_minutes, 1439, 'delta_minutes is 1439' ); is( $dur->delta_seconds, 59, 'delta_seconds is 59' ); is( $dur->delta_nanoseconds, 999_999_999, 'delta_nanoseconds is 999,999,999' ); ok( $dur->is_positive, 'duration is positive' ); } { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 20, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 10, time_zone => 'UTC', ); my $dur = $dt2 - $dt1; is( $dur->delta_days, 0, 'days is 0' ); is( $dur->delta_seconds, 0, 'seconds is 0' ); is( $dur->delta_nanoseconds, -10, 'nanoseconds is -10' ); ok( $dur->is_negative, 'duration is negative' ); } { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 11, second => 0, nanosecond => 20, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 10, time_zone => 'UTC', ); my $dur = $dt2 - $dt1; is( $dur->delta_days, 0, 'delta_days is 0' ); is( $dur->delta_minutes, -1, 'delta_minutes is -1' ); is( $dur->delta_seconds, 0, 'delta_seconds is 0' ); is( $dur->delta_nanoseconds, -10, 'nanoseconds is -10' ); ok( $dur->is_negative, 'duration is negative' ); } { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 20, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 11, second => 0, nanosecond => 10, time_zone => 'UTC', ); my $dur = $dt2 - $dt1; is( $dur->delta_days, 0, 'days is 0' ); is( $dur->delta_seconds, 59, 'seconds is 59' ); is( $dur->delta_nanoseconds, 999_999_990, 'nanoseconds is 999,999,990' ); ok( $dur->is_positive, 'duration is positive' ); } { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 11, second => 0, nanosecond => 10, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 10, second => 0, nanosecond => 20, time_zone => 'UTC', ); my $dur = $dt2 - $dt1; is( $dur->delta_days, 0, 'days is 0' ); is( $dur->delta_seconds, -59, 'seconds is -59' ); is( $dur->delta_nanoseconds, -999_999_990, 'nanoseconds is -999,999,990' ); ok( $dur->is_negative, 'duration is negative' ); } { my $dt1 = DateTime->new( year => 2000, month => 1, day => 5, hour => 0, minute => 11, second => 0, nanosecond => 20, time_zone => 'UTC', ); my $dur = $dt1 - $dt1; is( $dur->delta_days, 0, 'days is 0' ); is( $dur->delta_seconds, 0, 'seconds is 0' ); is( $dur->delta_nanoseconds, 0, 'nanoseconds is 0' ); ok( !$dur->is_positive, 'not positive' ); ok( !$dur->is_negative, 'not negative' ); } { my $dt1 = DateTime->new( year => 2003, month => 12, day => 31 ); my $dt2 = $dt1->clone->subtract( months => 1 ); is( $dt2->year, 2003, '2003-12-31 - 1 month = 2003-11-30' ); is( $dt2->month, 11, '2003-12-31 - 1 month = 2003-11-30' ); is( $dt2->day, 30, '2003-12-31 - 1 month = 2003-11-30' ); } { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 4, minute => 3, second => 2, nanosecond => 12, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 6, day => 12, hour => 5, minute => 7, second => 23, nanosecond => 7, time_zone => 'UTC' ); my $dur = $date2->subtract_datetime_absolute($date1); is( $dur->delta_months, 0, 'delta_months is 0' ); is( $dur->delta_minutes, 0, 'delta_minutes is 0' ); is( $dur->delta_seconds, 2_855_060, 'delta_seconds is 2,855,060' ); is( $dur->delta_nanoseconds, 999_999_995, 'delta_seconds is 999,999,995' ); } { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 4, minute => 3, second => 2, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 6, day => 12, hour => 5, minute => 7, second => 23, time_zone => 'UTC' ); my $dur = $date1->subtract_datetime_absolute($date2); is( $dur->delta_months, 0, 'delta_months is 0' ); is( $dur->delta_minutes, 0, 'delta_minutes is 0' ); is( $dur->delta_seconds, -2_855_061, 'delta_seconds is -2,855,061' ); is( $dur->delta_nanoseconds, 0, 'delta_nanoseconds is 0' ); } { my $date1 = DateTime->new( year => 2003, month => 9, day => 30 ); my $date2 = DateTime->new( year => 2003, month => 10, day => 1 ); my $date3 = DateTime->new( year => 2003, month => 10, day => 31 ); my $date4 = DateTime->new( year => 2003, month => 11, day => 1 ); my $date5 = DateTime->new( year => 2003, month => 2, day => 28 ); my $date6 = DateTime->new( year => 2003, month => 3, day => 1 ); my $date7 = DateTime->new( year => 2003, month => 1, day => 31 ); my $date8 = DateTime->new( year => 2003, month => 2, day => 1 ); foreach my $p ( [ $date1, $date2 ], [ $date3, $date4 ], [ $date5, $date6 ], [ $date7, $date8 ], ) { my $pos_diff = $p->[1]->subtract_datetime( $p->[0] ); is( $pos_diff->delta_days, 1, '1 day diff at end of month' ); is( $pos_diff->delta_months, 0, '0 month diff at end of month' ); my $neg_diff = $p->[0]->subtract_datetime( $p->[1] ); is( $neg_diff->delta_days, -1, '-1 day diff at end of month' ); is( $neg_diff->delta_months, 0, '0 month diff at end of month' ); } } { my $dt1 = DateTime->new( year => 2005, month => 6, day => 11, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2005, month => 11, day => 10, time_zone => 'UTC', ); my $dur = $dt2->subtract_datetime($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 4, '4 months - smaller day > bigger day' ); is( $deltas{days}, 29, '29 days - smaller day > bigger day' ); is( $deltas{minutes}, 0, '0 minutes - smaller day > bigger day' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, '$dt1 + $dur == $dt2' ); # XXX - this does not work, nor will it ever work # is( $dt2->clone->subtract_duration($dur), $dt1, '$dt2 - $dur == $dt1' ); } { my $dt1 = DateTime->new( year => 2005, month => 6, day => 11, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 2005, month => 11, day => 10, time_zone => 'UTC', ); my $dur = $dt2->delta_days($dt1); my %deltas = $dur->deltas; is( $deltas{months}, 0, '30 months - smaller day > bigger day' ); is( $deltas{days}, 152, '152 days - smaller day > bigger day' ); is( $deltas{minutes}, 0, '0 minutes - smaller day > bigger day' ); is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0, '$dt1 + $dur == $dt2' ); is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0, '$dt2 - $dur == $dt1' ); } { my $dt = DateTime->new( year => 2012, month => 6, day => 30, time_zone => 'floating', ); my $default = $dt->clone()->subtract( months => 1 ); is( $default->format_cldr('yyyy-MM-dd'), '2012-05-31', 'default subtract uses preserve end_of_month mode' ); my $with_mode = $dt->clone()->subtract( months => 1, end_of_month => 'limit', ); is( $with_mode->format_cldr('yyyy-MM-dd'), '2012-05-30', 'set end_of_month mode to limit in call to subtract()' ); } { my $dt = DateTime->new( year => 2014, month => 7, day => 3, time_zone => 'floating', ); $dt->subtract( days => 2 ); is( $dt->date, '2014-07-01', 'subtracting 2 days from a floating datetime' ); } done_testing(); DateTime-1.46/xt/author/pp-47default-time-zone.t0000644000175000017500000000547513240151623021253 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 2000, month => 2, day => 21 ); is( $dt->time_zone->name, 'floating', 'Time zones for new DateTime objects should default to floating' ); is( DateTime->last_day_of_month( year => 2000, month => 2 ) ->time_zone->name, 'floating', 'last_day_of_month time zone also should default to floating' ); is( DateTime->from_day_of_year( year => 2000, day_of_year => 212 ) ->time_zone->name, 'floating', 'from_day_of_year time zone also should default to floating' ); is( DateTime->now->time_zone->name, 'UTC', '... except for constructors which assume UTC' ); is( DateTime->from_epoch( epoch => time() )->time_zone->name, 'UTC', '... except for constructors which assume UTC' ); } { my $dt1 = DateTime->new( year => 1970, hour => 1, nanosecond => 100 ); my $dt2 = DateTime->from_object( object => $dt1 ); is( $dt2->time_zone->name, 'floating', 'Copying DateTime objects from other DateTime objects should retain the timezone' ); } { my $dt = DateTime->new( year => 2000, month => 2, day => 21 ); local $ENV{PERL_DATETIME_DEFAULT_TZ} = 'America/Los_Angeles'; is( $dt->time_zone->name, 'floating', 'Setting PERL_DATETIME_DEFAULT_TZ env should not impact existing objects' ); $dt = DateTime->new( year => 2000, month => 2, day => 21 ); is( $dt->time_zone->name, $ENV{PERL_DATETIME_DEFAULT_TZ}, '... but new objects should no longer default to the floating time zone' ); is( DateTime->last_day_of_month( year => 2000, month => 2 ) ->time_zone->name, $ENV{PERL_DATETIME_DEFAULT_TZ}, 'last_day_of_month time zone also should default to floating' ); is( DateTime->from_day_of_year( year => 2000, day_of_year => 212 ) ->time_zone->name, $ENV{PERL_DATETIME_DEFAULT_TZ}, 'from_day_of_year time zone also should default to floating' ); is( DateTime->now->time_zone->name, 'UTC', '... and constructors which assume UTC should remain unchanged' ); my $dt1 = DateTime->new( year => 1970, hour => 1, nanosecond => 100 ); my $dt2 = DateTime->from_object( object => $dt1 ); is( $dt2->time_zone->name, $ENV{PERL_DATETIME_DEFAULT_TZ}, 'Copying DateTime objects from other DateTime objects should retain the timezone' ); } { my $dt = DateTime->new( year => 2000, month => 2, day => 21 ); is( $dt->time_zone->name, 'floating', 'Default time zone should revert to "floating" when PERL_DATETIME_DEFAULT_TZ no longer set' ); } done_testing(); DateTime-1.46/xt/author/pp-12week.t0000644000175000017500000000301013240151623016624 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; my @tests = ( [ [ 1964, 12, 31 ], [ 1964, 53 ] ], [ [ 1965, 1, 1 ], [ 1964, 53 ] ], [ [ 1971, 9, 7 ], [ 1971, 36 ] ], [ [ 1971, 10, 25 ], [ 1971, 43 ] ], [ [ 1995, 1, 1 ], [ 1994, 52 ] ], [ [ 1995, 11, 18 ], [ 1995, 46 ] ], [ [ 1995, 12, 31 ], [ 1995, 52 ] ], [ [ 1996, 12, 31 ], [ 1997, 1 ] ], [ [ 2001, 4, 28 ], [ 2001, 17 ] ], [ [ 2001, 8, 2 ], [ 2001, 31 ] ], [ [ 2001, 9, 11 ], [ 2001, 37 ] ], [ [ 2002, 12, 25 ], [ 2002, 52 ] ], [ [ 2002, 12, 31 ], [ 2003, 1 ] ], [ [ 2003, 1, 1 ], [ 2003, 1 ] ], [ [ 2003, 12, 31 ], [ 2004, 1 ] ], [ [ 2004, 1, 1 ], [ 2004, 1 ] ], [ [ 2004, 12, 31 ], [ 2004, 53 ] ], [ [ 2005, 1, 1 ], [ 2004, 53 ] ], [ [ 2005, 12, 31 ], [ 2005, 52 ] ], [ [ 2006, 1, 1 ], [ 2005, 52 ] ], [ [ 2006, 12, 31 ], [ 2006, 52 ] ], [ [ 2007, 1, 1 ], [ 2007, 1 ] ], [ [ 2007, 12, 31 ], [ 2008, 1 ] ], [ [ 2008, 1, 1 ], [ 2008, 1 ] ], [ [ 2008, 12, 31 ], [ 2009, 1 ] ], [ [ 2009, 1, 1 ], [ 2009, 1 ] ], ); foreach my $test (@tests) { my @args = @{ $test->[0] }; my @results = @{ $test->[1] }; my $dt = DateTime->new( year => $args[0], month => $args[1], day => $args[2], time_zone => 'UTC', ); my ( $year, $week ) = $dt->week(); is( "$year-W$week", "$results[0]-W$results[1]", 'week for ' . $dt->ymd ); } done_testing(); DateTime-1.46/xt/author/pp-24from-object.t0000644000175000017500000000444713240151623020122 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } ## no critic (Modules::ProhibitMultiplePackages) use strict; use warnings; use Test::More; use DateTime; my $dt1 = DateTime->new( year => 1970, hour => 1, nanosecond => 100 ); my $dt2 = DateTime->from_object( object => $dt1 ); is( $dt1->year, 1970, 'year is 1970' ); is( $dt1->hour, 1, 'hour is 1' ); is( $dt1->nanosecond, 100, 'nanosecond is 100' ); { my $t1 = DateTime::Calendar::_Test::WithoutTZ->new( rd_days => 1, rd_secs => 0 ); # Tests creating objects from other calendars (without time zones) my $t2 = DateTime->from_object( object => $t1 ); isa_ok( $t2, 'DateTime' ); is( $t2->datetime, '0001-01-01T00:00:00', 'convert from object without tz' ); ok( $t2->time_zone->is_floating, 'time_zone is floating' ); } { my $tz = DateTime::TimeZone->new( name => 'America/Chicago' ); my $t1 = DateTime::Calendar::_Test::WithTZ->new( rd_days => 1, rd_secs => 0, time_zone => $tz ); # Tests creating objects from other calendars (with time zones) my $t2 = DateTime->from_object( object => $t1 ); isa_ok( $t2, 'DateTime' ); is( $t2->time_zone->name, 'America/Chicago', 'time_zone is preserved' ); } { my $tz = DateTime::TimeZone->new( name => 'UTC' ); my $t1 = DateTime::Calendar::_Test::WithTZ->new( rd_days => 720258, rd_secs => 86400, time_zone => $tz ); my $t2 = DateTime->from_object( object => $t1 ); isa_ok( $t2, 'DateTime' ); is( $t2->second, 60, 'new DateTime from_object with TZ which is a leap second' ); } { for my $class (qw( DateTime::Infinite::Past DateTime::Infinite::Future )) { isa_ok( DateTime->from_object( object => $class->new ), $class, "from_object($class)" ); } } done_testing(); # Set up two simple test packages package DateTime::Calendar::_Test::WithoutTZ; sub new { my $class = shift; bless {@_}, $class; } sub utc_rd_values { return $_[0]{rd_days}, $_[0]{rd_secs}, 0; } package DateTime::Calendar::_Test::WithTZ; sub new { my $class = shift; bless {@_}, $class; } sub utc_rd_values { return $_[0]{rd_days}, $_[0]{rd_secs}, 0; } sub time_zone { return $_[0]{time_zone}; } DateTime-1.46/xt/author/pp-16truncate.t0000644000175000017500000002045013240151623017531 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } ## no critic (Modules::ProhibitExcessMainComplexity) use strict; use warnings; use Test::Fatal; use Test::More 0.88; use DateTime; use Try::Tiny; my %vals = ( year => 50, month => 3, day => 15, hour => 10, minute => 55, second => 17, nanosecond => 1234, ); { my $dt = DateTime->new(%vals); $dt->truncate( to => 'second' ); foreach my $f (qw( year month day hour minute second )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new(%vals); $dt->truncate( to => 'minute' ); foreach my $f (qw( year month day hour minute )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( second nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new(%vals); $dt->truncate( to => 'hour' ); foreach my $f (qw( year month day hour )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( minute second nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new(%vals); $dt->truncate( to => 'day' ); foreach my $f (qw( year month day )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( hour minute second nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new(%vals); $dt->truncate( to => 'month' ); foreach my $f (qw( year month )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( day )) { is( $dt->$f(), 1, "$f should be 1" ); } foreach my $f (qw( hour minute second nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new(%vals); $dt->truncate( to => 'year' ); foreach my $f (qw( year )) { is( $dt->$f(), $vals{$f}, "$f should be $vals{$f}" ); } foreach my $f (qw( month day )) { is( $dt->$f(), 1, "$f should be 1" ); } foreach my $f (qw( hour minute second nanosecond )) { is( $dt->$f(), 0, "$f should be 0" ); } } { my $dt = DateTime->new( year => 2003, month => 11, day => 17 ); for ( 1 .. 6 ) { my $trunc = $dt->clone->add( days => $_ )->truncate( to => 'week' ); is( $trunc->day, 17, 'truncate to week should always truncate to monday of week' ); } { my $trunc = $dt->clone->add( days => 7 )->truncate( to => 'week' ); is( $trunc->day, 24, 'truncate to week should always truncate to monday of week' ); } } { my $dt = DateTime->new( year => 2003, month => 10, day => 2 ) ->truncate( to => 'week' ); is( $dt->year, 2003, 'truncation to week across month boundary' ); is( $dt->month, 9, 'truncation to week across month boundary' ); is( $dt->day, 29, 'truncation to week across month boundary' ); } { my $dt = DateTime->new( year => 2013, month => 12, day => 16, locale => 'fr_FR' ); for ( 1 .. 6 ) { my $trunc = $dt->clone->add( days => $_ )->truncate( to => 'local_week' ); is( $trunc->day, 16, 'truncate to local_week returns correct date - locale start is Monday' ); } { my $trunc = $dt->clone->add( days => 7 )->truncate( to => 'local_week' ); is( $trunc->day, 23, 'truncate to local_week returns correct date - locale start is Monday' ); } } { my $dt = DateTime->new( year => 2013, month => 11, day => 2, locale => 'fr_FR' )->truncate( to => 'local_week' ); is( $dt->year, 2013, 'truncation to local_week across month boundary - locale start is Monday' ); is( $dt->month, 10, 'truncation to local_week across month boundary - locale start is Monday' ); is( $dt->day, 28, 'truncation to local_week across month boundary - locale start is Monday' ); } { my $dt = DateTime->new( year => 2013, month => 12, day => 15, locale => 'en_US' ); for ( 1 .. 6 ) { my $trunc = $dt->clone->add( days => $_ )->truncate( to => 'local_week' ); is( $trunc->day, 15, 'truncate to local_week returns correct date - locale start is Sunday' ); } { my $trunc = $dt->clone->add( days => 7 )->truncate( to => 'local_week' ); is( $trunc->day, 22, 'truncate to local_week returns correct date - locale start is Sunday' ); } } { my $dt = DateTime->new( year => 2013, month => 11, day => 2, locale => 'en_US' )->truncate( to => 'local_week' ); is( $dt->year, 2013, 'truncation to local_week across month boundary - locale start is Sunday' ); is( $dt->month, 10, 'truncation to local_week across month boundary - locale start is Sunday' ); is( $dt->day, 27, 'truncation to local_week across month boundary - locale start is Sunday' ); } { my %months_to_quarter = ( 1 => 1, 2 => 1, 3 => 1, 4 => 4, 5 => 4, 6 => 4, 7 => 7, 8 => 7, 9 => 7, 10 => 10, 11 => 10, 12 => 10, ); for my $year ( -1, 100, 2016 ) { for my $month ( sort keys %months_to_quarter ) { for my $day ( 1, 15, 27 ) { my $dt = DateTime->new( year => $year, month => $month, day => $day, ); subtest( 'truncate to quarter - ' . $dt->ymd, sub { $dt->truncate( to => 'quarter' ); is( $dt->year, $year, 'year is unchanged' ); is( $dt->month, $months_to_quarter{$month}, "month $month becomes month $months_to_quarter{$month}" ); is( $dt->day, 1, 'day is always 1' ); is( $dt->hour, 0, 'hour is always 0' ); is( $dt->minute, 0, 'minute is always 0' ); is( $dt->second, 0, 'second is always 0' ); is( $dt->nanosecond, 0, 'nanosecond is always 0' ); } ); } } } } { my $dt = DateTime->new(%vals); for my $bad (qw( seconds minutes year_foo month_bar )) { like( exception { $dt->truncate( to => $bad ) }, qr/Validation failed for type named TruncationLevel/, "bad truncate parameter ($bad) throws an error" ); } } { my $dt = DateTime->new( year => 2010, month => 3, day => 25, hour => 1, minute => 5, time_zone => 'Asia/Tehran', ); is( $dt->day_of_week(), 4, 'day of week is Thursday' ); my $error; try { $dt->truncate( to => 'week' ); } catch { $error = $_; }; like( $error, qr/Invalid local time for date/, 'truncate operation threw an error because of an invalid local datetime' ); is( $dt->day_of_week(), 4, 'day of week does not change after failed truncate() call' ); } done_testing(); DateTime-1.46/xt/author/pp-20infinite.t0000644000175000017500000001135213240151623017505 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; use DateTime::Locale; my $pos = DateTime::Infinite::Future->new; my $neg = DateTime::Infinite::Past->new; my $posinf = DateTime::INFINITY; my $neginf = DateTime::NEG_INFINITY; my $nan_string = DateTime::NAN; # infinite date math { ok( $pos->is_infinite, 'positive infinity should be infinite' ); ok( $neg->is_infinite, 'negative infinity should be infinite' ); ok( !$pos->is_finite, 'positive infinity should not be finite' ); ok( !$neg->is_finite, 'negative infinity should not be finite' ); # These methods produce numbers or strings - we want to make sure they all # return Inf or -Inf as expected. my @ification_methods = qw( ymd mdy dmy hms time iso8601 datetime year ce_year month day day_of_week quarter hour hour_1 hour_12 hour_12_0 minute second fractional_second week week_year week_number mjd jd nanosecond millisecond microsecond epoch ); for my $meth (@ification_methods) { is( $pos->$meth, $posinf, "+Infinity $meth returns $posinf" ); is( $neg->$meth, $neginf, "-Infinity $meth returns $neginf" ); } # that's a long time ago! my $long_ago = DateTime->new( year => -100_000 ); ok( $neg < $long_ago, 'negative infinity is really negative' ); my $far_future = DateTime->new( year => 100_000 ); ok( $pos > $far_future, 'positive infinity is really positive' ); ok( $pos > $neg, 'positive infinity is bigger than negative infinity' ); my $pos_dur = $pos - $far_future; ok( $pos_dur->is_positive, 'infinity - normal = infinity' ); my $pos2 = $long_ago + $pos_dur; ok( $pos2 == $pos, 'normal + infinite duration = infinity' ); my $neg_dur = $far_future - $pos; ok( $neg_dur->is_negative, 'normal - infinity = neg infinity' ); my $neg2 = $long_ago + $neg_dur; ok( $neg2 == $neg, 'normal + neg infinite duration = neg infinity' ); my $dur = $pos - $pos; my %deltas = $dur->deltas; my @compare = qw( days seconds nanoseconds ); foreach (@compare) { # NaN != NaN (but should stringify the same) is( $deltas{$_} . q{}, $nan_string, "infinity - infinity = nan ($_)" ); } my $new_pos = $pos->clone->add( days => 10 ); ok( $new_pos == $pos, 'infinity + normal duration = infinity' ); my $new_pos2 = $pos->clone->subtract( days => 10 ); ok( $new_pos2 == $pos, 'infinity - normal duration = infinity' ); ok( $pos == $posinf, 'infinity (datetime) == infinity (number)' ); ok( $neg == $neginf, 'neg infinity (datetime) == neg infinity (number)' ); } # This could vary across platforms my $pos_as_string = $posinf . q{}; my $neg_as_string = $neginf . q{}; # formatting { foreach my $m ( qw( year month day hour minute second microsecond millisecond nanosecond ) ) { is( $pos->$m() . q{}, $pos_as_string, "pos $m is $pos_as_string" ); is( $neg->$m() . q{}, $neg_as_string, "neg $m is $pos_as_string" ); } } { my $now = DateTime->now; is( DateTime->compare( $pos, $now ), 1, 'positive infinite is greater than now' ); is( DateTime->compare( $neg, $now ), -1, 'negative infinite is less than now' ); } { my $now = DateTime->now; my $pos2 = $pos + DateTime::Duration->new( months => 1 ); ok( $pos == $pos2, 'infinity (datetime) == infinity (datetime)' ); } { my $now = DateTime->now; my $neg2 = $neg + DateTime::Duration->new( months => 1 ); ok( $neg == $neg2, '-infinity (datetime) == -infinity (datetime)' ); } { cmp_ok( "$pos", 'eq', $posinf, 'stringified infinity (datetime) eq infinity (number)' ); cmp_ok( "$neg", 'eq', $neginf, 'stringified neg infinity (datetime) eq neg infinity (number)' ); } { is( $pos->day_name(), undef, 'day_name returns undef', ); is( $pos->am_or_pm(), undef, 'am_or_pm returns undef' ); is( $pos->locale()->name(), 'Fake locale for Infinite DateTime objects', 'locale name for fake locale' ); is( $pos->locale()->datetime_format_long(), DateTime::Locale->load('en_US')->datetime_format_long(), 'fake locale returns same format as en_US' ); } done_testing(); DateTime-1.46/xt/author/eol.t0000644000175000017500000000320113240151623015672 0ustar autarchautarchuse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::EOL 0.19 use Test::More 0.88; use Test::EOL; my @files = ( 'lib/DateTime.pm', 'lib/DateTime/Conflicts.pm', 'lib/DateTime/Duration.pm', 'lib/DateTime/Helpers.pm', 'lib/DateTime/Infinite.pm', 'lib/DateTime/LeapSecond.pm', 'lib/DateTime/PP.pm', 'lib/DateTime/PPExtra.pm', 'lib/DateTime/Types.pm', 't/00-report-prereqs.dd', 't/00-report-prereqs.t', 't/00load.t', 't/01sanity.t', 't/02last-day.t', 't/03components.t', 't/04epoch.t', 't/05set.t', 't/06add.t', 't/07compare.t', 't/09greg.t', 't/10subtract.t', 't/11duration.t', 't/12week.t', 't/13strftime.t', 't/14locale.t', 't/15jd.t', 't/16truncate.t', 't/17set-return.t', 't/18today.t', 't/19leap-second.t', 't/20infinite.t', 't/21bad-params.t', 't/22from-doy.t', 't/23storable.t', 't/24from-object.t', 't/25add-subtract.t', 't/26dt-leapsecond-pm.t', 't/27delta.t', 't/28dow.t', 't/29overload.t', 't/30future-tz.t', 't/31formatter.t', 't/32leap-second2.t', 't/33seconds-offset.t', 't/34set-tz.t', 't/35rd-values.t', 't/36invalid-local.t', 't/37local-add.t', 't/38local-subtract.t', 't/39no-so.t', 't/40leap-years.t', 't/41cldr-format.t', 't/42duration-class.t', 't/43new-params.t', 't/44set-formatter.t', 't/45core-time.t', 't/46warnings.t', 't/47default-time-zone.t', 't/48rt-115983.t', 't/zzz-check-breaks.t' ); eol_unix_ok($_, { trailing_whitespace => 1 }) foreach @files; done_testing; DateTime-1.46/xt/author/test-all-my-deps.t0000644000175000017500000000117713240151623020226 0ustar autarchautarchuse strict; use warnings; use Cwd qw( abs_path ); use Test::More; BEGIN { plan skip_all => 'Must set DATETIME_TEST_DEPS to true in order to run these tests' unless $ENV{DATETIME_TEST_DEPS}; } use Test::DependentModules qw( test_all_dependents ); local $ENV{PERL_TEST_DM_LOG_DIR} = abs_path('.'); my $exclude = $ENV{DATETIME_TEST_DEPS} eq 'all' ? qr/(?:^App-) | ^(?: Archive-RPM | Video-Xine )$ /x : qr/^(?!DateTime-)/; test_all_dependents( 'DateTime', { exclude => $exclude } ); DateTime-1.46/xt/author/pp-07compare.t0000644000175000017500000001415313240151623017335 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; my $date1 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); # make sure that comparing to itself eq 0 my $identity = $date1->compare($date2); ok( $identity == 0, 'Identity comparison' ); $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 1, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 second diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 1, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 minute diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 13, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 hour diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 25, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 day diff' ); $date2 = DateTime->new( year => 1997, month => 11, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 month diff' ); $date2 = DateTime->new( year => 1998, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == -1, 'Comparison $a < $b, 1 year diff' ); # $a > $b tests $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 11, minute => 59, second => 59, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 second diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 11, minute => 59, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 minute diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 11, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 hour diff' ); $date2 = DateTime->new( year => 1997, month => 10, day => 23, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 day diff' ); $date2 = DateTime->new( year => 1997, month => 9, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 month diff' ); $date2 = DateTime->new( year => 1996, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'UTC' ); ok( $date1->compare($date2) == 1, 'Comparison $a > $b, 1 year diff' ); my $infinity = DateTime::INFINITY; ok( $date1->compare($infinity) == -1, 'Comparison $a < inf' ); ok( $date1->compare( -$infinity ) == 1, 'Comparison $a > -inf' ); # comparison overloading, and infinity ok( ( $date1 <=> $infinity ) == -1, 'Comparison overload $a <=> inf' ); ok( ( $infinity <=> $date1 ) == 1, 'Comparison overload $inf <=> $a' ); # comparison with floating time { my $dt1 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'America/Chicago' ); my $dt2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, time_zone => 'floating' ); is( DateTime->compare( $dt1, $dt2 ), 0, 'Comparison with floating time (cmp)' ); is( ( $dt1 <=> $dt2 ), 0, 'Comparison with floating time (<=>)' ); is( ( $dt1 cmp $dt2 ), 0, 'Comparison with floating time (cmp)' ); is( DateTime->compare_ignore_floating( $dt1, $dt2 ), 1, 'Comparison with floating time (cmp)' ); } # sub-second { my $dt1 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, nanosecond => 100, ); my $dt2 = DateTime->new( year => 1997, month => 10, day => 24, hour => 12, minute => 0, second => 0, nanosecond => 200, ); is( DateTime->compare( $dt1, $dt2 ), -1, 'Comparison with floating time (cmp)' ); is( ( $dt1 <=> $dt2 ), -1, 'Comparison with floating time (<=>)' ); is( ( $dt1 cmp $dt2 ), -1, 'Comparison with floating time (cmp)' ); } { my $dt1 = DateTime->new( year => 2000, month => 10, day => 24, hour => 12, minute => 0, second => 0, nanosecond => 10000, ); my $dt2 = DateTime->new( year => 2000, month => 10, day => 24, hour => 12, minute => 0, second => 0, nanosecond => 10000, ); is( DateTime->compare( $dt1, $dt2 ), 0, 'Comparison with floating time (cmp)' ); is( ( $dt1 <=> $dt2 ), 0, 'Comparison with floating time (<=>)' ); is( ( $dt1 cmp $dt2 ), 0, 'Comparison with floating time (cmp)' ); is( DateTime->compare_ignore_floating( $dt1, $dt2 ), 0, 'Comparison with compare_ignore_floating (cmp)' ); } { package DT::Test; sub new { my $class = shift; return bless [@_], $class; } sub utc_rd_values { @{ $_[0] } } } { my $dt = DateTime->new( year => 1950 ); my @values = $dt->utc_rd_values; $values[2] += 50; my $dt_test1 = DT::Test->new(@values); ok( $dt < $dt_test1, 'comparison works across different classes' ); $values[0] -= 1; my $dt_test2 = DT::Test->new(@values); ok( $dt > $dt_test2, 'comparison works across different classes' ); } done_testing(); DateTime-1.46/xt/author/test-version.t0000644000175000017500000000063713240151623017567 0ustar autarchautarchuse strict; use warnings; use Test::More; # generated by Dist::Zilla::Plugin::Test::Version 1.09 use Test::Version; my @imports = qw( version_all_ok ); my $params = { is_strict => 1, has_version => 1, multiple => 0, }; push @imports, $params if version->parse( $Test::Version::VERSION ) >= version->parse('1.002'); Test::Version->import(@imports); version_all_ok; done_testing; DateTime-1.46/xt/author/xs-is-loaded.t0000644000175000017500000000031213240151623017404 0ustar autarchautarchuse strict; use warnings; use Test::More; use DateTime; ## no critic (Variables::ProhibitPackageVars) ok( !$DateTime::IsPurePerl, 'XS implementation is loaded by default' ); done_testing(); DateTime-1.46/xt/author/pp-28dow.t0000644000175000017500000000305213240151623016477 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 0 ); is( $dt->year, 0, 'year is 0' ); is( $dt->month, 1, 'month is 1' ); is( $dt->day, 1, 'day is 1' ); is( $dt->day_of_week, 6, 'day of week is 6' ); } { my $dt = DateTime->new( year => 0, month => 12, day => 31 ); is( $dt->year, 0, 'year is 0' ); is( $dt->month, 12, 'month is 12' ); is( $dt->day, 31, 'day is 31' ); is( $dt->day_of_week, 7, 'day of week is 7' ); } { my $dt = DateTime->new( year => -1 ); is( $dt->year, -1, 'year is -1' ); is( $dt->month, 1, 'month is 1' ); is( $dt->day, 1, 'day is 1' ); is( $dt->day_of_week, 5, 'day of week is 5' ); } { my $dt = DateTime->new( year => 1 ); is( $dt->year, 1, 'year is 1' ); is( $dt->month, 1, 'month is 1' ); is( $dt->day, 1, 'day is 1' ); is( $dt->day_of_week, 1, 'day of week is 1' ); } { my $dow = 1; for my $year ( 1, 0, -1 ) { my $days_in_year = $year ? 365 : 366; for my $doy ( reverse 1 .. $days_in_year ) { is( DateTime->from_day_of_year( year => $year, day_of_year => $doy, )->day_of_week, $dow, "day of week for day $doy of year $year is $dow" ); $dow--; $dow = 7 if $dow == 0; } } } done_testing(); DateTime-1.46/xt/author/pp-27delta.t0000644000175000017500000000745613240151623017012 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 4, minute => 3, second => 2, nanosecond => 12, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 6, day => 12, hour => 5, minute => 7, second => 23, nanosecond => 7, time_zone => 'UTC' ); { my $dur_md = $date2->delta_md($date1); is( $dur_md->delta_months, 1, 'delta_md months is 1' ); is( $dur_md->delta_days, 2, 'delta_md days is 2' ); is( $dur_md->delta_minutes, 0, 'delta_md minutes is 0' ); is( $dur_md->delta_seconds, 0, 'delta_md seconds is 0' ); is( $dur_md->delta_nanoseconds, 0, 'delta_md nanoseconds is 0' ); my $dur_d = $date2->delta_days($date1); is( $dur_d->delta_months, 0, 'delta_d months is 0' ); is( $dur_d->delta_days, 33, 'delta_d days is 33' ); is( $dur_d->delta_minutes, 0, 'delta_d minutes is 0' ); is( $dur_d->delta_seconds, 0, 'delta_d seconds is 0' ); is( $dur_d->delta_nanoseconds, 0, 'delta_d nanoseconds is 0' ); my $dur_ms = $date2->delta_ms($date1); is( $dur_ms->delta_months, 0, 'delta_ms months is 0' ); is( $dur_ms->delta_days, 0, 'delta_ms days is 0' ); is( $dur_ms->delta_minutes, 47584, 'delta_ms minutes is 47584' ); is( $dur_ms->delta_seconds, 20, 'delta_ms seconds is 20' ); is( $dur_ms->delta_nanoseconds, 0, 'delta_ms nanoseconds is 0' ); is( $dur_ms->hours, 793, 'hours is 793' ); } { my $dur_md = $date1->delta_md($date2); is( $dur_md->delta_months, 1, 'delta_md months is 1' ); is( $dur_md->delta_days, 2, 'delta_md days is 2' ); is( $dur_md->delta_minutes, 0, 'delta_md minutes is 0' ); is( $dur_md->delta_seconds, 0, 'delta_md seconds is 0' ); is( $dur_md->delta_nanoseconds, 0, 'delta_md nanoseconds is 0' ); my $dur_d = $date1->delta_days($date2); is( $dur_d->delta_months, 0, 'delta_d months is 0' ); is( $dur_d->delta_days, 33, 'delta_d days is 33' ); is( $dur_d->delta_minutes, 0, 'delta_d minutes is 0' ); is( $dur_d->delta_seconds, 0, 'delta_d seconds is 0' ); is( $dur_d->delta_nanoseconds, 0, 'delta_d nanoseconds is 0' ); my $dur_ms = $date1->delta_ms($date2); is( $dur_ms->delta_months, 0, 'delta_ms months is 0' ); is( $dur_ms->delta_days, 0, 'delta_ms days is 0' ); is( $dur_ms->delta_minutes, 47584, 'delta_ms minutes is 47584' ); is( $dur_ms->delta_seconds, 20, 'delta_ms seconds is 20' ); is( $dur_ms->delta_nanoseconds, 0, 'delta_ms nanoseconds is 0' ); is( $dur_ms->hours, 793, 'hours is 793' ); } } { my $date1 = DateTime->new( year => 2001, month => 5, day => 10, hour => 15, minute => 0, second => 0, time_zone => 'UTC' ); my $date2 = DateTime->new( year => 2001, month => 5, day => 11, hour => 12, minute => 30, second => 10, time_zone => 'UTC' ); my $dur_ms = $date1->delta_ms($date2); is( $dur_ms->delta_months, 0, 'delta_ms months is 0' ); is( $dur_ms->delta_days, 0, 'delta_ms days is 0' ); is( $dur_ms->delta_minutes, 1290, 'delta_ms minutes is 1290' ); is( $dur_ms->delta_seconds, 10, 'delta_ms seconds is 30' ); is( $dur_ms->delta_nanoseconds, 0, 'delta_ms nanoseconds is 0' ); is( $dur_ms->hours, 21, 'hours is 21' ); } done_testing(); DateTime-1.46/xt/author/pp-21bad-params.t0000644000175000017500000000403413240151623017707 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; foreach my $p ( { year => 2000, month => 13 }, { year => 2000, month => 0 }, { year => 2000, month => 12, day => 32 }, { year => 2000, month => 12, day => 0 }, { year => 2000, month => 12, day => 10, hour => -1 }, { year => 2000, month => 12, day => 10, hour => 24 }, { year => 2000, month => 12, day => 10, hour => 12, minute => -1 }, { year => 2000, month => 12, day => 10, hour => 12, minute => 60 }, { year => 2000, month => 12, day => 10, hour => 12, second => -1 }, { year => 2000, month => 12, day => 10, hour => 12, second => 62 }, ) { like( exception { DateTime->new(%$p) }, qr/Validation failed/, 'Parameters outside valid range should fail in call to new()' ); like( exception { DateTime->new( year => 2000 )->set(%$p) }, qr/Validation failed/, 'Parameters outside valid range should fail in call to set()' ); } { like( exception { DateTime->last_day_of_month( year => 2000, month => 13, ); }, qr/Validation failed/, 'Parameters outside valid range should fail in call to last_day_of_month()' ); like( exception { DateTime->last_day_of_month( year => 2000, month => 0 ) }, qr/Validation failed/, 'Parameters outside valid range should fail in call to last_day_of_month()' ); } { like( exception { DateTime->new( year => 2000, month => 4, day => 31 ) }, qr/valid day of month/i, 'Day past last day of month should fail' ); like( exception { DateTime->new( year => 2001, month => 2, day => 29 ) }, qr/valid day of month/i, 'Day past last day of month should fail' ); is( exception { DateTime->new( year => 2000, month => 2, day => 29 ) }, undef, 'February 29 should be valid in leap years' ); } done_testing(); DateTime-1.46/xt/author/portability.t0000644000175000017500000000026713240151623017466 0ustar autarchautarchuse strict; use warnings; use Test::More; eval 'use Test::Portability::Files'; plan skip_all => 'Test::Portability::Files required for testing portability' if $@; run_tests(); DateTime-1.46/xt/author/no-tabs.t0000644000175000017500000000314713240151623016467 0ustar autarchautarchuse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.15 use Test::More 0.88; use Test::NoTabs; my @files = ( 'lib/DateTime.pm', 'lib/DateTime/Conflicts.pm', 'lib/DateTime/Duration.pm', 'lib/DateTime/Helpers.pm', 'lib/DateTime/Infinite.pm', 'lib/DateTime/LeapSecond.pm', 'lib/DateTime/PP.pm', 'lib/DateTime/PPExtra.pm', 'lib/DateTime/Types.pm', 't/00-report-prereqs.dd', 't/00-report-prereqs.t', 't/00load.t', 't/01sanity.t', 't/02last-day.t', 't/03components.t', 't/04epoch.t', 't/05set.t', 't/06add.t', 't/07compare.t', 't/09greg.t', 't/10subtract.t', 't/11duration.t', 't/12week.t', 't/13strftime.t', 't/14locale.t', 't/15jd.t', 't/16truncate.t', 't/17set-return.t', 't/18today.t', 't/19leap-second.t', 't/20infinite.t', 't/21bad-params.t', 't/22from-doy.t', 't/23storable.t', 't/24from-object.t', 't/25add-subtract.t', 't/26dt-leapsecond-pm.t', 't/27delta.t', 't/28dow.t', 't/29overload.t', 't/30future-tz.t', 't/31formatter.t', 't/32leap-second2.t', 't/33seconds-offset.t', 't/34set-tz.t', 't/35rd-values.t', 't/36invalid-local.t', 't/37local-add.t', 't/38local-subtract.t', 't/39no-so.t', 't/40leap-years.t', 't/41cldr-format.t', 't/42duration-class.t', 't/43new-params.t', 't/44set-formatter.t', 't/45core-time.t', 't/46warnings.t', 't/47default-time-zone.t', 't/48rt-115983.t', 't/zzz-check-breaks.t' ); notabs_ok($_) foreach @files; done_testing; DateTime-1.46/xt/author/pod-coverage.t0000644000175000017500000000422113240151623017471 0ustar autarchautarch#!perl # This file was automatically generated by Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable 0.07. use Test::Pod::Coverage 1.08; use Test::More 0.88; BEGIN { if ( $] <= 5.008008 ) { plan skip_all => 'These tests require Pod::Coverage::TrustPod, which only works with Perl 5.8.9+'; } } use Pod::Coverage::TrustPod; my %skip = map { $_ => 1 } qw( DateTime::Conflicts DateTime::Helpers DateTime::PP DateTime::PPExtra ); my @modules; for my $module ( all_modules() ) { next if $skip{$module}; push @modules, $module; } plan skip_all => 'All the modules we found were excluded from POD coverage test.' unless @modules; plan tests => scalar @modules; my %trustme = ( 'DateTime' => [ qr/^[A-Z_]+$/, qr/0$/, qr/^STORABLE/, qr/^utc_year$/, qr/^timegm$/, qr/^day_of_month$/, qr/^doq$/, qr/^dow$/, qr/^doy$/, qr/^iso8601$/, qr/^local_rd_as_seconds$/, qr/^mday$/, qr/^min$/, qr/^mon$/, qr/^sec$/, qr/^wday$/, qr/^DefaultLanguage$/, qr/^era$/, qr/^language$/ ], 'DateTime::Duration' => [ qr/^[A-Z_]+$/ ], 'DateTime::Infinite' => [ qr/^.+$/ ] ); my @also_private; for my $module ( sort @modules ) { pod_coverage_ok( $module, { coverage_class => 'Pod::Coverage::TrustPod', also_private => \@also_private, trustme => $trustme{$module} || [], }, "pod coverage for $module" ); } done_testing(); DateTime-1.46/xt/author/pp-02last-day.t0000644000175000017500000000232113240151623017412 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; my @last_day = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); my @leap_last_day = @last_day; $leap_last_day[1]++; foreach my $month ( 1 .. 12 ) { my $dt = DateTime->last_day_of_month( year => 2001, month => $month, time_zone => 'UTC', ); is( $dt->year, 2001, 'check year' ); is( $dt->month, $month, 'check month' ); is( $dt->day, $last_day[ $month - 1 ], 'check day' ); } foreach my $month ( 1 .. 12 ) { my $dt = DateTime->last_day_of_month( year => 2004, month => $month, time_zone => 'UTC', ); is( $dt->year, 2004, 'check year' ); is( $dt->month, $month, 'check month' ); is( $dt->day, $leap_last_day[ $month - 1 ], 'check day' ); } { is( exception { DateTime->last_day_of_month( year => 2000, month => 1, nanosecond => 2000 ); }, undef, 'last_day_of_month should accept nanosecond' ); } done_testing(); DateTime-1.46/xt/author/tidyall.t0000644000175000017500000000067413240151623016570 0ustar autarchautarch# This file was automatically generated by Dist::Zilla::Plugin::Test::TidyAll v$VERSION use Test::More 0.88; BEGIN { if ( $] < 5.010 ) { plan skip_all => 'This test requires Perl version 5.010'; } } use Test::Code::TidyAll 0.24; tidyall_ok( verbose => ( exists $ENV{TEST_TIDYALL_VERBOSE} ? $ENV{TEST_TIDYALL_VERBOSE} : 1 ), jobs => ( exists $ENV{TEST_TIDYALL_JOBS} ? $ENV{TEST_TIDYALL_JOBS} : 4 ), ); done_testing; DateTime-1.46/xt/author/pp-37local-add.t0000644000175000017500000001265213240151623017534 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; # These tests should be the final word on dt addition involving a # DST-changing time zone # time addition is "wait X amount of time, then what does the clock # say?" this means it acts on the UTC components. { my $dt = DateTime->new( year => 2003, month => 4, day => 6, time_zone => 'America/Chicago', ); $dt->add( hours => 1 ); is( $dt->datetime, '2003-04-06T01:00:00', 'add one hour to midnight, get 1 am' ); is( exception { $dt->add( hours => 1 ) }, undef, 'no error adding 1 hour just before DST leap forward' ); is( $dt->datetime, '2003-04-06T03:00:00', 'add one hour to 1 am, get 3 am' ); $dt->subtract( hours => 1 ); is( $dt->datetime, '2003-04-06T01:00:00', 'subtract one hour from 3 am, get 1 am' ); $dt->subtract( hours => 1 ); is( $dt->datetime, '2003-04-06T00:00:00', 'subtract one hour from 1 am, get midnight' ); } { my $dt = DateTime->new( year => 2003, month => 10, day => 26, time_zone => 'America/Chicago', ); $dt->add( hours => 1 ); is( $dt->datetime, '2003-10-26T01:00:00', 'add one hour to midnight, get 1 am' ); $dt->add( hours => 1 ); is( $dt->datetime, '2003-10-26T01:00:00', 'add one hour to 1 am, get 1 am (again)' ); $dt->add( hours => 1 ); is( $dt->datetime, '2003-10-26T02:00:00', 'add one hour to 1 am (2nd time), get 2 am' ); $dt->subtract( hours => 1 ); is( $dt->datetime, '2003-10-26T01:00:00', 'subtract 1 hour from 2 am, get 1 am' ); $dt->subtract( hours => 1 ); is( $dt->datetime, '2003-10-26T01:00:00', 'subtract 1 hour from 1 am, get 1 am (again)' ); $dt->subtract( hours => 1 ); is( $dt->datetime, '2003-10-26T00:00:00', 'subtract 1 hour from 1 am (2nd), get midnight' ); } # date addition is "leave the clock alone, just change the date # portion". this means it acts on local components { my $dt = DateTime->new( year => 2003, month => 4, day => 6, time_zone => 'America/Chicago', ); $dt->add( days => 1 ); is( $dt->datetime, '2003-04-07T00:00:00', 'add 1 day at midnight, same clock time' ); $dt->add( months => 7 ); is( $dt->datetime, '2003-11-07T00:00:00', 'add 7 months at midnight, same clock time' ); $dt->subtract( months => 7 ); is( $dt->datetime, '2003-04-07T00:00:00', 'subtract 7 months at midnight, same clock time' ); $dt->subtract( days => 1 ); is( $dt->datetime, '2003-04-06T00:00:00', 'subtract 1 day at midnight, same clock time' ); } { my $dt = DateTime->new( year => 2003, month => 10, day => 26, time_zone => 'America/Chicago', ); $dt->add( days => 1 ); is( $dt->datetime, '2003-10-27T00:00:00', 'add 1 day at midnight, get midnight' ); $dt->add( months => 7 ); is( $dt->datetime, '2004-05-27T00:00:00', 'add 7 months at midnight, get midnight' ); $dt->subtract( months => 7 ); is( $dt->datetime, '2003-10-27T00:00:00', 'subtract 7 months at midnight, get midnight' ); $dt->subtract( days => 1 ); is( $dt->datetime, '2003-10-26T00:00:00', 'subtract 1 day at midnight, get midnight' ); } # date and time addition in one call is still two separate operations. # First we do date, then time. { my $dt = DateTime->new( year => 2003, month => 4, day => 5, time_zone => 'America/Chicago', ); $dt->add( days => 1, hours => 2 ); is( $dt->datetime, '2003-04-06T03:00:00', 'add one day & 2 hours from midnight, get 3 am' ); # !!! - not reversible this way - needs some good docs my $dt1 = $dt->clone->subtract( days => 1, hours => 2 ); is( $dt1->datetime, '2003-04-05T01:00:00', 'subtract one day & 2 hours from 3 am, get 1 am' ); # is reversible this way - also needs docs my $dt2 = $dt->clone->subtract( hours => 2 )->subtract( days => 1 ); is( $dt2->datetime, '2003-04-05T00:00:00', 'subtract 2 hours and then one day from 3 am, get midnight' ); } { my $dt = DateTime->new( year => 2003, month => 10, day => 25, time_zone => 'America/Chicago', ); $dt->add( days => 1, hours => 2 ); is( $dt->datetime, '2003-10-26T01:00:00', 'add one day & 2 hours from midnight, get 1 am' ); my $dt1 = $dt->clone->subtract( days => 1, hours => 2 ); is( $dt1->datetime, '2003-10-24T23:00:00', 'add one day & 2 hours from midnight, get 11 pm' ); my $dt2 = $dt->clone->subtract( hours => 2 )->subtract( days => 1 ); is( $dt2->datetime, '2003-10-25T00:00:00', 'subtract 2 hours and then one day from 3 am, get midnight' ); } # an example from the docs { my $dt = DateTime->new( year => 2003, month => 4, day => 5, hour => 2, time_zone => 'America/Chicago', ); $dt->add( hours => 24 ); is( $dt->datetime, '2003-04-06T03:00:00', 'datetime after adding 24 hours is 2003-04-06T03:00:00' ); } done_testing(); DateTime-1.46/xt/author/pp-34set-tz.t0000644000175000017500000000507313240151623017136 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More 0.88; use DateTime; # These tests are for a bug related to a bad interaction between the # horrid ->_handle_offset_modifier method and calling ->set_time_zone # on a real Olson time zone. When _handle_offset_modifier was called # from set_time_zone, it tried calling ->_offset_for_local_datetime, # which was bogus, because at that point it doesn't know the local # date time any more, only UTC. # # The fix is to have ->_handle_offset_modifier call ->offset when it # knows that UTC is valid, which is determined by an arg to # ->_handle_offset_modifier # These tests come from one of the zdump-generated test files in # DT::TZ { my $dt = DateTime->new( year => 1922, month => 8, day => 31, hour => 23, minute => 59, second => 59, time_zone => 'UTC', ); $dt->set_time_zone('Africa/Accra'); is( $dt->year, 1922, 'local year should be 1922 (1922-08-31 23:59:59)' ); is( $dt->month, 8, 'local month should be 8 (1922-08-31 23:59:59)' ); is( $dt->day, 31, 'local day should be 31 (1922-08-31 23:59:59)' ); is( $dt->hour, 23, 'local hour should be 23 (1922-08-31 23:59:59)' ); is( $dt->minute, 59, 'local minute should be 59 (1922-08-31 23:59:59)' ); is( $dt->second, 59, 'local second should be 59 (1922-08-31 23:59:59)' ); is( $dt->is_dst, 0, 'is_dst should be 0 (1922-08-31 23:59:59)' ); is( $dt->offset, 0, 'offset should be 0 (1922-08-31 23:59:59)' ); is( $dt->time_zone_short_name, 'GMT', 'short name should be GMT (1922-08-31 23:59:59)' ); } { my $dt = DateTime->new( year => 2013, month => 3, day => 10, hour => 2, minute => 4, time_zone => 'floating', ); like( exception { $dt->set_time_zone('America/Los_Angeles') }, qr/\QInvalid local time for date in time zone/, 'got an exception when trying to set time zone when it leads to invalid local time' ); is( $dt->time_zone()->name(), 'floating', 'time zone was not changed after set_time_zone() throws an exception' ); } { my $dt = DateTime->now( time_zone => 'America/Chicago' ); ok( $dt->set_time_zone('America/Chicago'), 'set_time_zone returns object when time zone name is same as current' ); ok( $dt->set_time_zone( $dt->time_zone() ), 'set_time_zone returns object when time zone object is same as current' ); } done_testing(); DateTime-1.46/xt/author/pp-05set.t0000644000175000017500000000604213240151623016476 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 1996, month => 11, day => 22, hour => 18, minute => 30, second => 20, time_zone => 'UTC', ); is( $dt->month, 11, 'check month' ); $dt->set( month => 5 ); is( $dt->year, 1996, 'check year after setting month' ); is( $dt->month, 5, 'check month after setting it' ); is( $dt->day, 22, 'check day after setting month' ); is( $dt->hour, 18, 'check hour after setting month' ); is( $dt->minute, 30, 'check minute after setting month' ); is( $dt->second, 20, 'check second after setting month' ); $dt->set_time_zone('-060001'); is( $dt->year, 1996, 'check year after setting time zone' ); is( $dt->month, 5, 'check month after setting time zone' ); is( $dt->day, 22, 'check day after setting time zone' ); is( $dt->hour, 12, 'check hour after setting time zone' ); is( $dt->minute, 30, 'check minute after setting time zone' ); is( $dt->second, 19, 'check second after setting time zone' ); is( $dt->offset, -21601, 'check time zone offset after setting new time zone' ); $dt->set_time_zone('+0100'); is( $dt->year, 1996, 'check year after setting time zone' ); is( $dt->month, 5, 'check month after setting time zone' ); is( $dt->day, 22, 'check day after setting time zone' ); is( $dt->hour, 19, 'check hour after setting time zone' ); is( $dt->minute, 30, 'check minute after setting time zone' ); is( $dt->second, 20, 'check second after setting time zone' ); is( $dt->offset, 3600, 'check time zone offset after setting new time zone' ); $dt->set( hour => 17 ); is( $dt->year, 1996, 'check year after setting hour' ); is( $dt->month, 5, 'check month after setting hour' ); is( $dt->day, 22, 'check day after setting hour' ); is( $dt->hour, 17, 'check hour after setting hour' ); is( $dt->minute, 30, 'check minute after setting hour' ); is( $dt->second, 20, 'check second after setting hour' ); } { my $dt = DateTime->new( year => 1996, month => 11, day => 22, hour => 18, minute => 30, second => 20, time_zone => 'UTC', ); $dt->set_year(2000); is( $dt->year, 2000, 'check year after set_year' ); $dt->set_month(5); is( $dt->month, 5, 'check month after set_month' ); $dt->set_day(6); is( $dt->day, 6, 'check day after set_day' ); $dt->set_hour(7); is( $dt->hour, 7, 'check hour after set_hour' ); $dt->set_minute(8); is( $dt->minute, 8, 'check minute after set_minute' ); $dt->set_second(9); is( $dt->second, 9, 'check second after set_second' ); $dt->set_nanosecond(9999); is( $dt->nanosecond, 9999, 'check nanosecond after set_nanosecond' ); $dt->set_locale('fr_FR'); is( $dt->month_name, 'mai', 'check month name after set_locale' ); } done_testing(); DateTime-1.46/xt/author/pp-25add-subtract.t0000644000175000017500000000165613240151623020270 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; # exercises a bug found in Perl version of _normalize_tai_seconds - # fixed in 0.15 { my $dt = DateTime->new( year => 2000, month => 12 ); $dt->add( months => 1 )->truncate( to => 'month' ) ->subtract( seconds => 1 ); is( $dt->year, 2000, 'year is 2001' ); is( $dt->month, 12, 'month is 12' ); is( $dt->hour, 23, 'hour is 23' ); is( $dt->minute, 59, 'minute is 59' ); is( $dt->second, 59, 'second is 59' ); } { my $dt = DateTime->new( year => 2000, month => 12 ); my $dt2 = $dt->clone->add( months => 1 )->subtract( seconds => 1 ); is( $dt2->year, 2000, 'year is 2001' ); is( $dt2->month, 12, 'month is 12' ); is( $dt2->hour, 23, 'hour is 23' ); is( $dt2->minute, 59, 'minute is 59' ); is( $dt2->second, 59, 'second is 59' ); } done_testing(); DateTime-1.46/xt/author/pp-00load.t0000644000175000017500000000020213240151623016605 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More 0.88; use_ok('DateTime'); done_testing(); DateTime-1.46/xt/author/pp-09greg.t0000644000175000017500000000621013240151623016630 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; ## no critic (Subroutines::ProtectPrivateSubs) # test _ymd2rd and _rd2ymd for various dates # 2 tests are performed for each date (on _ymd2rd and _rd2ymd) # dates are specified as [rd,year,month,day] for ( # min and max supported days (for 32-bit system) [ -( 2**28 ), -734951, 9, 7 ], [ 2**28, 734952, 4, 25 ], # some miscellaneous dates (these are actually epoch dates for # various calendars from Calendrical Calculations (1st ed) Table # 1.1) [ -1721425, -4713, 11, 24 ], [ -1373427, -3760, 9, 7 ], [ -1137142, -3113, 8, 11 ], [ -1132959, -3101, 1, 23 ], [ -963099, -2636, 2, 15 ], [ -1, 0, 12, 30 ], [ 1, 1, 1, 1 ], [ 2796, 8, 8, 27 ], [ 103605, 284, 8, 29 ], [ 226896, 622, 3, 22 ], [ 227015, 622, 7, 19 ], [ 654415, 1792, 9, 22 ], [ 673222, 1844, 3, 21 ] ) { is( join( '/', DateTime->_rd2ymd( $_->[0] ) ), join( '/', @{$_}[ 1 .. 3 ] ), $_->[0] . " \t=> " . join '/', @{$_}[ 1 .. 3 ] ); is( DateTime->_ymd2rd( @{$_}[ 1 .. 3 ] ), $_->[0], join( '/', @{$_}[ 1 .. 3 ] ) . " \t=> " . $_->[0] ); } # normalization tests for ( [ -1753469, -4797, -33, 1 ], [ -1753469, -4803, 39, 1 ], [ -1753105, -4796, -34, 28 ], [ -1753105, -4802, 38, 28 ] ) { is( DateTime->_ymd2rd( @{$_}[ 1 .. 3 ] ), $_->[0], join( '/', @{$_}[ 1 .. 3 ] ) . " \t=> " . $_->[0] . ' (normalization)' ); } # test first and last day of each month from Jan -4800..Dec 4800 # this test bails after the first failure with a not ok. # if it completes successfully, only one ok is issued. my @mlen = ( 0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); my ( $dno, $y, $m, $dno2, $y2, $m2, $d2, $mlen ) = ( -1753530, -4800, 1 ); while ( $y <= 4800 ) { # test $y,$m,1 ++$dno; $dno2 = DateTime->_ymd2rd( $y, $m, 1 ); if ( $dno != $dno2 ) { is( $dno2, $dno, "greg torture test: _ymd2rd($y,$m,1) should be $dno" ); last; } ( $y2, $m2, $d2 ) = DateTime->_rd2ymd($dno); if ( $y2 != $y || $m2 != $m || $d2 != 1 ) { is( "$y2/$m2/$d2", "$y/$m/1", "greg torture test: _rd2ymd($dno) should be $y/$m/1" ); last; } # test $y,$m,$mlen $mlen = $mlen[$m] || ( $y % 4 ? 28 : $y % 100 ? 29 : $y % 400 ? 28 : 29 ); $dno += $mlen - 1; $dno2 = DateTime->_ymd2rd( $y, $m, $mlen ); if ( $dno != $dno2 ) { is( $dno2, $dno, "greg torture test: _ymd2rd($y,$m,$mlen) should be $dno" ); last; } ( $y2, $m2, $d2 ) = DateTime->_rd2ymd($dno); if ( $y2 != $y || $m2 != $m || $d2 != $mlen ) { is( "$y2/$m2/$d2", "$y/$m/$mlen", "greg torture test: _rd2ymd($dno) should be $y/$m/$mlen" ); last; } # and on to the next month... if ( ++$m > 12 ) { $m = 1; ++$y; } } pass('greg torture test') if $y == 4801; done_testing(); DateTime-1.46/xt/author/pp-01sanity.t0000644000175000017500000000322113240151623017202 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 1870, month => 10, day => 21, hour => 12, minute => 10, second => 45, nanosecond => 123456, time_zone => 'UTC' ); is( $dt->year, '1870', 'Year accessor, outside of the epoch' ); is( $dt->month, '10', 'Month accessor, outside the epoch' ); is( $dt->day, '21', 'Day accessor, outside the epoch' ); is( $dt->hour, '12', 'Hour accessor, outside the epoch' ); is( $dt->minute, '10', 'Minute accessor, outside the epoch' ); is( $dt->second, '45', 'Second accessor, outside the epoch' ); is( $dt->nanosecond, '123456', 'nanosecond accessor, outside the epoch' ); $dt = DateTime->from_object( object => $dt ); is( $dt->year, '1870', 'Year should be identical' ); is( $dt->month, '10', 'Month should be identical' ); is( $dt->day, '21', 'Day should be identical' ); is( $dt->hour, '12', 'Hour should be identical' ); is( $dt->minute, '10', 'Minute should be identical' ); is( $dt->second, '45', 'Second should be identical' ); is( $dt->nanosecond, '123456', 'nanosecond should be identical' ); } { my $dt = DateTime->new( year => 1870, month => 10, day => 21, hour => 12, minute => 10, second => 45, time_zone => 'UTC' ); is( $dt->minute, '10', 'Minute accessor, outside the epoch' ); is( $dt->second, '45', 'Second accessor, outside the epoch' ); } done_testing(); DateTime-1.46/xt/author/pp-11duration.t0000644000175000017500000003314113240151623017525 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; use DateTime::Duration; { my %pairs = ( years => 1, months => 2, weeks => 3, days => 4, hours => 6, minutes => 7, seconds => 8, nanoseconds => 9, ); my $dur = DateTime::Duration->new(%pairs); while ( my ( $unit, $val ) = each %pairs ) { is( $dur->$unit(), $val, "$unit should be $val" ); } is( $dur->delta_months, 14, 'delta_months' ); is( $dur->delta_days, 25, 'delta_days' ); is( $dur->delta_minutes, 367, 'delta_minutes' ); is( $dur->delta_seconds, 8, 'delta_seconds' ); is( $dur->delta_nanoseconds, 9, 'delta_nanoseconds' ); is( $dur->in_units('months'), 14, 'in_units months' ); is( $dur->in_units('days'), 25, 'in_units days' ); is( $dur->in_units('minutes'), 367, 'in_units minutes' ); is( $dur->in_units('seconds'), 8, 'in_units seconds' ); is( $dur->in_units( 'nanoseconds', 'seconds' ), 9, 'in_units nanoseconds, seconds' ); is( $dur->in_units('years'), 1, 'in_units years' ); is( $dur->in_units( 'months', 'years' ), 2, 'in_units months, years' ); is( $dur->in_units('weeks'), 3, 'in_units weeks' ); is( $dur->in_units( 'days', 'weeks' ), 4, 'in_units days, weeks' ); is( $dur->in_units('hours'), 6, 'in_units hours' ); is( $dur->in_units( 'minutes', 'hours' ), 7, 'in_units minutes, hours' ); is( $dur->in_units('nanoseconds'), 8_000_000_009, 'in_units nanoseconds' ); my ( $years, $months, $weeks, $days, $hours, $minutes, $seconds, $nanoseconds ) = $dur->in_units( qw( years months weeks days hours minutes seconds nanoseconds ) ); is( $years, 1, 'in_units years, list context' ); is( $months, 2, 'in_units months, list context' ); is( $weeks, 3, 'in_units weeks, list context' ); is( $days, 4, 'in_units days, list context' ); is( $hours, 6, 'in_units hours, list context' ); is( $minutes, 7, 'in_units minutes, list context' ); is( $seconds, 8, 'in_units seconds, list context' ); is( $nanoseconds, 9, 'in_units nanoseconds, list context' ); ok( $dur->is_positive, 'should be positive' ); ok( !$dur->is_zero, 'should not be zero' ); ok( !$dur->is_negative, 'should not be negative' ); ok( $dur->is_wrap_mode, 'wrap mode' ); } { my %pairs = ( years => 1, months => 2, weeks => 3, days => 4, hours => 6, minutes => 7, seconds => 8, nanoseconds => 9, ); my $dur = DateTime::Duration->new( %pairs, end_of_month => 'limit' ); my $calendar_dur = $dur->calendar_duration; is( $calendar_dur->delta_months, 14, 'date - delta_months is 14' ); is( $calendar_dur->delta_minutes, 0, 'date - delta_minutes is 0' ); is( $calendar_dur->delta_seconds, 0, 'date - delta_seconds is 0' ); is( $calendar_dur->delta_nanoseconds, 0, 'date - delta_nanoseconds is 0' ); ok( $calendar_dur->is_limit_mode, 'limit mode' ); my $clock_dur = $dur->clock_duration; is( $clock_dur->delta_months, 0, 'time - delta_months is 0' ); is( $clock_dur->delta_minutes, 367, 'time - delta_minutes is 367' ); is( $clock_dur->delta_seconds, 8, 'time - delta_seconds is 8' ); is( $clock_dur->delta_nanoseconds, 9, 'time - delta_nanoseconds is 9' ); ok( $clock_dur->is_limit_mode, 'limit mode' ); } { my $dur = DateTime::Duration->new( days => 1, end_of_month => 'limit' ); ok( $dur->is_limit_mode, 'limit mode' ); } { my $dur = DateTime::Duration->new( days => 1, end_of_month => 'preserve' ); ok( $dur->is_preserve_mode, 'preserve mode' ); } my $leap_day = DateTime->new( year => 2004, month => 2, day => 29, time_zone => 'UTC', ); { my $new = $leap_day + DateTime::Duration->new( years => 1, end_of_month => 'wrap' ); is( $new->date, '2005-03-01', 'new date should be 2005-03-01' ); } { my $new = $leap_day + DateTime::Duration->new( years => 1, end_of_month => 'limit' ); is( $new->date, '2005-02-28', 'new date should be 2005-02-28' ); } { my $new = $leap_day + DateTime::Duration->new( years => 1, end_of_month => 'preserve' ); is( $new->date, '2005-02-28', 'new date should be 2005-02-28' ); my $new2 = $leap_day + DateTime::Duration->new( months => 1, end_of_month => 'preserve' ); is( $new2->date, '2004-03-31', 'new date should be 2004-03-31' ); } { my $inverse = DateTime::Duration->new( years => 1, months => 1, weeks => 1, days => 1, hours => 1, minutes => 2, seconds => 3, )->inverse; is( $inverse->years, 1, 'inverse years should be positive' ); is( $inverse->months, 1, 'inverse months should be positive' ); is( $inverse->weeks, 1, 'inverse weeks should be positive' ); is( $inverse->days, 1, 'inverse days should be positive' ); is( $inverse->hours, 1, 'inverse hours should be positive' ); is( $inverse->minutes, 2, 'inverse minutes should be positive' ); is( $inverse->seconds, 3, 'inverse minutes should be positive' ); is( $inverse->delta_months, -13, 'inverse delta months should be negative' ); is( $inverse->delta_days, -8, 'inverse delta months should be negative' ); is( $inverse->delta_minutes, -62, 'inverse delta minutes should be negative' ); is( $inverse->delta_seconds, -3, 'inverse delta seconds should be negative' ); ok( $inverse->is_negative, 'should be negative' ); ok( !$inverse->is_zero, 'should not be zero' ); ok( !$inverse->is_positive, 'should not be positivea' ); is( $inverse->end_of_month_mode(), 'preserve', 'inverse method uses default end_of_month_mode without explicit parameter' ); my $inverse2 = DateTime::Duration->new( years => 1 ) ->inverse( end_of_month => 'limit' ); is( $inverse2->end_of_month_mode(), 'limit', 'inverse method allows setting end_of_month_mode' ); } { my $dur1 = DateTime::Duration->new( months => 6, days => 10 ); my $dur2 = DateTime::Duration->new( months => 3, days => 7 ); my $new1 = $dur1 + $dur2; is( $new1->delta_months, 9, 'test + overloading' ); is( $new1->delta_days, 17, 'test + overloading' ); my $new2 = $dur1 - $dur2; is( $new2->delta_months, 3, 'test - overloading' ); is( $new2->delta_days, 3, 'test - overloading' ); my $new3 = $dur2 - $dur1; is( $new3->delta_months, -3, 'test - overloading' ); is( $new3->delta_days, -3, 'test - overloading' ); } { my $dur1 = DateTime::Duration->new( months => 6, days => 10 ); my $new1 = $dur1 * 4; is( $new1->delta_months, 24, 'test * overloading' ); is( $new1->delta_days, 40, 'test * overloading' ); $dur1->multiply(4); is( $dur1->delta_months, 24, 'test multiply' ); is( $dur1->delta_days, 40, 'test multiply' ); } { my $dur1 = DateTime::Duration->new( months => 6, days => 10, seconds => 3, nanoseconds => 1_200_300_400 ); my $dur2 = DateTime::Duration->new( seconds => 1, nanoseconds => 500_000_000 ); is( $dur1->delta_seconds, 4, 'test nanoseconds overflow' ); is( $dur1->delta_nanoseconds, 200_300_400, 'test nanoseconds remainder' ); my $new1 = $dur1 - $dur2; is( $new1->delta_seconds, 2, 'seconds is positive' ); is( $new1->delta_nanoseconds, 700_300_400, 'nanoseconds remainder is negative' ); $new1->add( nanoseconds => 500_000_000 ); is( $new1->delta_seconds, 3, 'seconds are unaffected' ); is( $new1->delta_nanoseconds, 200_300_400, 'nanoseconds are back' ); my $new2 = $dur1 - $dur2; $new2->add( nanoseconds => 1_500_000_000 ); is( $new2->delta_seconds, 4, 'seconds go up' ); is( $new2->delta_nanoseconds, 200_300_400, 'nanoseconds are normalized' ); $new2->subtract( nanoseconds => 100_000_000 ); is( $new2->delta_nanoseconds, 100_300_400, 'sub nanoseconds works' ); my $new3 = $dur2 * 3; is( $new3->delta_seconds, 4, 'seconds normalized after multiplication' ); is( $new3->delta_nanoseconds, 500_000_000, 'nanoseconds normalized after multiplication' ); } { my $dur1 = DateTime::Duration->new( seconds => 1 ); my $dur2 = DateTime::Duration->new( seconds => 1 ); $dur1->add($dur2); is( $dur1->delta_seconds, 2, 'add method works with a duration object' ); $dur1->subtract($dur2); is( $dur1->delta_seconds, 1, 'subtract method works with a duration object' ); } { my $dur = DateTime::Duration->new( nanoseconds => -10 ); is( $dur->nanoseconds, 10, 'nanoseconds is 10' ); is( $dur->delta_nanoseconds, -10, 'delta_nanoseconds is -10' ); ok( $dur->is_negative, 'duration is negative' ); } { my $dur = DateTime::Duration->new( days => 0 ); is( $dur->delta_days, 0, 'delta_days is 0' ); ok( !$dur->is_positive, 'not positive' ); ok( $dur->is_zero, 'is zero' ); ok( !$dur->is_negative, 'not negative' ); } { is( exception { DateTime::Duration->new( months => 3 )->add( hours => -3 ) ->add( minutes => 1 ); }, undef, 'method chaining should work' ); } { my $min_1 = DateTime::Duration->new( minutes => 1 ); my $hour_1 = DateTime::Duration->new( hours => 1 ); my $min_59 = $hour_1 - $min_1; is( $min_59->delta_months, 0, 'delta_months is 0' ); is( $min_59->delta_days, 0, 'delta_days is 0' ); is( $min_59->delta_minutes, 59, 'delta_minutes is 59' ); is( $min_59->delta_seconds, 0, 'delta_seconds is 0' ); is( $min_59->delta_nanoseconds, 0, 'delta_nanoseconds is 0' ); my $min_neg_59 = $min_1 - $hour_1; is( $min_neg_59->delta_months, 0, 'delta_months is 0' ); is( $min_neg_59->delta_days, 0, 'delta_days is 0' ); is( $min_neg_59->delta_minutes, -59, 'delta_minutes is -59' ); is( $min_neg_59->delta_seconds, 0, 'delta_seconds is 0' ); is( $min_neg_59->delta_nanoseconds, 0, 'delta_nanoseconds is 0' ); } { my $dur1 = DateTime::Duration->new( minutes => 10 ); my $dur2 = DateTime::Duration->new( minutes => 20 ); like( exception { 1 if $dur1 <=> $dur2 }, qr/does not overload comparison/, 'check error for duration comparison overload' ); is( DateTime::Duration->compare( $dur1, $dur2 ), -1, '20 minutes is greater than 10 minutes' ); is( DateTime::Duration->compare( $dur1, $dur2, DateTime->new( year => 1 ) ), -1, '20 minutes is greater than 10 minutes' ); } { my $dur1 = DateTime::Duration->new( days => 29 ); my $dur2 = DateTime::Duration->new( months => 1 ); my $base = DateTime->new( year => 2004 ); is( DateTime::Duration->compare( $dur1, $dur2, $base ), -1, '29 days is less than 1 month with base of 2004-01-01' ); $base = DateTime->new( year => 2004, month => 2 ); is( DateTime::Duration->compare( $dur1, $dur2, $base ), 0, '29 days is equal to 1 month with base of 2004-02-01' ); $base = DateTime->new( year => 2005, month => 2 ); is( DateTime::Duration->compare( $dur1, $dur2, $base ), 1, '29 days is greater than 1 month with base of 2005-02-01' ); } { my $dur1 = DateTime::Duration->new( nanoseconds => 1_000, seconds => 1, ); my $dur2 = $dur1->clone->subtract( nanoseconds => 5_000 ); is( $dur2->delta_seconds, 0, 'normalize nanoseconds to positive' ); is( $dur2->delta_nanoseconds, 999_996_000, 'normalize nanoseconds to positive' ); my $dur3 = $dur1->clone->subtract( nanoseconds => 6_000 ) ->subtract( nanoseconds => 999_999_000 ); is( $dur3->delta_seconds, 0, 'normalize nanoseconds to negative' ); is( $dur3->delta_nanoseconds, -4_000, 'normalize nanoseconds to negative' ); my $dur4 = DateTime::Duration->new( seconds => -1, nanoseconds => -2_500_000_000 ); is( $dur4->delta_seconds, -3, 'normalize many negative nanoseconds' ); is( $dur4->delta_nanoseconds, -500_000_000, 'normalize many negative nanoseconds' ); } { my $dur = DateTime::Duration->new( minutes => 30, seconds => -1, ); ok( !$dur->is_positive, 'is not positive' ); ok( !$dur->is_zero, 'is not zero' ); ok( !$dur->is_negative, 'is not negative' ); } { my $dur = DateTime::Duration->new( minutes => 50 ); is( $dur->in_units('years'), 0, 'in_units returns 0 for years' ); is( $dur->in_units('months'), 0, 'in_units returns 0 for months' ); is( $dur->in_units('days'), 0, 'in_units returns 0 for days' ); is( $dur->in_units('hours'), 0, 'in_units returns 0 for hours' ); is( $dur->in_units('seconds'), 0, 'in_units returns 0 for seconds' ); is( $dur->in_units('nanoseconds'), 0, 'in_units returns 0 for nanoseconds' ); } { local $TODO = 'reject fractional units in DateTime::Duration->new'; like( exception { DateTime::Duration->new( minutes => 50.2 ) }, qr/is an integer/, 'cannot create a duration with fractional units' ); } done_testing(); DateTime-1.46/xt/author/pp-45core-time.t0000644000175000017500000000053113240151623017570 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; no warnings 'redefine'; ## no critic (Variables::ProtectPrivateVars) local *DateTime::_core_time = sub {0}; my $dt = DateTime->now; is( "$dt", '1970-01-01T00:00:00', 'overriding DateTime::_core_time() works' ); done_testing(); DateTime-1.46/xt/author/pp-36invalid-local.t0000644000175000017500000000257613240151623020435 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; my $badlt_rx = qr/Invalid local time|local time [0-9\-:T]+ does not exist/; { like( exception { DateTime->new( year => 2003, month => 4, day => 6, hour => 2, time_zone => 'America/Chicago', ); }, $badlt_rx, 'exception for invalid time' ); like( exception { DateTime->new( year => 2003, month => 4, day => 6, hour => 2, minute => 59, second => 59, time_zone => 'America/Chicago', ); }, $badlt_rx, 'exception for invalid time' ); } { is( exception { DateTime->new( year => 2003, month => 4, day => 6, hour => 1, minute => 59, second => 59, time_zone => 'America/Chicago', ); }, undef, 'no exception for valid time' ); my $dt = DateTime->new( year => 2003, month => 4, day => 5, hour => 2, time_zone => 'America/Chicago', ); like( exception { $dt->add( days => 1 ) }, $badlt_rx, 'exception for invalid time produced via add' ); } done_testing(); DateTime-1.46/xt/author/pp-22from-doy.t0000644000175000017500000000321113240151623017431 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; my @last_day = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); my @leap_last_day = @last_day; $leap_last_day[1]++; { my $doy = 15; foreach my $month ( 1 .. 12 ) { $doy += $last_day[ $month - 2 ] if $month > 1; my $dt = DateTime->from_day_of_year( year => 2001, day_of_year => $doy, time_zone => 'UTC', ); is( $dt->year, 2001, 'check year' ); is( $dt->month, $month, 'check month' ); is( $dt->day, 15, 'check day' ); is( $dt->day_of_year, $doy, 'check day of year' ); } } { my $doy = 15; foreach my $month ( 1 .. 12 ) { $doy += $leap_last_day[ $month - 2 ] if $month > 1; my $dt = DateTime->from_day_of_year( year => 2004, day_of_year => $doy, time_zone => 'UTC', ); is( $dt->year, 2004, 'check year' ); is( $dt->month, $month, 'check month' ); is( $dt->day, 15, 'check day' ); is( $dt->day_of_year, $doy, 'check day of year' ); } } { like( exception { DateTime->from_day_of_year( year => 2001, day_of_year => 366 ) }, qr/2001 is not a leap year/, 'Cannot give day of year 366 in non-leap years' ); is( exception { DateTime->from_day_of_year( year => 2004, day_of_year => 366 ) }, undef, 'Day of year 366 should work in leap years' ); } done_testing(); DateTime-1.46/xt/author/pp-46warnings.t0000644000175000017500000000434313240151623017542 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use Test::Warnings 0.005 ':all'; use DateTime; my $year_5001_epoch = 95649120000; ## no critic (TestingAndDebugging::ProhibitNoWarnings) SKIP: { my $year = ( gmtime($year_5001_epoch) )[5]; skip 'These tests require a 64-bit Perl', 2 unless defined $year && $year == 3101; { like( warning { DateTime->from_epoch( epoch => $year_5001_epoch, time_zone => 'Asia/Taipei', ); }, qr{\QYou are creating a DateTime object with a far future year (5001) and a time zone (Asia/Taipei).}, 'got a warning when calling ->from_epoch with a far future epoch and a time_zone' ); } { no warnings 'DateTime'; is_deeply( warning { DateTime->from_epoch( epoch => $year_5001_epoch, time_zone => 'Asia/Taipei', ); }, [], 'no warning when calling ->from_epoch with a far future epoch and a time_zone with DateTime warnings category suppressed' ); } } { like( warning { DateTime->new( year => 5001, time_zone => 'Asia/Taipei', ); }, qr{\QYou are creating a DateTime object with a far future year (5001) and a time zone (Asia/Taipei).}, 'got a warning when calling ->new with a far future year and a time_zone' ); } { no warnings 'DateTime'; is_deeply( warning { DateTime->new( year => 5001, time_zone => 'Asia/Taipei', ); }, [], 'no warning when calling ->new with a far future epoch and a time_zone with DateTime warnings category suppressed' ); } { no warnings; is_deeply( warning { DateTime->new( year => 5001, time_zone => 'Asia/Taipei', ); }, [], 'no warning when calling ->new with a far future epoch and a time_zone with all warnings suppressed' ); } done_testing(); DateTime-1.46/xt/author/pp-35rd-values.t0000644000175000017500000000276513240151623017620 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 2000, hour => 1, nanosecond => 500, time_zone => 'UTC', ); my ( $utc_rd_days, $utc_rd_secs, $utc_nanosecs ) = $dt->utc_rd_values; is( $utc_rd_days, 730120, 'utc rd days is 730120' ); is( $utc_rd_secs, 3600, 'utc rd seconds is 3600' ); is( $utc_nanosecs, 500, 'nanoseconds is 500' ); my ( $local_rd_days, $local_rd_secs, $local_nanosecs ) = $dt->local_rd_values; is( $local_rd_days, $utc_rd_days, 'local & utc rd days are equal' ); is( $local_rd_secs, $utc_rd_secs, 'local & utc rd seconds are equal' ); is( $local_nanosecs, $utc_nanosecs, 'local & UTC nanoseconds are equal' ); } { my $dt = DateTime->new( year => 2000, hour => 1, nanosecond => 500, time_zone => '+02:00', ); my ( $utc_rd_days, $utc_rd_secs, $utc_nanosecs ) = $dt->utc_rd_values; is( $utc_rd_days, 730119, 'utc rd days is 730119' ); is( $utc_rd_secs, 82800, 'utc rd seconds is 82800' ); is( $utc_nanosecs, 500, 'nanoseconds is 500' ); my ( $local_rd_days, $local_rd_secs, $local_nanosecs ) = $dt->local_rd_values; is( $local_rd_days, 730120, 'local rd days is 730120' ); is( $local_rd_secs, 3600, 'local rd seconds is 3600' ); is( $local_nanosecs, 500, 'local nanoseconds is 500' ); } done_testing(); DateTime-1.46/xt/author/pp-40leap-years.t0000644000175000017500000000055713240151623017751 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; ## no critic (Subroutines::ProtectPrivateSubs) for my $y ( 0, 400, 2000, 2004 ) { ok( DateTime->_is_leap_year($y), "$y is a leap year" ); } for my $y ( 1, 100, 1900, 2133 ) { ok( !DateTime->_is_leap_year($y), "$y is not a leap year" ); } done_testing(); DateTime-1.46/xt/author/pp-30future-tz.t0000644000175000017500000000326113240151623017646 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; # # This test exercises a bug that occurred when date math did not # always make sure to update the utc_year attribute of the given # DateTime. The sympton was that the time zone future span generation # would fail because utc_year was less than the span's max_year, so # span generation wouldn't actually do anything, and it would die with # "Invalid local time". # { # Each iteration needs to use a different zone, because if it # works once, the generated spans are cached. for my $add ( [ years => 50, 1, 'America/New_York' ], [ days => 50, 365, 'America/Chicago' ], [ minutes => 50, 365 * 1440, 'America/Denver', ], [ seconds => 50, 365 * 1440 * 60, 'America/Los_Angeles' ], [ nanoseconds => 50, 365 * 1440 * 60 * 1_000_000_000, 'America/North_Dakota/Center' ], [ years => 750, 1, 'Europe/Paris' ], [ days => 750, 365, 'Europe/London' ], [ minutes => 750, 365 * 1440, 'Europe/Brussels', ], [ seconds => 750, 365 * 1440 * 60, 'Europe/Vienna' ], [ nanoseconds => 750, 365 * 1440 * 60 * 1_000_000_000, 'Europe/Prague' ], ) { my $dt = DateTime->now->set( hour => 12 )->set_time_zone( $add->[3] ); my $new = eval { $dt->clone->add( $add->[0], $add->[1] * $add->[2] ) }; is( $@, q{}, "Make sure we can add $add->[1] years worth of $add->[0] in $add->[3] time zone" ); } } done_testing(); DateTime-1.46/xt/author/pp-48rt-115983.t0000644000175000017500000000115413240151623017106 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; # The bug here is that if DateTime doesn't clean it's namespace, it ends up # having a catch method that is getting called here and being passed a hashref # containing the return value of $dt->truncate. See # https://rt.cpan.org/Ticket/Display.html?id=115983 my $dt = DateTime->now; like( exception { try { } catch { $dt->truncate( to => 'hour' ); }; }, qr/Can\'t locate object method "catch"/, 'DateTime does not have a catch method' ); done_testing(); DateTime-1.46/xt/author/pp-04epoch.t0000644000175000017500000001272213240151623017002 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use Test::Fatal; use DateTime; { # Tests creating objects from epoch time my $t1 = DateTime->from_epoch( epoch => 0 ); is( $t1->epoch, 0, 'epoch should be 0' ); is( $t1->second, 0, 'seconds are correct on epoch 0' ); is( $t1->minute, 0, 'minutes are correct on epoch 0' ); is( $t1->hour, 0, 'hours are correct on epoch 0' ); is( $t1->day, 1, 'days are correct on epoch 0' ); is( $t1->month, 1, 'months are correct on epoch 0' ); is( $t1->year, 1970, 'year is correct on epoch 0' ); } { my $dt = DateTime->from_epoch( epoch => '3600' ); is( $dt->epoch, 3600, 'creation test from epoch = 3600 (compare to epoch)' ); } { # these tests could break if the time changed during the next three lines my $now = time; my $nowtest = DateTime->now(); my $nowtest2 = DateTime->from_epoch( epoch => $now ); is( $nowtest->hour, $nowtest2->hour, 'Hour: Create without args' ); is( $nowtest->month, $nowtest2->month, 'Month : Create without args' ); is( $nowtest->minute, $nowtest2->minute, 'Minute: Create without args' ); } { my $epochtest = DateTime->from_epoch( epoch => '997121000' ); is( $epochtest->epoch, 997121000, 'epoch method returns correct value' ); is( $epochtest->hour, 18, 'hour' ); is( $epochtest->min, 3, 'minute' ); } { my $dt = DateTime->from_epoch( epoch => 3600 ); $dt->set_time_zone('+0100'); is( $dt->epoch, 3600, 'epoch is 3600' ); is( $dt->hour, 2, 'hour is 2' ); } { my $dt = DateTime->new( year => 1970, month => 1, day => 1, hour => 0, time_zone => '-0100', ); is( $dt->epoch, 3600, 'epoch is 3600' ); } { my $dt = DateTime->from_epoch( epoch => 0, time_zone => '-0100', ); is( $dt->offset, -3600, 'offset should be -3600' ); is( $dt->epoch, 0, 'epoch is 0' ); } # Adding/subtracting should affect epoch { my $expected = 1049160602; my $epochtest = DateTime->from_epoch( epoch => $expected ); is( $epochtest->epoch, $expected, "epoch method returns correct value ($expected)" ); is( $epochtest->hour, 1, 'hour' ); is( $epochtest->min, 30, 'minute' ); $epochtest->add( hours => 2 ); $expected += 2 * 60 * 60; is( $epochtest->hour, 3, 'adjusted hour' ); is( $epochtest->epoch, $expected, "epoch method returns correct adjusted value ($expected)" ); } { my $dt = DateTime->from_epoch( epoch => 0.5 ); is( $dt->nanosecond, 500_000_000, 'nanosecond should be 500,000,000 with 0.5 as epoch' ); is( $dt->epoch, 0, 'epoch should be 0' ); is( $dt->hires_epoch, 0.5, 'hires_epoch should be 0.5' ); } { my $dt = DateTime->from_epoch( epoch => -0.5 ); is( $dt->nanosecond, 500_000_000, 'nanosecond should be 500,000,000 with -0.5 as epoch' ); is( $dt->epoch, -1, 'epoch should be -1' ); is( $dt->hires_epoch, -0.5, 'hires_epoch should be -0.5' ); } { my $dt = DateTime->from_epoch( epoch => 1609459199.999999 ); is( $dt->nanosecond, 999999000, 'nanosecond should be 999,999,000 with 1609459199.999999 as epoch' ); is( $dt->epoch, 1609459199, 'epoch should be 1609459199' ); } { my $dt = DateTime->from_epoch( epoch => 0.1234567891 ); is( $dt->nanosecond, 123_457_000, 'nanosecond should be rounded to 123,457,000 when given 0.1234567891' ); } { my $dt = DateTime->from_epoch( epoch => -0.1234567891 ); is( $dt->nanosecond, 876_543_000, 'nanosecond should be rounded to 876,543,000 when given -0.1234567891' ); } { is( DateTime->new( year => 1904 )->epoch, -2082844800, 'epoch should work back to at least 1904' ); my $dt = DateTime->from_epoch( epoch => -2082844800 ); is( $dt->year, 1904, 'year should be 1904' ); is( $dt->month, 1, 'month should be 1904' ); is( $dt->day, 1, 'day should be 1904' ); } { for my $pair ( [ 1 => -62135596800 ], [ 99 => -59042995200 ], [ 100 => -59011459200 ], [ 999 => -30641760000 ], ) { my ( $year, $epoch ) = @{$pair}; is( DateTime->new( year => $year )->epoch, $epoch, "epoch for $year is $epoch" ); } } { package Number::Overloaded; use overload '0+' => sub { $_[0]->{num} }, fallback => 1; sub new { bless { num => $_[1] }, $_[0] } } { my $time = Number::Overloaded->new(12345); my $dt = DateTime->from_epoch( epoch => $time ); is( $dt->epoch, 12345, 'can pass overloaded object to from_epoch' ); $time = Number::Overloaded->new(12345.1234); $dt = DateTime->from_epoch( epoch => $time ); is( $dt->epoch, 12345, 'decimal epoch in overloaded object' ); } { my $time = Number::Overloaded->new(-12345); my $dt = DateTime->from_epoch( epoch => $time ); is( $dt->epoch, -12345, 'negative epoch in overloaded object' ); } { my @tests = ( 'asldkjlkjd', '1234 foo', 'adlkj 1234', ); for my $test (@tests) { like( exception { DateTime->from_epoch( epoch => $test ) }, qr/Validation failed for type named Num/, qq{'$test' is not a valid epoch value} ); } } done_testing(); DateTime-1.46/xt/author/pp-23storable.t0000644000175000017500000000445513240151623017524 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; unless ( eval { require Storable; 1 } ) { plan skip_all => 'Cannot load Storable'; } { my @dt = ( DateTime->new( year => 1950, hour => 1, nanosecond => 1, time_zone => 'America/Chicago', locale => 'de' ), DateTime::Infinite::Past->new, DateTime::Infinite::Future->new, ); foreach my $dt (@dt) { my $copy = Storable::thaw( Storable::nfreeze($dt) ); is( $copy->time_zone->name, $dt->time_zone->name, 'Storable freeze/thaw preserves tz' ); is( ref $copy->locale, ref $dt->locale, 'Storable freeze/thaw preserves locale' ); is( $copy->year, $dt->year, 'Storable freeze/thaw preserves rd values' ); is( $copy->hour, $dt->hour, 'Storable freeze/thaw preserves rd values' ); is( $copy->nanosecond, $dt->nanosecond, 'Storable freeze/thaw preserves rd values' ); } } { my $dt1 = DateTime->now( locale => 'en-US' ); my $dt2 = Storable::dclone($dt1); my $dt3 = Storable::thaw( Storable::nfreeze($dt2) ); is( $dt1->iso8601, $dt2->iso8601, 'dclone produces date equal to original' ); is( $dt2->iso8601, $dt3->iso8601, 'explicit freeze and thaw produces date equal to original' ); # Back-compat shim for new DateTime::Locale. Remove once DT::Locale based # on CLDR 28+ is released. my $meth = $dt1->locale->can('code') ? 'code' : 'id'; my $orig_code = $dt1->locale->$meth; is( $dt2->locale->$meth, $orig_code, 'check locale id after dclone' ); is( $dt3->locale->$meth, $orig_code, 'check locale id after explicit freeze/thaw' ); } { package Formatter; sub format_datetime { } } { my $dt = DateTime->new( year => 2004, formatter => 'Formatter', ); my $copy = Storable::thaw( Storable::nfreeze($dt) ); is( $dt->formatter, $copy->formatter, 'Storable freeze/thaw preserves formatter' ); } done_testing(); DateTime-1.46/xt/author/mojibake.t0000644000175000017500000000015113240151623016675 0ustar autarchautarch#!perl use strict; use warnings qw(all); use Test::More; use Test::Mojibake; all_files_encoding_ok(); DateTime-1.46/xt/author/pp-32leap-second2.t0000644000175000017500000001657013240151623020166 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 59, second => 58, time_zone => '+0100', ); is( $t->second, 58, 'second value for leap second T-2, +0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-2' ); is( $t->{utc_rd_secs}, 86398, 'UTC RD seconds for leap second T-2' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second T-2' ); is( $t->{local_rd_secs}, 3598, 'local RD seconds for leap second T-2' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 59, second => 59, time_zone => '+0100', ); is( $t->second, 59, 'second value for leap second T-1, +0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-1' ); is( $t->{utc_rd_secs}, 86399, 'UTC RD seconds for leap second T-1' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second T-1' ); is( $t->{local_rd_secs}, 3599, 'local RD seconds for leap second T-1' ); } { my $t = eval { DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 59, second => 60, time_zone => '+0100', ); }; ok( !$@, 'constructor for second = 60' ); SKIP: { skip 'constructor failed - no object to test', 5 unless $t; is( $t->second, 60, 'second value for leap second T-0, +0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-0' ); is( $t->{utc_rd_secs}, 86400, 'UTC RD seconds for leap second T-0' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second T-0' ); is( $t->{local_rd_secs}, 3600, 'local RD seconds for leap second T-0' ); } } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 1, minute => 0, second => 0, time_zone => '+0100', ); is( $t->second, 0, 'second value for leap second T+1, +0100' ); is( $t->{utc_rd_days}, 720075, 'UTC RD days for leap second T+1' ); is( $t->{utc_rd_secs}, 0, 'UTC RD seconds for leap second T+1' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second T+1' ); is( $t->{local_rd_secs}, 3601, 'local RD seconds for leap second T+1' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 1, minute => 0, second => 1, time_zone => '+0100', ); is( $t->second, 1, 'second value for leap second T+2, +0100' ); is( $t->{utc_rd_days}, 720075, 'UTC RD days for leap second T+2' ); is( $t->{utc_rd_secs}, 1, 'UTC RD seconds for leap second T+2' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second T+2' ); is( $t->{local_rd_secs}, 3602, 'local RD seconds for leap second T+2' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 23, minute => 59, second => 59, time_zone => '+0100', ); is( $t->second, 59, 'second value for end of leap second day, +0100' ); is( $t->{utc_rd_days}, 720075, 'UTC RD days for end of leap second day' ); is( $t->{utc_rd_secs}, 82799, 'UTC RD seconds for end of leap second day' ); is( $t->{local_rd_days}, 720075, 'local RD days for leap second day' ); is( $t->{local_rd_secs}, 86400, 'local RD seconds for end of leap second day' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 22, minute => 59, second => 58, time_zone => '-0100', ); is( $t->second, 58, 'second value for leap second T-2, -0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-2' ); is( $t->{utc_rd_secs}, 86398, 'UTC RD seconds for leap second T-2' ); is( $t->{local_rd_days}, 720074, 'local RD days for leap second T-2' ); is( $t->{local_rd_secs}, 82798, 'local RD seconds for leap second T-2' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 22, minute => 59, second => 59, time_zone => '-0100', ); is( $t->second, 59, 'second value for leap second T-1, -0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-1' ); is( $t->{utc_rd_secs}, 86399, 'UTC RD seconds for leap second T-1' ); is( $t->{local_rd_days}, 720074, 'local RD days for leap second T-1' ); is( $t->{local_rd_secs}, 82799, 'local RD seconds for leap second T-1' ); } { my $t = eval { DateTime->new( year => 1972, month => 6, day => 30, hour => 22, minute => 59, second => 60, time_zone => '-0100', ); }; ok( !$@, 'constructor for second = 60' ); SKIP: { skip 'constructor failed - no object to test', 5 unless $t; is( $t->second, 60, 'second value for leap second T-0, -0100' ); is( $t->{utc_rd_days}, 720074, 'UTC RD days for leap second T-0' ); is( $t->{utc_rd_secs}, 86400, 'UTC RD seconds for leap second T-0' ); is( $t->{local_rd_days}, 720074, 'local RD days for leap second T-0' ); is( $t->{local_rd_secs}, 82800, 'local RD seconds for leap second T-0' ); } } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 0, second => 0, time_zone => '-0100', ); is( $t->second, 0, 'second value for leap second T+1, -0100' ); is( $t->{utc_rd_days}, 720075, 'UTC RD days for leap second T+1' ); is( $t->{utc_rd_secs}, 0, 'UTC RD seconds for leap second T+1' ); is( $t->{local_rd_days}, 720074, 'local RD days for leap second T+1' ); is( $t->{local_rd_secs}, 82801, 'local RD seconds for leap second T+1' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 0, second => 1, time_zone => '-0100', ); is( $t->second, 1, 'second value for leap second T+2, -0100' ); is( $t->{utc_rd_days}, 720075, 'UTC RD days for leap second T+2' ); is( $t->{utc_rd_secs}, 1, 'UTC RD seconds for leap second T+2' ); is( $t->{local_rd_days}, 720074, 'local RD days for leap second T+2' ); is( $t->{local_rd_secs}, 82802, 'local RD seconds for leap second T+2' ); } done_testing(); DateTime-1.46/xt/author/pp-is-loaded.t0000644000175000017500000000050113240151623017371 0ustar autarchautarchuse strict; use warnings; use Test::More; BEGIN { ## no critic (Variables::RequireLocalizedPunctuationVars) $ENV{PERL_DATETIME_PP} = 1; } use DateTime; ## no critic (Variables::ProhibitPackageVars) ok( $DateTime::IsPurePerl, 'PurePerl implementation is loaded when env var is set' ); done_testing(); DateTime-1.46/xt/author/pp-42duration-class.t0000644000175000017500000000123113240151623020627 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } ## no critic (Modules::ProhibitMultiplePackages) use strict; use warnings; use Test::More; use DateTime; { package DateTime::MySubclass; use base 'DateTime'; sub duration_class {'DateTime::Duration::MySubclass'} package DateTime::Duration::MySubclass; use base 'DateTime::Duration'; sub is_my_subclass {1} } my $dt = DateTime::MySubclass->now; my $delta = $dt - $dt; isa_ok( $delta, 'DateTime::Duration::MySubclass' ); isa_ok( $dt + $delta, 'DateTime::MySubclass' ); my $delta_days = $dt->delta_days($dt); isa_ok( $delta_days, 'DateTime::Duration::MySubclass' ); done_testing(); DateTime-1.46/xt/author/pp-43new-params.t0000644000175000017500000000431213240151623017755 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; like( exception { DateTime->new( year => 10.5 ) }, qr/Validation failed for type named Year/, 'year must be an integer' ); like( exception { DateTime->new( year => -10.5 ) }, qr/Validation failed for type named Year/, 'year must be an integer' ); like( exception { DateTime->new( year => 10, month => 2.5 ) }, qr/Validation failed for type named Month/, 'month must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12.4 ) }, qr/Validation failed for type named DayOfMonth/, 'day must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12, hour => 4.1 ); }, qr/Validation failed for type named Hour/, 'hour must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12, hour => 4, minute => 12.2 ); }, qr/Validation failed for type named Minute/, 'minute must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12, hour => 4, minute => 12, second => 51.8 ); }, qr/Validation failed for type named Second/, 'second must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12, hour => 4, minute => 12, second => 51, nanosecond => 124512.12412 ); }, qr/Validation failed for type named Nanosecond/, 'nanosecond must be an integer' ); like( exception { DateTime->new( year => 10, month => 2, day => 12 )->today; }, qr/called with reference/, 'today must be called as a class method, not an object method' ); like( exception { DateTime->new( year => 10, month => 2, day => 12 )->now; }, qr/called with reference/, 'now must be called as a class method, not an object method' ); done_testing(); DateTime-1.46/xt/author/pod-syntax.t0000644000175000017500000000025213240151623017224 0ustar autarchautarch#!perl # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); DateTime-1.46/xt/author/pp-44set-formatter.t0000644000175000017500000000135713240151623020506 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; use overload; my $dt = DateTime->now; like( exception { $dt->set_formatter('Invalid::Formatter') }, qr/\QValidation failed for type named Maybe[Formatter]/, 'set_format is validated' ); SKIP: { ## no critic (BuiltinFunctions::ProhibitStringyEval) skip 'This test requires DateTime::Format::Strptime 1.2000+', 1 unless eval 'use DateTime::Format::Strptime 1.2000; 1;'; my $formatter = DateTime::Format::Strptime->new( pattern => '%Y%m%d %T', ); is( $dt->set_formatter($formatter), $dt, 'set_formatter returns the datetime object' ); } done_testing(); DateTime-1.46/xt/author/pp-17set-return.t0000644000175000017500000000201413240151623020011 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; use DateTime::Duration; { my $dt = DateTime->new( year => 2008, month => 2, day => 28 ); my $du = DateTime::Duration->new( years => 1 ); my $p; $p = $dt->set( year => 1882 ); is( DateTime->compare( $p, $dt ), 0, 'set returns self' ); $p = $dt->set_time_zone('Australia/Sydney'); is( DateTime->compare( $p, $dt ), 0, 'set_time_zone returns self' ); $p = $dt->add_duration($du); is( DateTime->compare( $p, $dt ), 0, 'add_duration returns self' ); $p = $dt->add( years => 2 ); is( DateTime->compare( $p, $dt ), 0, 'add returns self' ); $p = $dt->subtract_duration($du); is( DateTime->compare( $p, $dt ), 0, 'subtract_duration returns self' ); $p = $dt->subtract( years => 3 ); is( DateTime->compare( $p, $dt ), 0, 'subtract returns self' ); $p = $dt->truncate( to => 'day' ); is( DateTime->compare( $p, $dt ), 0, 'truncate returns self' ); } done_testing(); DateTime-1.46/xt/author/pp-33seconds-offset.t0000644000175000017500000000405513240151623020630 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 58, second => 59, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-06-30T23:59:29', '+00:00:30 leap second T-61' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 29, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-06-30T23:59:59', '+00:00:30 leap second T-31' ); } { local $TODO = 'offsets with seconds are broken near leap seconds'; my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 30, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-06-30T23:59:60', '+00:00:30 leap second T-30' ); } { local $TODO = 'offsets with seconds are broken near leap seconds'; my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 31, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-07-01T00:00:00', '+00:00:30 leap second T-29' ); } { local $TODO = 'offsets with seconds are broken near leap seconds'; my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 60, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-07-01T00:00:30', '+00:00:30 leap second T-0' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 0, minute => 0, second => 0, time_zone => 'UTC' ); $dt->set_time_zone('+00:00:30'); is( $dt->datetime, '1997-07-01T00:00:30', '+00:00:30 leap second T+1' ); } done_testing(); DateTime-1.46/xt/author/pp-13strftime.t0000644000175000017500000002734713240151623017552 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } # test suite stolen shamelessly from TimeDate distro use strict; use warnings; use utf8; use Test::More 0.96; use DateTime; use DateTime::Locale; test_strftime_for_locale( 'en-US', en_tests() ); test_strftime_for_locale( 'de', de_tests() ); test_strftime_for_locale( 'it', it_tests() ); subtest( 'strftime with multiple params', sub { my $dt = DateTime->new( year => 1800, month => 1, day => 10, time_zone => 'UTC', ); my ( $y, $d ) = $dt->strftime( '%Y', '%d' ); is( $y, 1800, 'first value is year' ); is( $d, 10, 'second value is day' ); $y = $dt->strftime( '%Y', '%d' ); is( $y, 1800, 'scalar context returns year' ); } ); subtest( 'hour formatting', sub { my $dt = DateTime->new( year => 2003, hour => 0, minute => 0 ); is( $dt->strftime('%I %M %p'), '12 00 AM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), '12 00 AM', 'formatting of hours as 1-12' ); $dt->set( hour => 1 ); is( $dt->strftime('%I %M %p'), '01 00 AM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), ' 1 00 AM', 'formatting of hours as 1-12' ); $dt->set( hour => 11 ); is( $dt->strftime('%I %M %p'), '11 00 AM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), '11 00 AM', 'formatting of hours as 1-12' ); $dt->set( hour => 12 ); is( $dt->strftime('%I %M %p'), '12 00 PM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), '12 00 PM', 'formatting of hours as 1-12' ); $dt->set( hour => 13 ); is( $dt->strftime('%I %M %p'), '01 00 PM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), ' 1 00 PM', 'formatting of hours as 1-12' ); $dt->set( hour => 23 ); is( $dt->strftime('%I %M %p'), '11 00 PM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), '11 00 PM', 'formatting of hours as 1-12' ); $dt->set( hour => 0 ); is( $dt->strftime('%I %M %p'), '12 00 AM', 'formatting of hours as 1-12' ); is( $dt->strftime('%l %M %p'), '12 00 AM', 'formatting of hours as 1-12' ); } ); subtest( '%V', sub { is( DateTime->new( year => 2003, month => 1, day => 1 ) ->strftime('%V'), '01', '%V is 01' ); } ); subtest( '%% and %{method}', sub { my $dt = DateTime->new( year => 2004, month => 8, day => 16, hour => 15, minute => 30, nanosecond => 123456789, locale => 'en', ); # Should print '%{day_name}', prints '30onday'! is( $dt->strftime('%%{day_name}%n'), "%{day_name}\n", '%%{day_name}%n bug' ); # Should print '%6N', prints '123456' is( $dt->strftime('%%6N%n'), "%6N\n", '%%6N%n bug' ); } ); subtest( 'nanosecond formatting', sub { subtest( 'nanosecond floating point rounding', sub { # Internally this becomes 119999885 nanoseconds (floating point math is awesome) my $epoch = 1297777805.12; my $dt = DateTime->from_epoch( epoch => $epoch ); my @vals = ( 1, 12, 120, 1200, 12000, 120000, 1200000, 12000000, 120000000, 1200000000, ); my $x = 1; for my $val (@vals) { my $spec = '%' . $x++ . 'N'; is( $dt->strftime($spec), $val, "strftime($spec) for $epoch == $val" ); } } ); subtest( 'nanosecond rounding in strftime', sub { my $dt = DateTime->new( 'year' => 1999, month => 9, day => 7, hour => 13, minute => 2, second => 42, nanosecond => 12345678, ); my %tests = ( '%N' => '012345678', '%3N' => '012', '%6N' => '012345', '%10N' => '0123456780', ); for my $fmt ( sort keys %tests ) { is( $dt->strftime($fmt), $tests{$fmt}, "$fmt is $tests{$fmt}" ); } } ); } ); subtest( '0 nanoseconds', sub { my $dt = DateTime->new( year => 2011 ); for my $i ( 1 .. 9 ) { my $spec = '%' . $i . 'N'; my $expect = '0' x $i; is( $dt->strftime($spec), $expect, "strftime $spec with 0 nanoseconds" ); } } ); subtest( 'week-year formatting', sub { my $dt = DateTime->new( 'year' => 2012, month => 1, day => 1 ); subtest( $dt->ymd, sub { my %tests = ( '%U' => '01', '%W' => '00', '%j' => '001', ); for my $fmt ( sort keys %tests ) { is( $dt->strftime($fmt), $tests{$fmt}, "$fmt is $tests{$fmt}" ); } } ); $dt = DateTime->new( 'year' => 2012, month => 1, day => 10 ); subtest( $dt->ymd, sub { my %tests = ( '%U' => '02', '%W' => '02', '%j' => '010', ); for my $fmt ( sort keys %tests ) { is( $dt->strftime($fmt), $tests{$fmt}, "$fmt is $tests{$fmt}" ); } } ); } ); done_testing(); sub test_strftime_for_locale { my $locale = shift; my $tests = shift; my $dt = DateTime->new( year => 1999, month => 9, day => 7, hour => 13, minute => 2, second => 42, nanosecond => 123456789, time_zone => 'UTC', locale => $locale, ); subtest( $locale, sub { for my $fmt ( sort keys %{$tests} ) { is( $dt->strftime($fmt), $tests->{$fmt}, "$fmt is $tests->{$fmt}" ); } } ); } sub en_tests { my $en_locale = DateTime::Locale->load('en-US'); my $c_format = $en_locale->datetime_format; $c_format =~ s/\{1\}/$en_locale->month_format_abbreviated->[8] . ' 7, 1999'/e; $c_format =~ s/\{0\}/'1:02:42 ' . $en_locale->am_pm_abbreviated->[1]/e; return { '%%' => '%', '%a' => $en_locale->day_format_abbreviated->[1], '%A' => $en_locale->day_format_wide->[1], '%b' => $en_locale->month_format_abbreviated->[8], '%B' => $en_locale->month_format_wide->[8], '%C' => '19', '%d' => '07', '%e' => ' 7', '%D' => '09/07/99', '%h' => $en_locale->month_format_abbreviated->[8], '%H' => '13', '%I' => '01', '%j' => '250', '%k' => '13', '%l' => ' 1', '%m' => '09', '%M' => '02', '%N' => '123456789', '%3N' => '123', '%6N' => '123456', '%10N' => '1234567890', '%p' => $en_locale->am_pm_abbreviated->[1], '%r' => '01:02:42 ' . $en_locale->am_pm_abbreviated->[1], '%R' => '13:02', '%s' => '936709362', '%S' => '42', '%T' => '13:02:42', '%U' => '36', '%V' => '36', '%w' => '2', '%W' => '36', '%y' => '99', '%Y' => '1999', '%Z' => 'UTC', '%z' => '+0000', '%E' => '%E', '%{foobar}' => '%{foobar}', '%{month}' => '9', '%{year}' => '1999', '%x' => $en_locale->month_format_abbreviated->[8] . ' 7, 1999', '%X' => '1:02:42 ' . $en_locale->am_pm_abbreviated->[1], '%c' => $c_format, }; } sub de_tests { my $de_locale = DateTime::Locale->load('de'); return { '%%' => '%', '%a' => $de_locale->day_format_abbreviated->[1], '%A' => $de_locale->day_format_wide->[1], '%b' => $de_locale->month_format_abbreviated->[8], '%B' => $de_locale->month_format_wide->[8], '%C' => '19', '%d' => '07', '%e' => ' 7', '%D' => '09/07/99', '%b' => $de_locale->month_format_abbreviated->[8], '%H' => '13', '%I' => '01', '%j' => '250', '%k' => '13', '%l' => ' 1', '%m' => '09', '%M' => '02', '%p' => $de_locale->am_pm_abbreviated->[1], '%r' => '01:02:42 ' . $de_locale->am_pm_abbreviated->[1], '%R' => '13:02', '%s' => '936709362', '%S' => '42', '%T' => '13:02:42', '%U' => '36', '%V' => '36', '%w' => '2', '%W' => '36', '%y' => '99', '%Y' => '1999', '%Z' => 'UTC', '%z' => '+0000', '%{month}' => '9', '%{year}' => '1999', }; } sub it_tests { my $it_locale = DateTime::Locale->load('it'); return { '%%' => '%', '%a' => $it_locale->day_format_abbreviated->[1], '%A' => $it_locale->day_format_wide->[1], '%b' => $it_locale->month_format_abbreviated->[8], '%B' => $it_locale->month_format_wide->[8], '%C' => '19', '%d' => '07', '%e' => ' 7', '%D' => '09/07/99', '%b' => $it_locale->month_format_abbreviated->[8], '%H' => '13', '%I' => '01', '%j' => '250', '%k' => '13', '%l' => ' 1', '%m' => '09', '%M' => '02', '%p' => $it_locale->am_pm_abbreviated->[1], '%r' => '01:02:42 ' . $it_locale->am_pm_abbreviated->[1], '%R' => '13:02', '%s' => '936709362', '%S' => '42', '%T' => '13:02:42', '%U' => '36', '%V' => '36', '%w' => '2', '%W' => '36', '%y' => '99', '%Y' => '1999', '%Z' => 'UTC', '%z' => '+0000', '%{month}' => '9', '%{year}' => '1999', }; } DateTime-1.46/xt/author/pod-spell.t0000644000175000017500000000263413240151623017023 0ustar autarchautarchuse strict; use warnings; use Test::More; # generated by Dist::Zilla::Plugin::Test::PodSpelling 2.007005 use Test::Spelling 0.12; use Pod::Wordlist; add_stopwords(); all_pod_files_spelling_ok( qw( bin lib ) ); __DATA__ 1nickt Alders Anno BCE Bell Ben Bennett BooK Book Bowen Bruhat CLDR CPAN Ceccarelli Christian Conflicts Conrad DATETIME DROLSKY DROLSKY's Daisuke Dan DateTime DateTimes Datetime Datetimes Dave David Davis Domini Doug Duration EEEE EEEEE Etheridge Flávio Formatters GGGG GGGGG Gianni Glock Gregory Hansen Hant Hauke Helpers Hill Hoblitt IEEE Iain Infinite Jason Joshua Karen Kington LLL LLLL LLLLL LeapSecond Liang Liang's MMM MMMM MMMMM Maki McIntosh Measham Measham's Michael Nick Olaf Oschwald Ovid POSIX PP PPExtra PayPal Philippe Precious QQQ QQQQ Rata Ricardo Richard Rolsky Rolsky's Ron SU Sam Signes Soibelmann Somerville Stewart Storable TW TZ Tonkin Truskett Tsai Types UTC VVVV Wheeler YAPCs ZZZZ ZZZZZ afterwards autarch bian book bowen ccc cccc ccccc chansen conformant curtis_ovid_poe danielandrewstewart datetime datetime's datetimes david davidp deceased decrement dian dmaki dracos drolsky durations eee eeee eeeee ether fallback fglock fiji formatter gianni github grinnz haukex hh iCal jhoblitt ji jmac lib madcityzen mike mrdvt92 mutiplication na namespace ni nitty olaf oschwald other's proleptic qqq qqqq rjbs rkhill sexagesimal subclasses uu viviparous vvvv wiki yy yyyy yyyyy zh zzzz DateTime-1.46/xt/author/pp-03components.t0000644000175000017500000003376713240151623020104 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::More; use DateTime; { my $d = DateTime->new( year => 2001, month => 7, day => 5, hour => 2, minute => 12, second => 50, time_zone => 'UTC', ); is( $d->year, 2001, '->year' ); is( $d->ce_year, 2001, '->ce_year' ); is( $d->month, 7, '->month' ); is( $d->quarter, 3, '->quarter' ); is( $d->month_0, 6, '->month_0' ); is( $d->month_name, 'July', '->month_name' ); is( $d->month_abbr, 'Jul', '->month_abbr' ); is( $d->day_of_month, 5, '->day_of_month' ); is( $d->day_of_month_0, 4, '->day_of_month_0' ); is( $d->day, 5, '->day' ); is( $d->day_0, 4, '->day_0' ); is( $d->mday, 5, '->mday' ); is( $d->mday_0, 4, '->mday_0' ); is( $d->mday, 5, '->mday' ); is( $d->mday_0, 4, '->mday_0' ); is( $d->hour, 2, '->hour' ); is( $d->hour_1, 2, '->hour_1' ); is( $d->hour_12, 2, '->hour_12' ); is( $d->hour_12_0, 2, '->hour_12_0' ); is( $d->minute, 12, '->minute' ); is( $d->min, 12, '->min' ); is( $d->second, 50, '->second' ); is( $d->sec, 50, '->sec' ); is( $d->day_of_year, 186, '->day_of_year' ); is( $d->day_of_year_0, 185, '->day_of_year' ); is( $d->day_of_quarter, 5, '->day_of_quarter' ); is( $d->doq, 5, '->doq' ); is( $d->day_of_quarter_0, 4, '->day_of_quarter_0' ); is( $d->doq_0, 4, '->doq_0' ); is( $d->day_of_week, 4, '->day_of_week' ); is( $d->day_of_week_0, 3, '->day_of_week_0' ); is( $d->week_of_month, 1, '->week_of_month' ); is( $d->weekday_of_month, 1, '->weekday_of_month' ); is( $d->wday, 4, '->wday' ); is( $d->wday_0, 3, '->wday_0' ); is( $d->dow, 4, '->dow' ); is( $d->dow_0, 3, '->dow_0' ); is( $d->day_name, 'Thursday', '->day_name' ); is( $d->day_abbr, 'Thu', '->day_abrr' ); is( $d->ymd, '2001-07-05', '->ymd' ); is( $d->ymd('!'), '2001!07!05', q{->ymd('!')} ); is( $d->date, '2001-07-05', '->date' ); is( $d->date('!'), '2001!07!05', q{->date('!')} ); is( $d->mdy, '07-05-2001', '->mdy' ); is( $d->mdy('!'), '07!05!2001', q{->mdy('!')} ); is( $d->dmy, '05-07-2001', '->dmy' ); is( $d->dmy('!'), '05!07!2001', q{->dmy('!')} ); is( $d->hms, '02:12:50', '->hms' ); is( $d->hms('!'), '02!12!50', q{->hms('!')} ); is( $d->time, '02:12:50', '->hms' ); is( $d->time('!'), '02!12!50', q{->time('!')} ); is( $d->datetime, '2001-07-05T02:12:50', '->datetime' ); is( $d->datetime(q{ }), '2001-07-05 02:12:50', q{->datetime(q{ }} ); is( $d->iso8601, '2001-07-05T02:12:50', '->iso8601' ); is( $d->iso8601(q{ }), '2001-07-05T02:12:50', '->iso8601 ignores arguments' ); ok( !$d->is_leap_year, '->is_leap_year' ); ok( !$d->is_last_day_of_month, '->is_last_day_of_month' ); is( $d->month_length, 31, '->month_length' ); is( $d->quarter_length, 92, '->quarter_length' ); is( $d->year_length, 365, '->year_length' ); is( $d->era_abbr, 'AD', '->era_abbr' ); is( $d->era, $d->era_abbr, '->era (deprecated)' ); is( $d->era_name, 'Anno Domini', '->era_abbr' ); is( $d->quarter_abbr, 'Q3', '->quarter_abbr' ); is( $d->quarter_name, '3rd quarter', '->quarter_name' ); } { my $leap_d = DateTime->new( year => 2004, month => 7, day => 5, hour => 2, minute => 12, second => 50, time_zone => 'UTC', ); ok( $leap_d->is_leap_year, '->is_leap_year' ); is( $leap_d->year_length, 366, '->year_length' ); } { my @tests = ( { year => 2017, month => 8, day => 19, expect => 0 }, { year => 2017, month => 8, day => 31, expect => 1 }, { year => 2017, month => 2, day => 28, expect => 1 }, { year => 2016, month => 2, day => 28, expect => 0 }, ); for my $t (@tests) { my $expect = delete $t->{expect}; my $dt = DateTime->new($t); my $is = $dt->is_last_day_of_month; ok( ( $expect ? $is : !$is ), '->is_last_day_of_month' ); } } { my @tests = ( { year => 2016, month => 2, day => 1, expect => 29 }, { year => 2017, month => 2, day => 1, expect => 28 }, ); for my $t (@tests) { my $expect = delete $t->{expect}; my $dt = DateTime->new($t); is( $dt->month_length, $expect, '->month_length' ); } } { my $sunday = DateTime->new( year => 2003, month => 1, day => 26, time_zone => 'UTC', ); is( $sunday->day_of_week, 7, 'Sunday is day 7' ); } { my $monday = DateTime->new( year => 2003, month => 1, day => 27, time_zone => 'UTC', ); is( $monday->day_of_week, 1, 'Monday is day 1' ); } { # time zone offset should not affect the values returned my $d = DateTime->new( year => 2001, month => 7, day => 5, hour => 2, minute => 12, second => 50, time_zone => '-0124', ); is( $d->year, 2001, '->year' ); is( $d->ce_year, 2001, '->ce_year' ); is( $d->month, 7, '->month' ); is( $d->day_of_month, 5, '->day_of_month' ); is( $d->hour, 2, '->hour' ); is( $d->hour_1, 2, '->hour_1' ); is( $d->minute, 12, '->minute' ); is( $d->second, 50, '->second' ); } { my $dt0 = DateTime->new( year => 1, time_zone => 'UTC' ); is( $dt0->year, 1, 'year 1 is year 1' ); is( $dt0->ce_year, 1, 'ce_year 1 is year 1' ); is( $dt0->era_abbr, 'AD', 'era is AD' ); is( $dt0->year_with_era, '1AD', 'year_with_era is 1AD' ); is( $dt0->christian_era, 'AD', 'christian_era is AD' ); is( $dt0->year_with_christian_era, '1AD', 'year_with_christian_era is 1AD' ); is( $dt0->secular_era, 'CE', 'secular_era is CE' ); is( $dt0->year_with_secular_era, '1CE', 'year_with_secular_era is 1CE' ); $dt0->subtract( years => 1 ); is( $dt0->year, 0, 'year 1 minus 1 is year 0' ); is( $dt0->ce_year, -1, 'ce_year 1 minus 1 is year -1' ); is( $dt0->era_abbr, 'BC', 'era is BC' ); is( $dt0->year_with_era, '1BC', 'year_with_era is 1BC' ); is( $dt0->christian_era, 'BC', 'christian_era is BC' ); is( $dt0->year_with_christian_era, '1BC', 'year_with_christian_era is 1BC' ); is( $dt0->secular_era, 'BCE', 'secular_era is BCE' ); is( $dt0->year_with_secular_era, '1BCE', 'year_with_secular_era is 1BCE' ); } { my $dt_neg = DateTime->new( year => -10, time_zone => 'UTC', ); is( $dt_neg->year, -10, 'Year -10 is -10' ); is( $dt_neg->ce_year, -11, 'year -10 is ce_year -11' ); my $dt1 = $dt_neg + DateTime::Duration->new( years => 10 ); is( $dt1->year, 0, 'year is 0 after adding ten years to year -10' ); is( $dt1->ce_year, -1, 'ce_year is -1 after adding ten years to year -10' ); } { my $dt = DateTime->new( year => 50, month => 2, hour => 3, minute => 20, second => 5, time_zone => 'UTC', ); is( $dt->ymd('%s'), '0050%s02%s01', 'use %s as separator in ymd' ); is( $dt->mdy('%s'), '02%s01%s0050', 'use %s as separator in mdy' ); is( $dt->dmy('%s'), '01%s02%s0050', 'use %s as separator in dmy' ); is( $dt->hms('%s'), '03%s20%s05', 'use %s as separator in hms' ); } # test doy in leap year { my $dt = DateTime->new( year => 2000, month => 1, day => 5, time_zone => 'UTC', ); is( $dt->day_of_year, 5, 'doy for 2000-01-05 should be 5' ); is( $dt->day_of_year_0, 4, 'doy_0 for 2000-01-05 should be 4' ); } { my $dt = DateTime->new( year => 2000, month => 2, day => 29, time_zone => 'UTC', ); is( $dt->day_of_year, 60, 'doy for 2000-02-29 should be 60' ); is( $dt->day_of_year_0, 59, 'doy_0 for 2000-02-29 should be 59' ); } { my $dt = DateTime->new( year => -6, month => 2, day => 25, time_zone => 'UTC', ); is( $dt->ymd, '-0006-02-25', 'ymd is -0006-02-25' ); is( $dt->iso8601, '-0006-02-25T00:00:00', 'iso8601 is -0005-02-25T00:00:00' ); is( $dt->year, -6, 'year is -6' ); is( $dt->ce_year, -7, 'ce_year is -7' ); } { my $dt = DateTime->new( year => 1995, month => 2, day => 1 ); is( $dt->quarter, 1, '->quarter is 1' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 90, '->quarter_length' ); } { my $dt = DateTime->new( year => 1995, month => 5, day => 1 ); is( $dt->quarter, 2, '->quarter is 2' ); is( $dt->day_of_quarter, 31, '->day_of_quarter' ); is( $dt->quarter_length, 91, '->quarter_length' ); } { my $dt = DateTime->new( year => 1995, month => 8, day => 1 ); is( $dt->quarter, 3, '->quarter is 3' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 92, '->quarter_length' ); } { my $dt = DateTime->new( year => 1995, month => 11, day => 1 ); is( $dt->quarter, 4, '->quarter is 4' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 92, '->quarter_length' ); } { my $dt = DateTime->new( year => 1996, month => 2, day => 1 ); is( $dt->quarter, 1, '->quarter is 1' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 91, '->quarter_length' ); } { my $dt = DateTime->new( year => 1996, month => 5, day => 1 ); is( $dt->quarter, 2, '->quarter is 2' ); is( $dt->day_of_quarter, 31, '->day_of_quarter' ); is( $dt->quarter_length, 91, '->quarter_length' ); } { my $dt = DateTime->new( year => 1996, month => 8, day => 1 ); is( $dt->quarter, 3, '->quarter is 3' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 92, '->quarter_length' ); } { my $dt = DateTime->new( year => 1996, month => 11, day => 1 ); is( $dt->quarter, 4, '->quarter is 4' ); is( $dt->day_of_quarter, 32, '->day_of_quarter' ); is( $dt->quarter_length, 92, '->quarter_length' ); } # nano, micro, and milli seconds { my $dt = DateTime->new( year => 1996, nanosecond => 500_000_000 ); is( $dt->nanosecond, 500_000_000, 'nanosecond is 500,000,000' ); is( $dt->microsecond, 500_000, 'microsecond is 500,000' ); is( $dt->millisecond, 500, 'millisecond is 500' ); $dt->set( nanosecond => 500_000_500 ); is( $dt->nanosecond, 500_000_500, 'nanosecond is 500,000,500' ); is( $dt->microsecond, 500_000, 'microsecond is 500,000' ); is( $dt->millisecond, 500, 'millisecond is 500' ); $dt->set( nanosecond => 499_999_999 ); is( $dt->nanosecond, 499_999_999, 'nanosecond is 499,999,999' ); is( $dt->microsecond, 499_999, 'microsecond is 499,999' ); is( $dt->millisecond, 499, 'millisecond is 499' ); $dt->set( nanosecond => 450_000_001 ); is( $dt->nanosecond, 450_000_001, 'nanosecond is 450,000,001' ); is( $dt->microsecond, 450_000, 'microsecond is 450,000' ); is( $dt->millisecond, 450, 'millisecond is 450' ); $dt->set( nanosecond => 450_500_000 ); is( $dt->nanosecond, 450_500_000, 'nanosecond is 450,500,000' ); is( $dt->microsecond, 450_500, 'microsecond is 450,500' ); is( $dt->millisecond, 450, 'millisecond is 450' ); } { my $dt = DateTime->new( year => 2003, month => 5, day => 7 ); is( $dt->weekday_of_month, 1, '->weekday_of_month' ); is( $dt->week_of_month, 2, '->week_of_month' ); } { my $dt = DateTime->new( year => 2003, month => 5, day => 8 ); is( $dt->weekday_of_month, 2, '->weekday_of_month' ); is( $dt->week_of_month, 2, '->week_of_month' ); } { my $dt = DateTime->new( year => 1000, hour => 23 ); is( $dt->hour, 23, '->hour' ); is( $dt->hour_1, 23, '->hour_1' ); is( $dt->hour_12, 11, '->hour_12' ); is( $dt->hour_12_0, 11, '->hour_12_0' ); } { my $dt = DateTime->new( year => 1000, hour => 0 ); is( $dt->hour, 0, '->hour' ); is( $dt->hour_1, 24, '->hour_1' ); is( $dt->hour_12, 12, '->hour_12' ); is( $dt->hour_12_0, 0, '->hour_12_0' ); } SKIP: { ## no critic (BuiltinFunctions::ProhibitStringyEval) skip 'These tests require Test::Warn', 9 unless eval 'use Test::Warn; 1'; my $dt = DateTime->new( year => 2000 ); warnings_like( sub { $dt->year(2001) }, qr/is a read-only/, 'year() is read-only' ); warnings_like( sub { $dt->month(5) }, qr/is a read-only/, 'month() is read-only' ); warnings_like( sub { $dt->day(5) }, qr/is a read-only/, 'day() is read-only' ); warnings_like( sub { $dt->hour(5) }, qr/is a read-only/, 'hour() is read-only' ); warnings_like( sub { $dt->minute(5) }, qr/is a read-only/, 'minute() is read-only' ); warnings_like( sub { $dt->second(5) }, qr/is a read-only/, 'second() is read-only' ); warnings_like( sub { $dt->nanosecond(5) }, qr/is a read-only/, 'nanosecond() is read-only' ); warnings_like( sub { $dt->time_zone('America/Chicago') }, qr/is a read-only/, 'time_zone() is read-only' ); warnings_like( sub { $dt->locale('en_US') }, qr/is a read-only/, 'locale() is read-only' ); } done_testing(); DateTime-1.46/xt/author/pp-19leap-second.t0000644000175000017500000007345713240151623020120 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; use DateTime::LeapSecond; # tests using UTC times { # 1972-06-30T23:58:20 UTC my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); my $t1 = $t->clone; is( $t->year, 1972, 'year is 1972' ); is( $t->minute, 58, 'minute is 58' ); is( $t->second, 20, 'second is 20' ); # 1972-06-30T23:59:20 UTC $t->add( seconds => 60 ); is( $t->year, 1972, 'year is 1972' ); is( $t->minute, 59, 'minute is 59' ); is( $t->second, 20, 'second is 20' ); # 1972-07-01T00:00:19 UTC $t->add( seconds => 60 ); is( $t->year, 1972, 'year is 1972' ); is( $t->minute, 0, 'minute is 0' ); is( $t->second, 19, 'second is 19' ); # 1972-06-30T23:59:60 UTC $t->subtract( seconds => 20 ); is( $t->year, 1972, 'year is 1972' ); is( $t->minute, 59, 'minute is 59' ); is( $t->second, 60, 'second is 60' ); is( $t->{utc_rd_secs}, 86400, 'utc_rd_secs is 86400' ); # subtract_datetime my $t2 = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 0, second => 20, time_zone => 'UTC', ); my $dur = $t2->subtract_datetime_absolute($t1); is( $dur->delta_seconds, 121, 'delta_seconds is 121' ); $dur = $t1->subtract_datetime_absolute($t2); is( $dur->delta_seconds, -121, 'delta_seconds is -121' ); } { # tests using floating times # a floating time has no leap seconds my $t = DateTime->new( year => 1971, month => 12, day => 31, hour => 23, minute => 58, second => 20, time_zone => 'floating', ); my $t1 = $t->clone; $t->add( seconds => 60 ); is( $t->minute, 59, 'min' ); is( $t->second, 20, 'sec' ); $t->add( seconds => 60 ); is( $t->minute, 0, 'min' ); is( $t->second, 20, 'sec' ); # subtract_datetime, using floating times my $t2 = DateTime->new( year => 1972, month => 1, day => 1, hour => 0, minute => 0, second => 20, time_zone => 'floating', ); my $dur = $t2->subtract_datetime_absolute($t1); is( $dur->delta_seconds, 120, 'delta_seconds is 120' ); $dur = $t1->subtract_datetime_absolute($t2); is( $dur->delta_seconds, -120, 'delta_seconds is -120' ); } { # tests using time zones # leap seconds occur during _UTC_ midnight # 1972-06-30 20:58:20 -03:00 = 1972-06-30 23:58:20 UTC my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 58, second => 20, time_zone => 'America/Sao_Paulo', ); $t->add( seconds => 60 ); is( $t->datetime, '1972-06-30T20:59:20', 'normal add' ); is( $t->minute, 59, 'min' ); is( $t->second, 20, 'sec' ); $t->add( seconds => 60 ); is( $t->datetime, '1972-06-30T21:00:19', 'add over a leap second' ); is( $t->minute, 0, 'min' ); is( $t->second, 19, 'sec' ); $t->subtract( seconds => 20 ); is( $t->datetime, '1972-06-30T20:59:60', 'subtract over a leap second' ); is( $t->minute, 59, 'min' ); is( $t->second, 60, 'sec' ); is( $t->{utc_rd_secs}, 86400, 'rd_sec' ); } # test that we can set second to 60 (negative offset) { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 59, second => 60, time_zone => 'America/Sao_Paulo', ); is( $t->second, 60, 'second set to 60 in constructor' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 21, minute => 0, second => 0, time_zone => 'America/Sao_Paulo', ); is( $t->second, 0, 'datetime just after leap second' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 21, minute => 0, second => 1, time_zone => 'America/Sao_Paulo', ); is( $t->second, 1, 'datetime two seconds after leap second' ); } # test that we can set second to 60 (negative offset) { is( exception { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 22, minute => 59, second => 60, time_zone => '-0100', ); is( $t->second, 60, 'second set to 60 in constructor, negative TZ offset' ); }, undef, 'can set second to 60 in constructor' ); } # test that we can set second to 60 (positive offset) { is( exception { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 59, second => 60, time_zone => '+0100', ); is( $t->second, 60, 'second set to 60 in constructor, positive TZ offset' ); }, undef, 'can set second to 60 with positive TZ offset' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 59, second => 59, time_zone => '+0100', ); is( $t->second, 59, 'datetime just before leap second' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 1, minute => 0, second => 0, time_zone => '+0100', ); is( $t->second, 0, 'datetime just after leap second' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 1, minute => 0, second => 1, time_zone => '+0100', ); is( $t->second, 1, 'datetime two seconds after leap second' ); } { my $t = DateTime->new( year => 1972, month => 7, day => 1, hour => 0, minute => 0, second => 29, time_zone => '+00:00:30', ); is( $t->second, 29, 'time zone +00:00:30 and leap seconds, second value' ); is( $t->minute, 0, 'time zone +00:00:30 and leap seconds, minute value' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 59, second => 60, time_zone => 'America/Sao_Paulo', ); $t->set_time_zone('UTC'); is( $t->second, 60, 'second after setting time zone' ); is( $t->hour, 23, 'hour after setting time zone' ); $t->add( days => 1 ); is( $t->datetime, '1972-07-02T00:00:00', 'add 1 day starting on leap second' ); $t->subtract( days => 1 ); is( $t->datetime, '1972-07-01T00:00:00', 'add and subtract 1 day starting on leap second' ); is( $t->leap_seconds, 1, 'datetime has 1 leap second' ); } { my $t = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 59, second => 59, time_zone => 'UTC', ); is( $t->epoch, 78796799, 'epoch just before first leap second is 78796799' ); $t->add( seconds => 1 ); is( $t->epoch, 78796800, 'epoch of first leap second is 78796800' ); $t->add( seconds => 1 ); is( $t->epoch, 78796800, 'epoch of first second after first leap second is 78796700' ); } { my $dt = DateTime->new( year => 2003, time_zone => 'UTC' ); is( $dt->leap_seconds, 22, 'datetime has 22 leap seconds' ); } { my $dt = DateTime->new( year => 2003, time_zone => 'floating' ); is( $dt->leap_seconds, 0, 'floating datetime has 0 leap seconds' ); } # date math across leap seconds distinguishes between minutes and second { my $t = DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 30, time_zone => 'UTC' ); $t->add( minutes => 1 ); is( $t->year, 1973, '+1 minute, year == 1973' ); is( $t->month, 1, '+1 minute, month == 1' ); is( $t->day, 1, '+1 minute, day == 1' ); is( $t->hour, 0, '+1 minute, hour == 0' ); is( $t->minute, 0, '+1 minute, minute == 0' ); is( $t->second, 30, '+1 minute, second == 30' ); } { my $t = DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 30, time_zone => 'UTC' ); $t->add( seconds => 60 ); is( $t->year, 1973, '+60 seconds, year == 1973' ); is( $t->month, 1, '+60 seconds, month == 1' ); is( $t->day, 1, '+60 seconds, day == 1' ); is( $t->hour, 0, '+60 seconds, hour == 0' ); is( $t->minute, 0, '+60 seconds, minute == 0' ); is( $t->second, 29, '+60 seconds, second == 29' ); } { my $t = DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 30, time_zone => 'UTC' ); $t->add( minutes => 1, seconds => 1 ); is( $t->year, 1973, '+1 minute & 1 second, year == 1973' ); is( $t->month, 1, '+1 minute & 1 second, month == 1' ); is( $t->day, 1, '+1 minute & 1 second, day == 1' ); is( $t->hour, 0, '+1 minute & 1 second, hour == 0' ); is( $t->minute, 0, '+1 minute & 1 second, minute == 0' ); is( $t->second, 31, '+1 minute & 1 second, second == 31' ); } { ok( exception { DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 61, time_zone => 'UTC', ); }, 'Cannot give second of 61 except when it matches a leap second' ); ok( exception { DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 58, second => 60, time_zone => 'UTC', ); }, 'Cannot give second of 60 except when it matches a leap second' ); ok( exception { DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 60, time_zone => 'floating', ); }, 'Cannot give second of 60 with floating time zone' ); } { my $dt1 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 59, second => 60, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 58, second => 50, time_zone => 'UTC', ); my $pos_dur = $dt1 - $dt2; is( $pos_dur->delta_minutes, 1, 'delta_minutes is 1' ); is( $pos_dur->delta_seconds, 10, 'delta_seconds is 10' ); my $neg_dur = $dt2 - $dt1; is( $neg_dur->delta_minutes, -1, 'delta_minutes is -1' ); is( $neg_dur->delta_seconds, -10, 'delta_seconds is -10' ); } { my $dt1 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 59, second => 55, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 58, second => 50, time_zone => 'UTC', ); my $pos_dur = $dt1 - $dt2; is( $pos_dur->delta_minutes, 1, 'delta_minutes is 1' ); is( $pos_dur->delta_seconds, 5, 'delta_seconds is 5' ); my $neg_dur = $dt2 - $dt1; is( $neg_dur->delta_minutes, -1, 'delta_minutes is -1' ); is( $neg_dur->delta_seconds, -5, 'delta_seconds is -5' ); } { my $dt1 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 59, second => 55, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 1999, month => 1, day => 1, hour => 0, minute => 0, second => 30, time_zone => 'UTC', ); my $pos_dur = $dt2 - $dt1; is( $pos_dur->delta_minutes, 0, 'delta_minutes is 0' ); is( $pos_dur->delta_seconds, 36, 'delta_seconds is 36' ); my $neg_dur = $dt1 - $dt2; is( $neg_dur->delta_minutes, 0, 'delta_minutes is 0' ); is( $neg_dur->delta_seconds, -36, 'delta_seconds is -36' ); } # catch off-by-one when carrying a leap second { my $dt1 = DateTime->new( year => 1998, month => 12, day => 31, hour => 23, minute => 59, second => 0, nanosecond => 1, time_zone => 'UTC', ); my $dt2 = DateTime->new( year => 1999, month => 1, day => 1, hour => 0, minute => 0, second => 0, time_zone => 'UTC', ); my $pos_dur = $dt2 - $dt1; is( $pos_dur->delta_minutes, 0, 'delta_minutes is 0' ); is( $pos_dur->delta_seconds, 60, 'delta_seconds is 60' ); is( $pos_dur->delta_nanoseconds, 999999999, 'delta_nanoseconds is 999...' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->add( days => 2 ); is( $dt->datetime, '1972-07-02T23:58:20', 'add two days crossing a leap second (UTC)' ); } # a bunch of tests that math works across a leap second for various time zones { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->add( days => 2 ); is( $dt->datetime, '1972-07-02T20:58:20', 'add two days crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 1, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->add( days => 2 ); is( $dt->datetime, '1972-07-03T02:58:20', 'add two days crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->add( hours => 48 ); is( $dt->datetime, '1972-07-02T23:58:20', 'add 48 hours crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->add( hours => 48 ); is( $dt->datetime, '1972-07-02T20:58:20', 'add 48 hours crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 1, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->add( hours => 48 ); is( $dt->datetime, '1972-07-03T02:58:20', 'add 48 hours crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->add( minutes => 2880 ); is( $dt->datetime, '1972-07-02T23:58:20', 'add 2880 minutes crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->add( minutes => 2880 ); is( $dt->datetime, '1972-07-02T20:58:20', 'add 2880 minutes crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 1, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->add( minutes => 2880 ); is( $dt->datetime, '1972-07-03T02:58:20', 'add 2880 minutes crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->add( seconds => 172801 ); is( $dt->datetime, '1972-07-02T23:58:20', 'add 172801 seconds crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->add( seconds => 172801 ); is( $dt->datetime, '1972-07-02T20:58:20', 'add 172801 seconds crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 1, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->add( seconds => 172801 ); is( $dt->datetime, '1972-07-03T02:58:20', 'add 172801 seconds crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->subtract( days => 2 ); is( $dt->datetime, '1972-06-30T23:58:20', 'subtract two days crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->subtract( days => 2 ); is( $dt->datetime, '1972-06-30T20:58:20', 'subtract two days crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 3, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->subtract( days => 2 ); is( $dt->datetime, '1972-07-01T02:58:20', 'subtract two days crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->subtract( hours => 48 ); is( $dt->datetime, '1972-06-30T23:58:20', 'subtract 48 hours crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->subtract( hours => 48 ); is( $dt->datetime, '1972-06-30T20:58:20', 'subtract 48 hours crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 3, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->subtract( hours => 48 ); is( $dt->datetime, '1972-07-01T02:58:20', 'subtract 48 hours crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->subtract( minutes => 2880 ); is( $dt->datetime, '1972-06-30T23:58:20', 'subtract 2880 minutes crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->subtract( minutes => 2880 ); is( $dt->datetime, '1972-06-30T20:58:20', 'subtract 2880 minutes crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 3, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->subtract( minutes => 2880 ); is( $dt->datetime, '1972-07-01T02:58:20', 'subtract 2880 minutes crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 23, minute => 58, second => 20, time_zone => 'UTC', ); $dt->subtract( seconds => 172801 ); is( $dt->datetime, '1972-06-30T23:58:20', 'subtract 172801 seconds crossing a leap second (UTC)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 2, hour => 20, minute => 58, second => 20, time_zone => '-0300', ); $dt->subtract( seconds => 172801 ); is( $dt->datetime, '1972-06-30T20:58:20', 'subtract 172801 seconds crossing a leap second (-0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 3, hour => 2, minute => 58, second => 20, time_zone => '+0300', ); $dt->subtract( seconds => 172801 ); is( $dt->datetime, '1972-07-01T02:58:20', 'subtract 172801 seconds crossing a leap second (+0300)' ); } { my $dt = DateTime->new( year => 1972, month => 7, day => 1, hour => 12, minute => 58, second => 20, time_zone => '+1200', ); $dt->set_time_zone('-1200'); is( $dt->datetime, '1972-06-30T12:58:20', '24 hour time zone change near leap second' ); } { my $dt = DateTime->new( year => 1972, month => 6, day => 30, hour => 12, minute => 58, second => 20, time_zone => '-1200', ); $dt->set_time_zone('+1200'); is( $dt->datetime, '1972-07-01T12:58:20', '24 hour time zone change near leap second' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 0, minute => 59, second => 59, time_zone => '+0100' ); is( $dt->datetime, '1997-07-01T00:59:59', '+0100 time leap second T-1' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-06-30T23:59:59', 'UTC time leap second T-1' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 0, minute => 59, second => 60, time_zone => '+0100' ); is( $dt->datetime, '1997-07-01T00:59:60', 'local time leap second T-0' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-06-30T23:59:60', 'UTC time leap second T-0' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 1, minute => 0, second => 0, time_zone => '+0100' ); is( $dt->datetime, '1997-07-01T01:00:00', 'local time leap second T+1' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-07-01T00:00:00', 'UTC time leap second T+1' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 23, minute => 59, second => 59, time_zone => '+0100' ); is( $dt->datetime, '1997-07-01T23:59:59', 'local time end of leap second day' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-07-01T22:59:59', 'UTC time end of leap second day' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 22, minute => 59, second => 59, time_zone => '-0100' ); is( $dt->datetime, '1997-06-30T22:59:59', '-0100 time leap second T-1' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-06-30T23:59:59', 'UTC time leap second T-1' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 22, minute => 59, second => 60, time_zone => '-0100' ); is( $dt->datetime, '1997-06-30T22:59:60', '-0100 time leap second T-0' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-06-30T23:59:60', 'UTC time leap second T-0' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 0, second => 0, time_zone => '-0100' ); is( $dt->datetime, '1997-06-30T23:00:00', '-0100 time leap second T+1' ); $dt->set_time_zone('UTC'); is( $dt->datetime, '1997-07-01T00:00:00', 'UTC time leap second T+1' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 59, time_zone => 'UTC' ); is( $dt->datetime, '1997-06-30T23:59:59', 'UTC time leap second T-1' ); $dt->set_time_zone('+0100'); is( $dt->datetime, '1997-07-01T00:59:59', '+0100 time leap second T-1' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 60, time_zone => 'UTC' ); is( $dt->datetime, '1997-06-30T23:59:60', 'UTC time leap second T-0' ); $dt->set_time_zone('+0100'); is( $dt->datetime, '1997-07-01T00:59:60', '+0100 time leap second T-0' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 0, minute => 0, second => 0, time_zone => 'UTC' ); is( $dt->datetime, '1997-07-01T00:00:00', 'UTC time leap second T+1' ); $dt->set_time_zone('+0100'); is( $dt->datetime, '1997-07-01T01:00:00', '+0100 time leap second T+1' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 59, time_zone => 'UTC' ); is( $dt->datetime, '1997-06-30T23:59:59', 'UTC time end of leap second day' ); $dt->set_time_zone('+0100'); is( $dt->datetime, '1997-07-01T00:59:59', '+0100 time end of leap second day' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 59, time_zone => 'UTC' ); is( $dt->datetime, '1997-06-30T23:59:59', 'UTC time leap second T-1' ); $dt->set_time_zone('-0100'); is( $dt->datetime, '1997-06-30T22:59:59', '-0100 time leap second T-1' ); } { my $dt = DateTime->new( year => 1997, month => 6, day => 30, hour => 23, minute => 59, second => 60, time_zone => 'UTC' ); is( $dt->datetime, '1997-06-30T23:59:60', 'UTC time leap second T-0' ); $dt->set_time_zone('-0100'); is( $dt->datetime, '1997-06-30T22:59:60', '-0100 time leap second T-0' ); } { my $dt = DateTime->new( year => 1997, month => 7, day => 1, hour => 0, minute => 0, second => 0, time_zone => 'UTC' ); is( $dt->datetime, '1997-07-01T00:00:00', 'UTC time leap second T+1' ); $dt->set_time_zone('-0100'); is( $dt->datetime, '1997-06-30T23:00:00', '-0100 time leap second T+1' ); } { my $dt = DateTime->new( year => 2005, month => 12, day => 31, hour => 23, minute => 59, second => 60, time_zone => 'UTC' ); is( $dt->second, 60, 'leap second at end of 2005 is allowed' ); } { my $dt = DateTime->new( year => 2005, month => 12, day => 31, hour => 23, minute => 59, second => 59, time_zone => 'UTC', ); $dt->add( seconds => 1 ); is( $dt->datetime, '2005-12-31T23:59:60', 'dt is 2005-12-31T23:59:60' ); $dt->add( seconds => 1 ); is( $dt->datetime, '2006-01-01T00:00:00', 'dt is 2006-01-01T00:00:00' ); } # bug reported by Mike Schilli - addition got "stuck" at 60 seconds # and never rolled over to the following day { my $dt = DateTime->new( year => 2005, month => 12, day => 31, hour => 23, minute => 59, second => 59, time_zone => 'UTC', ); $dt->add( seconds => 1 ); is( $dt->datetime, '2005-12-31T23:59:60', 'dt is 2005-12-31T23:59:60' ); $dt->add( seconds => 1 ); is( $dt->datetime, '2006-01-01T00:00:00', 'dt is 2006-01-01T00:00:00' ); } # and this makes sure that fix for the above bug didn't break # _non-leapsecond_ second addition { my $dt = DateTime->new( year => 2005, month => 12, day => 30, hour => 23, minute => 59, second => 58, time_zone => 'UTC', ); $dt->add( seconds => 1 ); is( $dt->datetime, '2005-12-30T23:59:59', 'dt is 2005-12-30T23:59:59' ); $dt->add( seconds => 1 ); is( $dt->datetime, '2005-12-31T00:00:00', 'dt is 2005-12-31T00:00:00' ); } { for my $date ( [ 1972, 6, 30 ], [ 1972, 12, 31 ], [ 1973, 12, 31 ], [ 1974, 12, 31 ], [ 1975, 12, 31 ], [ 1976, 12, 31 ], [ 1977, 12, 31 ], [ 1978, 12, 31 ], [ 1979, 12, 31 ], [ 1981, 6, 30 ], [ 1982, 6, 30 ], [ 1983, 6, 30 ], [ 1985, 6, 30 ], [ 1987, 12, 31 ], [ 1989, 12, 31 ], [ 1990, 12, 31 ], [ 1992, 6, 30 ], [ 1993, 6, 30 ], [ 1994, 6, 30 ], [ 1995, 12, 31 ], [ 1997, 6, 30 ], [ 1998, 12, 31 ], [ 2005, 12, 31 ], [ 2008, 12, 31 ], [ 2012, 6, 30 ], [ 2015, 6, 30 ], [ 2016, 12, 31 ], ) { my $formatted = join '-', map { sprintf( '%02d', $_ ) } @{$date}; my $dt; is( exception { $dt = DateTime->new( year => $date->[0], month => $date->[1], day => $date->[2], hour => 23, minute => 59, second => 60, time_zone => 'UTC', ); }, undef, "We can make a DateTime object for the leap second on $formatted" ); is( DateTime::LeapSecond::day_length( ( $dt->utc_rd_values )[0] ), 86401, "DateTime::LeapSecond::day_length returns 86401 for $formatted" ); } } done_testing(); DateTime-1.46/xt/author/pp-29overload.t0000644000175000017500000001056013240151623017524 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use Test::Warnings 0.005 ':all'; use DateTime; { my $dt = DateTime->new( year => 1900, month => 12, day => 1 ); is( "$dt", '1900-12-01T00:00:00', 'stringification overloading' ); } { my $dt = DateTime->new( year => 2050, month => 1, day => 15, hour => 20, minute => 10, second => 10 ); my $before_string = '2050-01-15T20:10:09'; my $same_string = '2050-01-15T20:10:10'; my $after_string = '2050-01-15T20:10:11'; is( "$dt", $same_string, 'stringification overloading' ); ok( $dt eq $same_string, 'eq overloading true' ); ok( !( $dt eq $after_string ), 'eq overloading false' ); ok( $dt ne $after_string, 'ne overloading true' ); ok( !( $dt ne $same_string ), 'ne overloading false' ); is( $dt cmp $same_string, 0, 'cmp overloading' ); is( $dt cmp $after_string, -1, ' less than' ); ok( $dt lt $after_string, 'lt overloading' ); ok( !( $dt lt $same_string ), ' not' ); { package Other::Date; use overload q[""] => sub { return ${ $_[0] }; }, fallback => 1; sub new { my ( $class, $date ) = @_; return bless \$date, $class; } } my $same_od = Other::Date->new($same_string); my $after_od = Other::Date->new($after_string); my $before_od = Other::Date->new($before_string); ok( $dt eq $same_od, 'DateTime eq non-DateTime overloaded object true' ); ok( !( $dt eq $after_od ), ' eq false' ); ok( $dt ne $after_od, ' ne true' ); ok( !( $dt ne $same_od ), ' ne false' ); is( $dt cmp $same_od, 0, 'cmp overloading' ); is( $dt cmp $after_od, -1, ' lt overloading' ); ok( $dt lt $after_od, 'lt overloading' ); ok( !( $dt lt $same_od ), ' not' ); is_deeply( [ map { $_ . ' - ' . ( ref $_ || 'no ref' ) } sort { $a cmp $b or ref $a cmp ref $b } $same_od, $after_od, $before_od, $dt, $same_string, $after_string, $before_string ], [ map { $_ . ' - ' . ( ref $_ || 'no ref' ) } $before_string, $before_od, $same_string, $dt, $same_od, $after_string, $after_od ], 'eq sort' ); like( exception { my $x = $dt + 1 }, qr/Cannot add 1 to a DateTime object/, 'Cannot add plain scalar to a DateTime object' ); like( exception { my $x = $dt + bless {}, 'FooBar' }, qr/Cannot add FooBar=HASH\([^\)]+\) to a DateTime object/, 'Cannot add plain FooBar object to a DateTime object' ); like( exception { my $x = $dt - 1 }, qr/Cannot subtract 1 from a DateTime object/, 'Cannot subtract plain scalar from a DateTime object' ); like( exception { my $x = $dt - bless {}, 'FooBar' }, qr/Cannot subtract FooBar=HASH\([^\)]+\) from a DateTime object/, 'Cannot subtract plain FooBar object from a DateTime object' ); like( exception { my $x = $dt > 1 }, qr/A DateTime object can only be compared to another DateTime object/, 'Cannot compare a DateTime object to a scalar' ); like( exception { my $x = $dt > bless {}, 'FooBar' }, qr/A DateTime object can only be compared to another DateTime object/, 'Cannot compare a DateTime object to a FooBar object' ); like( warning { my $x = undef; $dt > $x; }, qr/uninitialized value in numeric gt .+ at .*x?t.(author.pp.)?29overload\.t/, 'Comparing undef to a DateTime object generates a Perl warning at the right spot ($dt > undef)' ); like( warning { my $x = undef; $x > $dt; }, qr/uninitialized value in numeric gt .+ at .*x?t.(author.pp.)?29overload\.t/, 'Comparing undef to a DateTime object generates a Perl warning at the right spot (undef > $dt)' ); ok( !( $dt eq 'some string' ), 'DateTime object always compares false to a string' ); ok( $dt ne 'some string', 'DateTime object always compares false to a string' ); ok( $dt eq $dt->clone, 'DateTime object is equal to a clone of itself' ); ok( !( $dt ne $dt->clone ), 'DateTime object is equal to a clone of itself (! ne)' ); } done_testing(); DateTime-1.46/xt/author/pp-14locale.t0000644000175000017500000000376613240151623017154 0ustar autarchautarchBEGIN { $ENV{PERL_DATETIME_PP} = 1; } use strict; use warnings; use Test::Fatal; use Test::More; use DateTime; use DateTime::Locale; is( exception { DateTime->new( year => 100, locale => 'en_US' ) }, undef, 'make sure new accepts locale parameter' ); is( exception { DateTime->now( locale => 'en_US' ) }, undef, 'make sure now accepts locale parameter' ); is( exception { DateTime->today( locale => 'en_US' ) }, undef, 'make sure today accepts locale parameter' ); is( exception { DateTime->from_epoch( epoch => 1, locale => 'en_US' ) }, undef, 'make sure from_epoch accepts locale parameter' ); is( exception { DateTime->last_day_of_month( year => 100, month => 2, locale => 'en_US' ); }, undef, 'make sure last_day_of_month accepts locale parameter' ); { package DT::Object; sub utc_rd_values { ( 0, 0 ) } } is( exception { DateTime->from_object( object => ( bless {}, 'DT::Object' ), locale => 'en_US' ); }, undef, , 'make sure constructor accepts locale parameter' ); is( exception { DateTime->new( year => 100, locale => DateTime::Locale->load('en_US') ); }, undef, 'make sure constructor accepts locale parameter as object' ); DateTime->DefaultLocale('it'); is( DateTime->now->locale->id, 'it', 'default locale should now be "it"' ); { my $dt = DateTime->new( year => 2013, month => 10, day => 27, hour => 0, time_zone => 'UTC' ); my $after_zone = $dt->clone()->set_time_zone('Europe/Rome'); is( $after_zone->offset(), '7200', 'offset is 7200 after set_time_zone()' ); my $after_locale = $dt->clone()->set_time_zone('Europe/Rome')->set_locale('en_GB'); is( $after_locale->offset(), '7200', 'offset is 7200 after set_time_zone() and set_locale()' ); } done_testing(); DateTime-1.46/tidyall.ini0000644000175000017500000000144613240151623015145 0ustar autarchautarchignore = .build/**/* ignore = DateTime-*/**/* ignore = blib/**/* ignore = inc/LeapSecondsHeader.pm ignore = lib/DateTime/Conflicts.pm ignore = t/00-* ignore = t/author-* ignore = t/release-* ignore = t/zzz-* ignore = xt/**/* [PerlCritic] select = **/*.{pl,pm,t,psgi} argv = --profile=$ROOT/perlcriticrc [PerlCritic non-auto-generated xt] select = xt/author/pp-is-loaded.t select = xt/author/test-all-my-deps.t select = xt/author/xs-is-loaded.t argv = --profile=$ROOT/perlcriticrc [PerlTidy] select = **/*.{pl,pm,t,psgi} argv = --profile=$ROOT/perltidyrc [PerlTidy non-auto-generated xt] select = xt/author/pp-is-loaded.t select = xt/author/test-all-my-deps.t select = xt/author/xs-is-loaded.t argv = --profile=$ROOT/perltidyrc [SortLines::Naturally] select = .stopwords [Test::Vars] select = **/*.pm DateTime-1.46/INSTALL0000644000175000017500000000214513240151623014030 0ustar autarchautarchThis is the Perl distribution DateTime. Installing DateTime is straightforward. ## Installation with cpanm If you have cpanm, you only need one line: % cpanm DateTime If it does not have permission to install modules to the current perl, cpanm will automatically set up and install to a local::lib in your home directory. See the local::lib documentation (https://metacpan.org/pod/local::lib) for details on enabling it in your environment. ## Installing with the CPAN shell Alternatively, if your CPAN shell is set up, you should just be able to do: % cpan DateTime ## Manual installation As a last resort, you can manually install it. Download the tarball, untar it, then build it: % perl Makefile.PL % make && make test Then install it: % make install If your perl is system-managed, you can create a local::lib in your home directory to install modules to. For details, see the local::lib documentation: https://metacpan.org/pod/local::lib ## Documentation DateTime documentation is available as POD. You can run perldoc from a shell to read the documentation: % perldoc DateTime DateTime-1.46/leaptab.txt0000644000175000017500000000071313240151623015147 0ustar autarchautarch1972 Jul. 1 +1 1973 Jan. 1 +1 1974 Jan. 1 +1 1975 Jan. 1 +1 1976 Jan. 1 +1 1977 Jan. 1 +1 1978 Jan. 1 +1 1979 Jan. 1 +1 1980 Jan. 1 +1 1981 Jul. 1 +1 1982 Jul. 1 +1 1983 Jul. 1 +1 1985 Jul. 1 +1 1988 Jan. 1 +1 1990 Jan. 1 +1 1991 Jan. 1 +1 1992 Jul. 1 +1 1993 Jul. 1 +1 1994 Jul. 1 +1 1996 Jan. 1 +1 1997 Jul. 1 +1 1999 Jan. 1 +1 2006 Jan. 1 +1 2009 Jan. 1 +1 2012 Jul. 1 +1 2015 Jul. 1 +1 2017 Jan. 1 +1 DateTime-1.46/Changes0000644000175000017500000016170413240151623014301 0ustar autarchautarch1.46 2018-02-11 - Fixed the formatting for the CLDR "S" symbol. It could in some cases round _up_ to 1 instead of truncating a value. For example, the "SSS" symbol would format 999,999,999 nanoseconds as "1.000". Fixed by Gianni Ceccarelli. PR #71. 1.45 2017-12-26 - Added month_length(), quarter_length() and year_length() methods. Implemented by Dan Stewart. PR #70. 1.44 2017-08-20 - Added a stringify() method. This does exactly the same thing as stringification overloading does. GH #58. - Added an is_last_day_of_month() method to indicate whether or not an object falls on the last day of its month. GH #60. 1.43 2017-05-29 - Added a small optimization for boolification overloading. Rather than relying on a fallback to stringification, we now return true directly, which is a little faster in cases like "if ($might_be_dt) { ... }". - The datetime() method now accepts a single argument to use as the separate between the date and time portion. This defaults to "T". 1.42 2016-12-25 - The DateTime::Duration->add and ->subtract methods now accept DateTime::Duration objects. This used to work by accident, but this is now done intentionally (with docs and tests). Reported by Petr Pisar. GitHub #50. 1.41 2016-11-16 - The DateTime->add and ->subtract methods now accept DateTime::Duration objects. This used to work by accident, but this is now done intentionally (with docs and tests). Based on PR #45 from Sam Kington. 1.40 2016-11-12 - Switched from RT to the GitHub issue tracker. 1.39 2016-09-17 - Bump minimum required Perl to 5.8.4 from 5.8.1. Looking at CPAN Testers, this distro hasn't actually passed with earlier Perl versions since 1.35. I'm not explicitly testing with anything earlier than 5.8.8 1.38 2016-09-16 - This release includes changes from past trial releases to switch from Params::Validate and Params::ValidationCompiler. Relevant release notes from those trial releases are repeated here for clarity. - Replaced Params::Validate with Params::ValidationCompiler and Specio. In my benchmarks this makes constructing a new DateTime object about 14% faster. However, it slows down module load time by about 100 milliseconds (1/10 of a second) on my desktop system with a primed cache (so really measuring compile time, not disk load time). - When you pass a locale to $dt->set you will now get a warning suggesting you should use $dt->set_locale instead. The previous trial releases didn't allow locale to be passed at all, which broke a lot of modules. I've sent PRs, but for now the parameter should be allowed (but discouraged). Reported by Slaven Rezić. RT #115420. - Removed the long-deprecated DateTime->DefaultLanguage method. Use DefaultLocale instead. - Removed the long-deprecated "language" constructor parameter. Use "locale" instead. 1.37 2016-08-14 (TRIAL RELEASE) - Require the latest Params::ValidationCompiler (0.11). 1.36 2016-08-06 - Require namespace::autoclean 0.19. 1.35 2016-08-05 - Use namespace::autoclean in all packages which import anything. Without cleaning the namespace, DateTime ends up with "methods" like try and catch (from Try::Tiny), which can lead to very confusing bugs. Reported by Mischa Schwieger. RT #115983. 1.34 2016-07-06 - Added the leap second coming on December 31, 2016. 1.33 2016-06-29 - Fixed the $dt->set docs to say that you cannot pass a locale (even though you can but you'll get a warning) and added more docs for $dt->set_locale. - Require DateTime::Locale 1.05. - Require DateTime::TimeZone 2.00. 1.32 2016-06-28 - This release *does not* include any of the changes in the 1.29-1.30 TRIAL releases. - When you pass a locale to $dt->set you will now get a warning suggesting you should use $dt->set_locale instead. If you have DateTime::Format::Mail installed you should upgrade to 0.0403 or later, since that module will trigger this warning. - Added support for $dt->truncate( to => 'quarter' ). Implemented by Michael Conrad. GitHub #17. 1.31 2016-06-18 (TRIAL RELEASE) - When you pass a locale to $dt->set you will now get a warning suggesting you should use $dt->set_locale instead. The previous trial releases didn't allow locale to be passed at all, which broke a lot of modules. I've sent PRs, but for now the parameter should be allowed (but discouraged). Reported by Slaven Rezić. RT #115420. 1.30 2016-06-18 (TRIAL RELEASE) - Require the latest version of Params::ValidationCompiler (0.06). Tests failed with 0.01. 1.29 2016-06-17 (TRIAL RELEASE) - Replaced Params::Validate with Params::ValidationCompiler and Specio. In my benchmarks this makes constructing a new DateTime object about 14% faster. However, it slows down module load time by about 100 milliseconds (1/10 of a second) on my desktop system with a primed cache (so really measuring compile time, not disk load time). 1.28 2016-05-21 - Fixed handling of some floating point epochs. Because DateTime treated the epoch like a string instead of a number, certain epochs with a non-integer value ended up treated like integers (Perl is weird). Patch by Christian Hansen. GitHub #15. This also addresses the problem that GitHub #6 brought up. Addresses RT #96452, reported by Slaven Rezić. 1.27 2016-05-13 - Added an environment variable PERL_DATETIME_DEFAULT_TZ to globally set the default time zone. Using this is very dangerous! Be careful!. Patch by Ovid. GitHub #14. 1.26 2016-03-21 - Switched from Module::Build to ExtUtils::MakeMaker. Implementation by Karen Etheridge. GitHub #13. 1.25 2016-03-06 - DateTime->from_object would die if given a DateTime::Infinite object. Now it returns another DateTime::Infinite object. Reported by Greg Oschwald. RT #112712. 1.24 2016-02-29 - The last release partially broke $dt->time. If you passed a value to use as unit separator, this was ignored. Reported by Sergiy Zuban. RT #112585. 1.23 2016-02-28 - Make all DateTime::Infinite objects return the system's representation of positive or negative infinity for any method which returns a number of string representation (year(), month(), ymd(), iso8601(), etc.). Previously some of these methods could return "Nan", "-Inf--Inf--Inf", and other confusing outputs. Reported by Greg Oschwald. RT #110341. 1.22 2016-02-21 (TRIAL RELEASE) - Fixed several issues with the handling of non-integer values passed to from_epoch(). This method was simply broken for negative values, which would end up being incremented by a full second, so for example -0.5 became 0.5. The method did not accept all valid float values. Specifically, it did not accept values in scientific notation. Finally, this method now rounds all non-integer values to the nearest millisecond. This matches the precision we can expect from Perl itself (53 bits) in most cases. Patch by Christian Hansen. GitHub #11. 1.21 2015-09-30 - Make all tests pass with both the current DateTime::Locale and the upcoming new version (currently still in trial releases). 1.20 2015-07-01 - The 1.18 release added the June 30, 2015 leap second to the XS code, but I forgot to update the corresponding pure Perl implementation in DateTime::LeapSecond. 1.19 2015-05-31 - If you compared a DateTime object to an undef value, you might have received a warning pointing to code inside DateTime.pm, instead of in your own code. Fixed by Jason McIntosh. GH #7. - The 30future-tz.t could fail if run at certain very specific times. This should now be much less likely, unless a time zone being tested implements a DST change at noon (which would even more insane than DST already is by a huge factor). Reported by Karen Etheridge and diagnosed by Slaven Rezić. RT #102925. 1.18 2015-01-05 - There will be a new leap second on June 30, 2015. 1.17 2015-01-04 - No code changes from the 1.16 release. 1.16 2015-01-04 (TRIAL RELEASE) - Test fix for systems where IVs are 4 bytes long. 1.15 2015-01-03 (TRIAL RELEASE) - Trying this again ... Experimental fix for adding very large numbers of days. Previously, trying to add more than around 2^28 days could cause errors if the result ended up in a leap year. This is being released as a trial release because I'm not sure how this change will behave on a 32-bit Perl. Reported by KMX. RT #97046. 1.14 2015-01-03 - Accidentally released 1.13 as a non-TRIAL release. Releasing 1.13 minus the integer change so there's a known-safe stable release on CPAN for people to install. 1.13 2015-01-03 * This release was deleted from CPAN. - Experimental fix for adding very large numbers of days. Previously, trying to add more than around 2^28 days could cause errors if the result ended up in a leap year. This is being released as a trial release because I'm not sure how this change will behave on a 32-bit Perl. Reported by KMX. RT #97046. - Various small doc chances to address RT #96958, #98733, and #101262. 1.12 2014-08-31 - The last release had the wrong repo info in the metadata. 1.11 2014-08-31 - The latest historical changes in DateTime::TimeZone 1.74 caused some tests to fail. Reported by Slaven Rezić. RT #98483. - This release of DateTime.pm now requires the DateTime::TimeZone 1.74. 1.10 2014-05-05 - Some tests added in 1.09 would fail on a Perl without a 64-bit gmtime(). Reported by Jerome Eteve. RT #95345. 1.09 2014-05-03 - A call to ->truncate( to => 'week' ) could fail but leave the object changed. RT #93347. - The value of ->jd() is now calculated based on ->mjd() instead of the other way around. This reduces floating point errors a bit when calculating MJD, and should have a neglible impact on the accuracy of JD. Reported by Anye Li. RT #92972. See the ticket for a more detailed description of what this fixes. - Attempting to construct a DateTime object with a year >= 5000 and a time zone other than floating or DST now issues a warning. This warning may go away once DateTime::TimeZone is made much faster. Inspired by a bug report from Lloyd Fournier. RT #92655. 1.08 2014-03-11 - DateTime now calls DateTime->_core_time() instead of calling Perl's time() built-in directly. This makes it much easier to override the value of time() that DateTime sees. This may make it easier to write tests for code that uses DateTime . 1.07 2014-02-06 - Added a hack to get this module working on Android. RT #92671. 1.06 2013-12-31 - DateTime's attempt to generate infinity by calculating 9**9**9 actually got a number on some platforms, like powerpcspe. Reported by Gregor Hermann. RT #91696. 1.05 2013-12-22 - Added a new CLDR ZZZZZ specifier, which is like ZZZ but inserts a colon. Patch by Ricardo Signes. - Added a new option for the truncate() method to truncate to the "local_week". This truncates to the locale's notion of the first day of the week, rather than always truncating to Monday. Patch by Christian Hansen. 1.04 2013-12-07 - Calling set_locale() or set_formatter() on an object with an ambiguous local time could change the underlying UTC time for that object. Reported by Marta Cuaresma Saturio. RT #90583. 1.03 2013-04-17 - The set_time_zone() method was not returning the object when called with a name that matched the current zone. Reported by Noel Maddy. RT #84699. 1.02 2013-04-15 - When a constructor method like new() or today() was called on an object, you'd get an error message like 'Can't locate object method "_normalize_nanoseconds" via package "2013-04-15T00:00:00"'. This has been fixed to provide a sane error message. Patch by Doug Bell. - When set_time_zone() is called with a name that matches the current time zone, DateTime now short circuits and avoids a lot of work. Patch by Mark Stosberg. 1.01 2013-04-01 - Fixed test failures on older Perls. 1.00 2013-03-31 - Bumped the version to 1.00. This is mostly because my prior use of both X.YY and X.YYYY versions causes trouble for some packaging systems. Plus after 10 years it's probably ready to be called 1.00. Requested by Adam. RT #82800. - The %j specifier for strftime was not zero-padding 1 and 2 digit numbers. Fixed by Christian Hansen. RT #84310. - The truncate method was sloppy about validating its "to" parameter, so you could pass things like "years" or "month whatever anything goes". The method would accept the parameter but then not actually truncate the object. RT #84229. - Previously, if a call to $dt->set_time_zone() failed it would still change the time zone of the object, leaving it in a broken state. Reported by Bill Moseley. RT #83940. - DateTime::Infinite objects should no longer die when methods that require a locale are called. Instead, these methods return undef for names and Inf/-Inf for numbers. This affects methods such as day_name() as well as CLDR and strftime formats. When a locale-specific format is used (like the "full" datetime format) it uses the en_US format. Reported by Paul Boldra. RT #67550. 0.78 2012-11-16 - Reverted the change to round nanoseconds up or down in various situtations. Now we always round down. This avoids the case where rounding up would require us to then increment the second value (which could then require us to increment the minute, which could then require us to increment the hour, which could then ...). In other words, we don't want to round 2011-12-31T23:59:59.999999 up to 2012-01-01T00:00:00, because that would be insane. This applies to the return values for ->microsecond, ->millisecond, and the %N specifier for strftime. Patch by Martin Hasch. RT #79845. 0.77 2012-09-25 - POD changes that should make the documentation look better, especially on the web. 0.76 2012-07-01 - The DateTime->subtract method ignored the end_of_month parameter. Patch by Chris Reinhardt. RT #77844. 0.75 2012-06-11 - The epoch for years 1-999 was broken because Time::Local is "clever". A pox on all clever APIs, I say! Reported by Christian Hansen. RT #77719. - Shut up compilation warning from 5.17.x. Reported by Tom Wyant. RT #77490. 0.74 2012-03-22 - Small packaging fix for metacpan's benefit. No need to upgrade. 0.73 2012-03-17 - Change tests to work with Zefram's entirely rebuilt DateTime::TimeZone distribution, which will replace the current implementation. Patch by Zefram. RT #75757. 0.72 2012-01-05 - Remove Test::DependentModules from the dep list. This is used by some author-only tests. Reported by Zefram. 0.71 2012-01-05 - There will be a new leap second on June 30, 2012. 0.70 2011-05-09 - Really fix %N, finally. This was breaking the DateTime::Event::Recurrence test suite. Patch by Dagfinn Ilmari Mannsåker. 0.69 2011-05-03 - When a DateTime object had nanoseconds == 0, the %N strftime specifier always returned "0" regardless of the precision requested. Reported by John Siracusa. RT #67928. 0.68 2011-04-25 - The tests for %N in the last release relied on the vagaries of floating point math on a 64-bit system. Now the from_epoch() method just uses string operations to separate the epoch into an integer value and a mantissa. This avoids floating point insanity. Reported by zefram. RT #67736. 0.67 2011-04-24 - The %N strftime specifier simply truncated nanoseconds, rather than rounding them. Reported by Michael R. Davis. RT #66744. - The %U strftime specifier was off by one in years where January 1st was a Sunday. Patch by Christian Hansen. RT #67631. - The %W strftime specifier was off by one in years where January 1st was a Sunday or Monday. Patch by Christian Hansen. RT #67631. - Some small optimizations from Christian Hansen. The biggest impact is for calculating week_of_month, week_number, and week_year. - This distro now requires Perl 5.8.1+ (it implicitly did this anyway now that Params::Validate is 5.8.1+). 0.66 2010-11-26 - A bunch of documentation cleanup. No code changes. 0.65 2010-10-25 - Actually put the right $VERSION in every package. No other changes. 0.64 2010-10-25 * All the constructors besides new() ended up calling new(), which meant that these constructors went through the parameter validation code twice. Avoiding this should make everything that constructs a new object (besides new() itself) a little faster. ** This change breaks DateTime::Fiscal::Retail454, but no other modules, to the best of my knowledge. ** - The t/39no-so.t test failed for some people. I can't reproduce it, but this release will hopefully fix the problem. Patch by Tokuhiro Matsuno. RT #62061. - Added a section on the DateTime Project ecosystem to the docs. Addresses RT #60930. - Fixed wiki links in the docs now that the wiki has moved to a new wiki platform. - Restored some of the dzil-ification. The repo now has a very minimal Build.PL file which is just enough to build the XS code and run the tests. This fixes the total lack of prereqs in the META.* files. Reported by Bjørn-Olav. RT #62427. 0.63 2010-09-24 - Actually bump the version in the module files. Oops. Reported by bricas. 0.62 2010-09-23 - Don't try to test with DateTime::Format::Strptime unless we have a relatively recent version. Should fix some test failures. 0.61 2010-07-16 - Switching to dzil in 0.56 broke the --pp flag for the Build.PL. Reported by Jonathan Noack. RT #59421. 0.60 2010-07-03 - By default, Dist::Zilla generates a Build.PL that requires Module::Build 0.3601+, but this distro really doesn't need any particular version. 0.59 2010-06-29 - More packaging fixes. This release makes sure that POD only shows up in the right files. In 0.56 through 0.58, some POD in the wrong place confused the search.cpan.org POD display code, and the main module's documentation wasn't viewable. 0.58 2010-06-28 - Versions 0.56 and 0.57 did not build XS properly when installing. 0.57 2010-06-26 - Make DateTime::LeapSecond have the same $VERSION as every other .pm file. 0.56 2010-06-26 - The set_formatter() method did not return the DateTime object, and did not actually validate the value provided for the formatter. Based on a patch by Andrew Whatson. RT #58506. - Improved docs on floating time zone. Based on suggestions by Michael Svoboda. RT #56389. - Added mention of end-of-month algorithms to docs on DateTime math. Based on a patch by Michael R. Davis. RT #58533. - License is now Artistic 2.0. 0.55 2010-03-16 - Get all tests passing on 5.6.2. Thanks to Zefram for help spotting the problems. - Moved code to my hg repo at http://hg.urth.org/hg/DateTime.pm. 0.54 2010-03-14 - Bumped the DateTime::TimeZone prereq to 1.09 to force people to use a modern version. Previously the minimum version was 0.59, and there have been a lot of bug fixes since then. - String overloading now extends to string comparison, so a DateTime object can be compared to any string. In other words if ( $dt eq $string ) { ... } will simply stringify $dt and then do a normal string-is-equals check. Previously, this would blow up unless both operands were a DateTime object. Note that future versions of Test::More (0.95_01+) will no longer stringify arguments to is(), which means that older versions of DateTime may cause new test failures when you upgrade Test::More. It is highly recommended that you upgrade DateTime before upgrading to Test::More 0.95_01+. Patch by Michael Schwern. RT #55453. - Allow passing end_of_month setting to $duration->inverse(). Requested by John Siracusa. RT #53985. 0.53 2009-12-06 - Added Test::Exception to build_requires. 0.52 2009-12-05 - Numeric to ->new() are now all validated to make sure they are integers. Previously, things like "month => 11.2" would have been allowed. Based on a bug report from Max Kanat-Alexandar. RT #45767. - Added a warning to the docs suggesting that you cache the locale time zone if you need to make many DateTime objects in the local zone. Looking up the local zone can be fairly expensive. RT #46753. 0.51 2009-11-01 - Switched to Module::Build. To force a non-XS build, start the build process with "perl Build.PL --pp". - POD-related tests are only run for the maintainer now. - Fixed handling of negative years in CLDR formatting for "y" and "u" patterns. Note that the LDML spec says nothing about how this should work, so I took my best guess. 0.50 2009-05-11 - Tests were failing on Win32 because they attempted to use a negative epoch. Fixed so that these tests are skipped. Fixes RT #45966. 0.49 2009-05-04 - A bug in the test code for handling overloaded objects in from_epoch resulted in a test failure on Perl 5.8.x. This release contains no changes besides a test code fix. 0.48 2009-05-04 - Some of the accessors (the "main" ones like year(), month(), day(), etc) now warn if they are passed a value. Patch from Shawn Moore. Fixes RT #6979. - DateTime::Duration expected DateTime to be loaded and used some constants from it, but did not explicitly "use DateTime". Reported by Jeff Kubina. RT #44740. - The CLDR formatting for "c" and "cc" was incorrectly using the local day of the week. This meant that it gave the wrong result for locales where Monday is not considered the first day of the week. Reported by Maros Kollar. RT #45007. - DateTime->from_epoch did not allow an object which overloaded numification as the epoch value. Patch by Michael Schwern. RT #45653. - Fixed how datetime subtraction is handled for some cases around DST changes. This had been improved back in 0.30, but there were still bugs. RT #45235. 0.47 2009-03-01 - The handling of CLDR format 'j' and 'jj' was backwards, using 24 hour time for locales that wanted 12 hour, and vice versa. Reported by Maros Kollar. - The CLDR formatting was missing support for lower-case "q" patterns. Reported by Maros Kollar. 0.46 2009-02-28 - Added a duration_class method for the benefit of DateTime.pm subclasses. Patch by Shawn Moore. 0.4501 2008-11-25 - The epoch() method got broken in the recent shuffling between Time::Local and Time::y2038. Unfortunately, the tests to catch this also got lost in the shuffle. Reported by Avianna Chao. 0.45 2008-11-11 - Reverted the changes to use Time::y2038, on the recommendation of Michael Schwern (the author of said module), because it is not yet stable. This may come back in a future release. 0.4401 2008-11-03 - In order to handle epochs > 2**32 properly on a 32-bit machine, we also need to import gmtime from Time::y2038. This changes fixes a whole bunch of test failures seen with 0.44. 0.44 2008-11-01 - XS-capable DateTime.pm now uses Time::y2038 instead of Time::Local. This lets it handle epochs up to 142 million years before and after the Unix epoch. - Fixed a compiler warning with Perl 5.10.0. - Fixed docs for year_with_era, which had AD and BC backwards. Reported by Vynce Montgomery. RT #39923. - The format_cldr() method did not format the "yy" format properly when the year ended in "0X". Reported by Wilson Santos. RT #40555. 0.4305 2008-10-03 - The pure Perl version of this module did not know about the end of 2008 leap second. Reported by James T Monty. 0.4304 2008-07-13 - Fix test failures when tests are run with DateTime::Locale 0.41. Reported by David Cantrell via CPAN Testers. 0.4303 2008-07-12 - There is a new leap second coming at the end of 2008. 0.4302 2008-05-20 [ BUG FIXES ] - The 41cldr_format.t test blew up on Perl 5.6.x, because of a bug in the test code. 0.4301 2008-05-18 [ BUG FIXES ] - In the 0.43 release, I forgot to change the DateTime::Locale dependency to require DT::Locale 0.40. 0.43 2008-05-18 [ *** BACKWARDS INCOMPATIBILITIES *** ] * Dropped support for Perl 5.005. [ ENHANCEMENTS ] - Added support for formatting the CLDR date pattern language, which is much more powerful than strftime. This, combined with the latest DateTime::Locale, makes the localized output much more correct. [ BUG FIXES ] - The hour_1() method was returning the real hour + 1, rather than just representing midnight as 24 instead of 0. This bug fix will probably break someone's code. 0.42 2008-02-29 [ BUG FIXES ] - The 17set_return.t tests failed on leap days, like today. Reported by Duncan Ferguson. RT #33695. 0.41 2007-09-10 [ BUG FIXES ] - The 13strftime.t test was failing when DateTime::Locale 0.35 was installed. The test has been adjusted and we now list DT::Locale 0.35 as the minimum version. Reported by David Cantrell. 0.40 2007-08-30 [ BUG FIXES ] - A custom formatter would be lost after a call to set() or truncate(). Reported by Kjell-Magne Øierud. RT #28728. - The truncate() method docs said it accepted "second" as a parameter, but it didn't actually do the right thing with it. Now it always truncates nanoseconds to 0 for any parameter it is passed. 0.39 2007-07-17 [ BUG FIXES ] - Yet more changes to how infinity is handled and tested. This passes for me on 32-bit Win XP and 64-bit Linux, which is promising. Patch by Yitzchak Scott-Thoennes. RT #22392. 0.38 2007-06-30 [ BUG FIXES ] - Require Test::Pod::Coverage 1.08 in pod-coverage.t, since we use all_modules, which was only exported as of version 1.08. Reported by MATSUNO Tokuhiro. Fixes RT #26594. - Fixed a bad link to the old FAQ location in the docs. Reported by Ric Signes. Fixes RT #26846. [ ENHANCEMENTS ] - DateTime.pm now explicitly overloads string comparison. This was done so that comparing a DateTime.pm object to a string returns false, rather than throwing an exception. Reported by Chris Dolan. Addresses RT #26085. 0.37 2007-03-30 [ BUG FIXES ] - Require DateTime::Locale 0.34, which fixes a problem that manifested when thawing a DateTime.pm object. See http://www.mail-archive.com/datetime@perl.org/msg05633.html for some discussion of this. - Added pod coverage tests, and added some POD for undocumented methods as a result. [ ENHANCEMENTS ] - This distro is now GPG-signed, per RT #24776. 0.36 2007-01-18 [ BUG FIXES ] - For infinity, use 100 ** 1000 instead of 100 ** 100 ** 100. This may fix the problems with infinity on some platforms (or may not). Suggested by Bjorn Tackmann. See RT #17390, #19626, and #22392. - Require DateTime::TimeZone 0.59, which includes a similar fix. 0.35 2006-10-22 [ ENHANCEMENTS ] - Added several new methods for getting locale-based data, era_abbr(), era_name(), quarter_abbr(), and quarter_name(). The era() method returns the same data as era_abbr(), but is deprecated. 0.34 2006-08-11 [ BUG FIXES ] - DateTime's code to fall back to the pure Perl implementation was broken in most cases, making it fairly useless. Reported by Adam Kennedy and Brendan Gibson. - Under Perl 5.6.2 (and presumably 5.6.x), some of the tests mysteriously failed. I tracked this down to a weird interaction between DateTime's string overloading and Test::Builder->cmp_ok(). See RT 19626. 0.33 2006-08-09 (the "Asia/Kaohsiung" release) [ ENHANCEMENTS ] - Attempting to do an overloaded operation (add, subtract, compare) with an inappropriate argument (like $dt + 1) gives a more useful error message. [ BUG FIXES ] - The fixes in 0.30 for subtract_datetime() crossing a DST change had a bug. When subtracting two dates, both occurring on a DST change date, but where the dates did not cross the change, the answer was off by an hour. Reported by Chris Prather. See RT 20697. - Borrowed a tweak from version.pm's Makefile.PL to make compiler detection work with MSVC. 0.32 2006-07-24 [ BUG FIXES ] - Change how C compiler detection is done in the Makefile.PL so it does not rely on having make on the system. The new way should work on (most?) Unix and Win32 systems. Suggested by David Golden. See RT 18969. 0.31 2006-05-21 [ ENHANCEMENTS ] - Switched some uses of die() to Carp::croak(), where appropriate. This should make error messages more useful in many cases. Based on a suggestion by Max Maischein. See RT tickets 11692 & 18728. [ BUG FIXES ] - Removed all uses of UNIVERSAL::isa and UNIVERSAL::can as functions. - Tweaked 20infinite.t test to give more useful output for some failures, though it probably doesn't fix them. See RT 17390. 0.30 2005-12-22 [ ENHANCEMENTS ] - Expanded and rewrote the docs on date math to try to explain exactly how DateTime.pm works, and in particular cover the problems DST introduces to various types of date math. The docs now also include some specific recommendations on getting sane results from datetime math. - Added calendar_duration() and clock_duration() methods to DateTime::Duration - Explicitly override the stringification method for DateTime::Infinite objects. They now stringify as whatever the IEEE infinity and negative infinity numbers stringify to on your platform. On Linux this is "inf" and "-inf". CPAN RT #16632. [ BUG FIXES ] - delta_md() and delta_days() did not always return correct values when crossing a DST change. - The pure Perl version of the code had a dependency ordering problem where DateTime::LeapSecond depended on other pure Perl code that wasn't yet available. I'm not sure how this ever worked. - Remove mentions of leap second on 1971-12-31 from the docs, because there was no leap second that day. Reported by Mike Schilli. - If you added a second to a datetime that was on a leap second (like 2005-12-31T23:59:60) it got "stuck" and kept returning the same datetime. Reported by Mike Schilli. - Changes to the tests in 20infinite.t may fix failures seen on some platforms and with new versions of Test::More (0.62 was known to cause failures) [ *** BACKWARDS INCOMPATIBILITIES *** ] - The subtract_datetime() method switched back to using the local portion of the date _and_ time, but it now accounts for days with DST changes specially. This produces results that fix the bugs that were fixed by previous subtraction changes in 0.28 and 0.29, but without introducing even more bugs. The overall result should be sane, but please see the docs for details. 0.2901 2005-07-04 - A leap second for the end of 2005 was announced. 0.29 2005-06-03 [ *** BACKWARDS INCOMPATIBILITIES *** ] - When adding/subtracting a duration with months or days that crossed a DST change, the result was based on the local time, not the UTC time. For consistent results, it is necessary to use the UTC time (but local date) for all date math. Reported by J. Alexander Docauer. 0.28 2005-02-27 [ ENHANCEMENTS ] - The era names for the era() method are now retrieved from the DateTime.pm object's associated locale. The old era() method, which was hard-coded to use BCE and CE, is renamed secular_era(). The christian_era() method remains the same. [ BUG FIXES ] - Fixed an embarassing bug in the subtract_datetime() method. It was subtracting local times, not UTC, which caused bugs when doing subtraction across a DST change. This method is used to implement subtraction overloading, so that was affected as well. Reported by Mike Schilli. - The docs for the %U and %W strftime specifiers implied that these should be zero-padded, but the code was not doing so. Reported by J Docauer. 0.27 2005-01-31 [ ENHANCEMENTS ] - Added local_rd_values() method for the benefit of other modules like DateTime::Event::Recurrence. 0.26 2005-01-27 [ BUG FIXES ] - The docs claimed that the delta_ms(), delta_md(), delta_days() methods always returned a positive duration, but this was not true for delta_md() or delta_days(). 0.25 2005-01-10 (the "new year, new bugs" release) [ BUG FIXES ] - Calling set_time_zone() for a datetime very close to a time zone change died for many of the Olson time zones. - The docs for the from_object constructor said that by default, new objects were in the UTC time zone, but in reality the default was the floating time zone. The docs were changed to match the code. Ticket 9278 on rt.cpan.org. 0.24 2004-12-10 (the "have I mentioned I hate leap seconds" release) [ BUG FIXES ] - Fixed even more bugs related to leap seconds and time zones. Reported by Eugene van der Pijll. [ KNOWN BUGS ] - Offsets with a seconds portion (like "+00:00:30") act strangely near leap seconds. Reported by Eugene van der Pijll. This will be fixed in a future release. 0.23 2004-12-09 (the "oh how I hate leap seconds" release) [ ENHANCEMENTS ] - Added a number of convenience "set" methods: set_year, set_month, set_day, set_hour, set_minute, set_second, set_nanosecond, and set_locale. Suggested by Michael Schwern. - Added christian_era and year_with_christian_era methods. - Clarified that from_epoch(), today(), and now() all return objects in the UTC time zone. Suggested by Sagar Shah and others. - Added formatter parameter to constructor, which allows per-object stringification. Based on a patch from Daisuke Maki. [ BUG FIXES ] - Trying to serialize DateTime::Infinite objects with Storable blew up. Patch by Daisuke Maki. - Require Test::More 0.34+, since I use a function introduced in that version in the tests. Suggested by Jean Forget. - Fix a bug in strftime() which could cause weirdness with pathological specifiers like "%%{day_name}%n". Reported by Jean Forget. - Fixed a number of bugs related to leap seconds and time zones. Reported by Eugene van der Pijll. 0.22 2004-07-23 [ *** BACKWARDS INCOMPATIBILITIES *** ] - The leap second table we were using mistakenly included a leap second on December 31, 1971. This will break all versions of the DateTime::Format::Epoch::TAI64 module up to and including version 0.06. Most users of DateTime.pm will not be affected. Patch by Joshua Hoblitt. 0.2101 2004-06-10 [ BUG FIXES ] - There was a bug in the date math code that occurred if you tried to add enough days, minutes or seconds to generate a datetime 10 years in the future (or so). If the the DateTime object had a a time zone with recurring DST changes, then the date math operation would cause a fatal error "Invalid local time for date in time zone ...". Reported by Dave Faraldo. 0.21 2004-03-28 (The "Another YAPC::Taipei release party release" release) [ *** BACKWARDS INCOMPATIBILITIES *** ] - When given mixed positive & negative arguments, DateTime::Duration no longer forces all arguments to be negative. - For mixed durations, the is_positive, is_zero, and is_negative methods all return false. - Brought back stringification overloading. As of version 1.06, Devel::StackTrace will ignore this overloading when displaying a trace. [ ENHANCEMENTS ] - Add a new in_units() method to DateTime::Duration. Patch by Andrew Pimlott. - Rely on DateTime::TimeZone and DateTime::Locale having their own Storable hooks, as opposed to handling them in DateTime.pm's own Storable hooks. This should fix RT ticket #5542, reported by Dan Rowles (I hope). - More docs on how date math is done. See the new section "The Results of Date Math". [ BUG FIXES ] - DateTime::Duration's is_positive, is_zero, and is_negative methods could incorrectly return true if a duration contained mixed positive and negative units. - Better normalization of nanoseconds in DateTime::Duration. Patch by Andrew Pimlott. 0.20 2004-02-12 [ IMPROVEMENTS ] - Tweaked the "How Date Math is Done" section in DateTime.pm to provide some more explicit examples. [ BUG FIXES ] - If seconds are not negative, DateTime::Duration will try to keep nanoseconds >= 0 when normalizing them to seconds, as long as this doesn't make seconds become negative. Suggested by Andrew Pimlott. - In the datetime subtraction code, there was an off-by-one error in the code to determine if one of the datetimes occurred in a minute containing a leap second. This led to the result of the subtraction being off by one second. Patch by Andrew Pimlott. - A duration's nanoseconds weren't normalized after multiplication. Patch by Andrew Pimlott. 0.1901 2004-01-07 (the "people care about ancient history?" release) [ BUG FIXES ] - The day of week was totally busted for dates before 0000-12-25. Reported by Flavio Glock. 0.19 2003-12-01 (the "never look before a leap second" release) [ IMPROVEMENTS ] - DateTime::Duration now provides a compare() class method. - DateTime::Duration now overloads comparison to throw an exception, because comparison requires a base DateTime object. Note that previous versions of DateTime::Duration _did not_ overload comparison, so if you were comparing them, you were just comparing the value of the object references. Thanks to Rick Measham, Jon Swartz, and Max Maischein for contributing to the discussion on datetime@perl.org about how to implement this feature. - Added DateTime::Duration->multiply to complement multiplication overloading. - Added a leap_seconds method. - Added a section to the docs about floating datetimes. - DateTime::LeapSecond no longer contains code copied from DateTime.pm, instead it just uses DateTime.pm directly. Patch by Joshua Hoblitt. [ BACKWARDS INCOMPATIBILITIES ] - DateTime::LeapSecond's leap_seconds() function now returns the number of leap seconds that have occurred, as opposed to the difference between TAI and UTC for a given Rata Die day, which is what it was returning previously. This means that the values it returns are 9 second less than the previous version. This does not affect DateTime.pm because it never looke at the actual value, just the difference between two leap second values, which remains the same. 0.18 2003-10-26 (the "delta, delta, delta, can I help ya, help ya, help ya?" release) [ IMPROVEMENTS ] - Added several new methods for calculating the difference between two datetime objects. These are delta_md(), delta_days(), and delta_ms(). Each of these methods returns the difference as a duration containing just certain units. [ BUG FIXES ] - Require Pod::Man 1.14+, so that head3/head4 markup doesn't cause installation to die. [ BACKWARDS INCOMPATIBILITIES ] - The local_rd_as_seconds method is deprecated, as it doesn't really serve much purpose. 0.1705 2003-10-07 [ BUG FIXES ] - Subtracting one datetime from another was still broken, and my fix in 0.1704 broke many other subtractions. Reported by Pierre Denis again. Many thanks to Pierre for paying attention. - Subtracting datetimes where the subtraction crossed a leap second was also broken. 0.1704 2003-10-07 [ IMPROVEMENTS ] - Documented the behavior of strftime() when given an invalid format. [ BUG FIXES ] - The DateTime::Duration synopsis showed a sign() method that doesn't exist, so I removed it from the synopsis. Reported by Flavio Glock. - Subtracting one datetime from another was seriously broken. The values for days & weeks were wrong in many cases. Reported by Pierre Denis. 0.1703 2003-09-22 [ BUG FIXES ] - truncate( to => 'week' ) caused a fatal error when the beginning of the week was in the previous month. Reported by R. Mathews (rt.cpan.org #3843). 0.1702 2003-09-18 [ IMPROVEMENTS ] - Added truncate( to => 'week' ). Suggested by Flavio Glock. 0.1701 2003-09-15 [ BUG FIXES ] - If from_epoch was given a fractional epoch with a floating point value with more than 9 digits after the decimal point, the object ended up containing a floating point number of nanoseconds. We now truncate this number to an integer. Fixed by Joshua Hoblitt. - The %V strftime specifier was documented, but not implemented. Reported by Joshua Hoblitt. - Test #56 in 03components.t would die with "Invalid offset: -124" when run with DateTime::TimeZone 0.2502+. Next time, I'll read my own docs ;) 0.17 2003-08-29 (the "math is hard" release) [ BACKWARDS INCOMPATIBILITIES ] - The default end_of_month mode for negative durations is now "preserve". This makes more sense, as the previous default meant that the following code: print DateTime->new( year => 2003, month => 5, day => 31 ) ->subtract( months => 1 )->ymd; printed "2003-05-01" as opposed to "2003-04-30". Thanks to Thomas Klausner for starting a discussion on this problem. - The subtract_datetime method now returns different results, as does subtraction overloading when both sides of the subtraction are DateTime objects. The subtract_datetime_absolute method returns results similar to what was previously returned from subtract_datetime. Thanks to Matthew McGillis for bringing this up, and Joshua Hoblitt and Eugene van der Pijll for contributing to the ensuing discussion. [ IMPROVEMENTS ] - DateTime.pm compare() method is now documented to work with any other calendar class that provides a utc_rd_values() method. - Added the subtract_datetime_absolute method. See the docs for details. - Documented the inverse() method in DateTime::Duration. 0.1601 2003-08-07 [ BUG FIXES ] - On platforms like Win32, where we can't find a finite() or isfinite() function/macro, the DateTime::LeapSecond code wasn't being loaded, so many tests failed. Reported by Ron Hill. 0.16 2003-08-06 [ IMPROVEMENTS ] - The XS code now implements leap second-related calculations. However, this is only used on platforms where we can find a usable finite() or isfinite() function/macro, so it isn't used on Win32. - This distro has now borged the DateTime::LeapSecond module. It is only loaded when the XS leap second code cannot be used. - Other miscellaneous performance improvements. 0.1503 2003-07-31 [ BUG FIXES ] - Adding a duration with delta months to an infinite DateTime was quite broken. Reported by Eugene van der Pijll. 0.1502 2003-07-31 [ BUG FIXES ] - XSLoader wasn't the problem on Solaris, so it's back. - Now loading the XS version of DateTime.pm is wrapped in an eval block. If it fails with an error about the object version not matching, the pure Perl version is loaded instead. This should fix Solaris. Thanks to Joshua Hoblitt for identifying this bug. 0.1501 2003-07-30 [ BUG FIXES ] - Fixed the from_object() method to set the returned object's time zone to the floating time zone if the source object did not have a time zone, as specified in the docs. Previously, the returned object's time zone was UTC. Patch by Eugene van der Pjill. - For this release, at least, the module always uses Dynaloader. This is in order to see if this fixes a problem on Solaris where the install library version of the DateTime .so file is loaded instead of the newly compiled version in the blib directory. 0.15 2003-07-29 [ IMPROVEMENTS ] - The utc_rd_values() method now returns nanoseconds in addition to Rata Die days and seconds. Based on a patch by Joshua Hoblitt. - The from_object() method expects objects to return the same values from their utc_rd_values() methods. Based on a patch by Joshua Hoblitt. [ BUG FIXES ] - Fixed a bug in the pure Perl version of _normalize_tai_seconds that caused very weird results from datetime math. This version may be used on platforms where the XS code compiles, so it can affect quite a number of systems. Reported by Dan Sully. 0.1402 2003-07-24 [ BUG FIXES ] - Fix DefaultLocale method, which didn't work at all. Reported by Serge Leger. 0.1401 2003-07-24 [ BUG FIXES ] - Fix a test failure in 13strftime.t under Perl 5.6.1 (and probably 5.6.0). 0.14 2003-07-23 [ BACKWARDS INCOMPATIBILITIES ] - The DateTime::Language modules are no longer being developed or distributed as part of the DateTime.pm distribution. Because of this, all "language" parameters should now be replaced by "locale" parameter. The "language" parameter is deprecated and will be removed in a future release. Also note that locales should be specified via ISO codes, not names like "English". The old DateTime::Language names will continue to work indefinitely, but they load DateTime::Locale objects instead. Locale-specific data will be returned in utf8 when necessary. - Similarly, the "language" and "DefaultLanguage" methods are now deprecated in favor of "locale" and "DefaultLocale". [ IMPROVEMENTS ] - DateTime::Duration now returns the object from mutator methods, in order to make method chaining possible. Suggested by Ben Bennett. - If the value for second given to new() is 60 or 61, then it must be a valid leap second. - DateTime now uses DateTime::Locale for localization, which allows for real language and territory based localization. The locale code is generated from the ICU project's data, and is much more complete than the DateTime::Language modules. However, we are losing (hopefully only temporarily) support for the various African languages contributed by Daniel Yacob. Support for those languages should return in a future release of DateTime::Locale. - Support for the '%c', '%x', and '%X' strftime format specifiers, which output localized date and time strings. - Added the time_zone_long_name method, primarily for the benefit of DateTime::Locale. - Added a note to the DateTime::Infinite docs warning that it may not work well on Win32. [ BUG FIXES ] - DateTime::Duration was not consistent in how it handled mixed positive and negative constructor parameters. Reported by Ben Bennett. 0.13 2003-05-05 [ IMPROVEMENTS ] - DateTime now does more validation of parameters given to constructors and to the set() method, so bogus values like a month of 13 are a fatal error. - Added a new constructor, from_day_of_year(). - Added a number of new "get" methods, including era, year_with_era, hour_1, hour_12, hour_12_0, weekday_of_month, and week_of_month. Based in part on a patch from Rick Measham. - Now any object method can be called in strftime format by using "%{method}" as a format specifier. Patch from Rick Measham - Added an is_zero method to DateTime::Duration, for objects of zero length. - DateTime->from_epoch will now accept a floating point epoch and turn the post-decimal portion into nanoseconds. This was done in order to interface more accurately with Time::HiRes. - Added a DateTime->hires_epoch method that returns a floating point value for epoch, also for compatibility with Time::HiRes. - DateTime.pm now implements Storable hooks to reduce the size of serialized DateTime objects. In particular, the contained time zone object is not serialized along with the DateTime object. - It is now possible to create arbitrary DateTime::Language subclasses in any namespace. [ BUG FIXES ] - "Fixed" 20infinite.t failures on Windows with 2 icky hacks. The first simply doesn't compile the XS code that deals with infinite numbers on Win32, so the pure Perl version is used instead. However, the rest of the XS code is still compiled on Win32. The other hack is to simply skip a failing test in 20infinite.t on Win32. Hopefully, this will eventually be fixed but given that this is not core functionality for most users, I'd rather get this release out the door now. - Fix epoch() method to work properly with dates greater than 50 years ago. Apparently, if Time::Local is given a year less than 100, it tries to guess the century, and it doesn't do this by simply adding 1900. Numbers less than 53 (for the year 2003) are treated as being in the current century. Ugh. - Fixed compilation on HPUX. Patch from Dan Sully. - The last_day_of_month() method did not accept a nanosecond parameter. - A DT::Duration object created with just nanoseconds was always positive, regardless of the value given for nanoseconds. - Fixed a serious bug when subtracting one datetime from another that could cause the result to be off by up to a second, and negative when it should be positive. This was caused by the introduction of nanoseconds in 0.10. - A zero length duration reported itself as positive when it should be neither positive nor negative. - In Perl 5.6.1/Red Hat Linux 7.2, multiplying a variable with value zero by -1 gives negative-zero, which breaks tests. perl -e ' $x=0; $x*=-1; print $x ' -0 Patch by Flavio Glock. - Comparing a DateTime::Infinite object to a regular datetime could cause a fatal error. Reported by John Peacock. - Fixed a failure in the 04epoch.t tests on Win32. Negative epoch values don't work on Win32. [ BACKWARDS INCOMPATIBILITIES ] - The "Portugese" language module has been renamed to "Portuguese". I'm so embarassed! Reported by Richard Evans. - DateTime::Infinite objects no longer die if "set" methods are called. Instead, these methods are now no-op methods that simply return the original object. This makes these objects more usable when mixed with regular datetime objects. - Removed the fractional_second constructor parameter. It was incorrectly documented anyway. The fractional_second _accessor_ is still there. - DateTime::Duration objects of zero length no longer return true for is_positive. 0.12 2003-05-05 [ BUG FIXES ] - Make sure tests always run with warnings on. - Fix line that had "$] >= 5.6.0" to be "$] >= 5.006". This caused warnings and was just wrong. Reported by John Siracusa. - Quiet warnings from pure Perl implementation. - Quiet warnings from language modules with Unicode when used with Perl 5.00503. 0.11 2003-05-03 [ IMPROVEMENTS ] - Moved a little bit of the leap second code to XS, so DateTime.pm may be a tiny bit faster. - Added name() method to DateTime::Language. Suggested by Rick Measham. - Use XSLoader with Perl 5.6.0+, which according to ancient perl5-porters discussions saves some memory. - Added infinite DateTime objects. See the DateTime::Infinite docs for details. [ BUG FIXES ] - The %I and %l strftime formats were formatting hours as 0-11, not 1-12 as documented. Patch by Simon Newton. - A DateTime::Duration object created only with weeks as a parameter always was positive. Fixed by Flavio Glock. [ BACKWARDS INCOMPATIBILTIES ] - Because of changes in DateTime::TimeZone 0.13, which this version now requires, when a local time is ambiguous, the latest UTC time is used, rather than the earliest, as was done previously. - The Brazilian language module has been renamed as Portugese. - Removed DateTime::Duration->compare (which I forgot to document anyway ;) and comparison overloading for DT::Duration. There's no meaningful way to compare 60 days to 2 months. 0.10 2003-04-19 (the "I'm sure the new regime will be spiffy" release) [IMPROVEMENTS] - Added Tigre language module. Contributed by Daniel Yacob. - DateTime::Duration objects now overload multiplication. Implemented by Flavio Glock. - Added support for nanoseconds in DateTime.pm and DateTime::Duration. Implemented by Flavio Glock. - Added complete support for leap seconds (through use of DateTime::LeapSecond). Mostly implemented by Flavio Glock. [ BACKWARDS INCOMPATIBILTIES ] - Because of the addition of leap seconds to the mix, we are now forced to handle seconds separately from minutes when doing date math. This means that several aspects of the DateTime::Duration API have changed. Specifically: -- There is now an additional delta_minutes() method. -- The hash returned by the deltas() method now includes a "minutes" key. -- The seconds delta may be greater than 59. -- The seconds() method may return a number greater than 59. 0.09 2003-04-05 (the "liberation through violence" release) [IMPROVEMENTS] - As requested by numerous people, there is now a pure Perl implementation of DateTime.pm included with this distribution. If you don't have a C compiler it will be used instead of the XS implementation. - Document how floating time zones are handling in comparisons, and add the compare_ignore_floating method. Based on a patch from Eugene van der Pijll. - Allow from_epoch(), now(), and today() to accept a time_zone parameter. Based on suggestions from Tim Bunce and Joshua Hoblitt. - Allow extraction of AM/PM string list from DateTime::Language classes. - Added quarter() and day_of_quarter() methods. Based on a patch from Tim Allwine. [BUG FIXES] - If a datetime had the floating timezone and then set_time_zone was used to set it to something else, the internal UTC time of the object was not changed, meaning that its offset could be calculated incorrectly. Patch by Eugene van der Pijll. - If datetime math was done with hours, minutes, or seconds, the return value of ->epoch would be wrong after this. Based on report and patch from Iain Truskett. 0.08 2003-03-21 (the "anti-war" release) [IMPROVEMENTS] - All set/modify methods now return the datetime object, in order to make method chaining possible. Patch by Iain Truskett. - The _greg2rd and _rd2greg methods have been renamed _ymd2rd and _rd2ymd, so as to make them look more normal when used in subclasses. - Added a truncate() method. Suggested by Flavio Glock. - Added Swedish language module. Contributed by Christian Hansen. - Added language modules for Afar, Amharic, Gedeo, Oromo, Sidama, Somali, and Tigrinya (Eritrean and Ethiopian), all courtesy of Daniel Yacob. - Various doc improvements, including a section on invalid local times. [BUG FIXES] - The week() method was wrong for many dates. Reported by Christian Hansen. - The last_day_of_month() method had the DateTime class hard-coded in it. Reported by Eugene van der Pijll. - Fixed a bug when comparing a datetime object to infinity (or negative infinity). Fixed by Flavio Glock. - Date math has been fixed so that it affects the _local_ times. This means that sometimes 1 day is not equal to 24 hours when the addition/subtraction crosses over a Daylight Saving Time change. See the "How Date Math is Done" section of the docs for more details. [BACKWARDS INCOMPATIBILITIES] - Objects constructed via the new() method now have a "floating" time zone by default, instead of using the "local" time zone. This is just simpler to deal with, and for code where time zones are unimportant, this is the most appropriate default. 0.07 2003-02-26 [IMPROVEMENTS] - Added a small hack to the compare() method so that this module can be used with Set::Infinite. - Changed compare so that it can be used to compare two objects from different calendars that conform to the DateTime::Calendar interface. - Added explanation of exactly what calendar this module represents ("proleptic Gregorian calendar") to docs. - Added a Spanish language DateTime::Language subclass. Implemented by Flavio S. Glock. - Added support for specifying a language by ISO code ("en" or "pt-br") as well as the subclass name. Based on a patch from Eric Cholet. - Revamped the externally visible DateTime::Language API. - Objects created via the from_object() method are set to the time zone of the object from which they were created, if it has one, or UTC otherwise. [BUG FIXES] - The from_object() method was broken because it retrieved a UTC datetime from the object passed in, and then created a new DateTime object using that UTC time as a _local_ time. [BACKWARDS INCOMPATIBILITIES] - Removed stringification overloading. Having this in place made it impossible to create a strack trace in much of the time zone code. - Renamed the DateTime::Language->subclasses method as languages. - It is no longer possible to directly instantiate a DateTime::Language subclass, instead use: my $en = DateTime::Language->new( language => 'English' ); - The from_object() method no longer accepts a "time_zone" parameter. 0.06 2003-02-16 - The docs said that there was no year 0 in the Gregorian calendar, but that was wrong. The year() method can now return 0. The year_0() method has been removed. - Added jd() and mjd() methods. - Re-implemented some of the core code in XS for speed. 0.05 2003-02-13 - Fix handling and reporting of epoch times. Epoch times are, by definition, UTC times, so any time created from an epoch should always have its time zone set to "UTC". This can be changed after the object is created. Similarly, value returned by the epoch() method needs to be based on the object's UTC time, not it's local time. Bug reported by Kellan Elliott-McCrea. - Change year_0 so that -1 BCE is 0, not 1 CE. This corresponds to astronomical years. - Change ymd, dmy, mdy, and iso8601 to use Gregorian years (..., -2, -1, 1, 2, ... ) as opposed to astronomical years. Also make sure all negative years are formatted as 4 digits. 0.04 2003-02-10 - Explicitly set time zone for objects created during tests. 0.03 2003-02-09 - Giving a language parameter to a constructor method didn't load the language class. - Test that all language classes are at least loadable. - Added Brazilian (not quite a language ;) and Danish, again stolen from Graham Barr's TimeDate suite. - Added is_dst method. Requested by Matt Sergeant. 0.02 2003-02-09 - Fixed a bug in calculating day of year in leap years (it was +1 off starting in February). Reported by Matt Sergeant. - Subtracting one datetime from another was broken in most cases. Improved the tests for this quite a bit. Reported by Eric Cholet. - Made the version number a non-dev-release so it's visible when CPAN.pm tries to install it as a prereq for something else. 0.01_00 2003-02-04 - The first alpha release. This module draws on Date::ICal for much of its internals, so it has more history than a normal alpha release. DateTime-1.46/README.md0000644000175000017500000020363613240151623014266 0ustar autarchautarch# NAME DateTime - A date and time object for Perl # VERSION version 1.46 # SYNOPSIS use DateTime; $dt = DateTime->new( year => 1964, month => 10, day => 16, hour => 16, minute => 12, second => 47, nanosecond => 500000000, time_zone => 'Asia/Taipei', ); $dt = DateTime->from_epoch( epoch => $epoch ); $dt = DateTime->now; # same as ( epoch => time() ) $year = $dt->year; $month = $dt->month; # 1-12 $day = $dt->day; # 1-31 $dow = $dt->day_of_week; # 1-7 (Monday is 1) $hour = $dt->hour; # 0-23 $minute = $dt->minute; # 0-59 $second = $dt->second; # 0-61 (leap seconds!) $doy = $dt->day_of_year; # 1-366 (leap years) $doq = $dt->day_of_quarter; # 1.. $qtr = $dt->quarter; # 1-4 # all of the start-at-1 methods above have corresponding start-at-0 # methods, such as $dt->day_of_month_0, $dt->month_0 and so on $ymd = $dt->ymd; # 2002-12-06 $ymd = $dt->ymd('/'); # 2002/12/06 $mdy = $dt->mdy; # 12-06-2002 $mdy = $dt->mdy('/'); # 12/06/2002 $dmy = $dt->dmy; # 06-12-2002 $dmy = $dt->dmy('/'); # 06/12/2002 $hms = $dt->hms; # 14:02:29 $hms = $dt->hms('!'); # 14!02!29 $is_leap = $dt->is_leap_year; # these are localizable, see Locales section $month_name = $dt->month_name; # January, February, ... $month_abbr = $dt->month_abbr; # Jan, Feb, ... $day_name = $dt->day_name; # Monday, Tuesday, ... $day_abbr = $dt->day_abbr; # Mon, Tue, ... # May not work for all possible datetime, see the docs on this # method for more details. $epoch_time = $dt->epoch; $dt2 = $dt + $duration_object; $dt3 = $dt - $duration_object; $duration_object = $dt - $dt2; $dt->set( year => 1882 ); $dt->set_time_zone( 'America/Chicago' ); $dt->set_formatter( $formatter ); # DESCRIPTION DateTime is a class for the representation of date/time combinations, and is part of the Perl DateTime project. For details on this project please see [http://datetime.perl.org/](http://datetime.perl.org/). The DateTime site has a FAQ which may help answer many "how do I do X?" questions. The FAQ is at [http://datetime.perl.org/wiki/datetime/page/FAQ](http://datetime.perl.org/wiki/datetime/page/FAQ). It represents the Gregorian calendar, extended backwards in time before its creation (in 1582). This is sometimes known as the "proleptic Gregorian calendar". In this calendar, the first day of the calendar (the epoch), is the first day of year 1, which corresponds to the date which was (incorrectly) believed to be the birth of Jesus Christ. The calendar represented does have a year 0, and in that way differs from how dates are often written using "BCE/CE" or "BC/AD". For infinite datetimes, please see the [DateTime::Infinite](https://metacpan.org/pod/DateTime::Infinite) module. # USAGE ## 0-based Versus 1-based Numbers The DateTime.pm module follows a simple logic for determining whether or not a given number is 0-based or 1-based. Month, day of month, day of week, and day of year are 1-based. Any method that is 1-based also has an equivalent 0-based method ending in "\_0". So for example, this class provides both `day_of_week()` and `day_of_week_0()` methods. The `day_of_week_0()` method still treats Monday as the first day of the week. All _time_-related numbers such as hour, minute, and second are 0-based. Years are neither, as they can be both positive or negative, unlike any other datetime component. There _is_ a year 0. There is no `quarter_0()` method. ## Error Handling Some errors may cause this module to die with an error string. This can only happen when calling constructor methods, methods that change the object, such as `set()`, or methods that take parameters. Methods that retrieve information about the object, such as `year()` or `epoch()`, will never die. ## Locales All the object methods which return names or abbreviations return data based on a locale. This is done by setting the locale when constructing a DateTime object. If this is not set, then "en-US" is used. ## Floating DateTimes The default time zone for new DateTime objects, except where stated otherwise, is the "floating" time zone. This concept comes from the iCal standard. A floating datetime is one which is not anchored to any particular time zone. In addition, floating datetimes do not include leap seconds, since we cannot apply them without knowing the datetime's time zone. The results of date math and comparison between a floating datetime and one with a real time zone are not really valid, because one includes leap seconds and the other does not. Similarly, the results of datetime math between two floating datetimes and two datetimes with time zones are not really comparable. If you are planning to use any objects with a real time zone, it is strongly recommended that you **do not** mix these with floating datetimes. ## Math If you are going to be doing date math, please read the section ["How DateTime Math Works"](#how-datetime-math-works). ## Determining the Local Time Zone Can Be Slow If `$ENV{TZ}` is not set, it may involve reading a number of files in `/etc` or elsewhere. If you know that the local time zone won't change while your code is running, and you need to make many objects for the local time zone, it is strongly recommended that you retrieve the local time zone once and cache it: our $App::LocalTZ = DateTime::TimeZone->new( name => 'local' ); ... # then everywhere else my $dt = DateTime->new( ..., time_zone => $App::LocalTZ ); DateTime itself does not do this internally because local time zones can change, and there's no good way to determine if it's changed without doing all the work to look it up. Do not try to use named time zones (like "America/Chicago") with dates very far in the future (thousands of years). The current implementation of `DateTime::TimeZone` will use a huge amount of memory calculating all the DST changes from now until the future date. Use UTC or the floating time zone and you will be safe. ## Globally Setting a Default Time Zone **Warning: This is very dangerous. Do this at your own risk!** By default, `DateTime` uses either the floating time zone or UTC for newly created objects, depending on the constructor. You can force `DateTime` to use a different time zone by setting the `PERL_DATETIME_DEFAULT_TZ` environment variable. As noted above, this is very dangerous, as it affects all code that creates a `DateTime` object, including modules from CPAN. If those modules expect the normal default, then setting this can cause confusing breakage or subtly broken data. Before setting this variable, you are strongly encouraged to audit your CPAN dependencies to see how they use `DateTime`. Try running the test suite for each dependency with this environment variable set before using this in production. ## Upper and Lower Bounds Internally, dates are represented the number of days before or after 0001-01-01. This is stored as an integer, meaning that the upper and lower bounds are based on your Perl's integer size (`$Config{ivsize}`). The limit on 32-bit systems is around 2^29 days, which gets you to year (+/-)1,469,903. On a 64-bit system you get 2^62 days, (+/-)12,626,367,463,883,278 (12.626 quadrillion). # METHODS DateTime provide many methods. The documentation breaks them down into groups based on what they do (constructor, accessors, modifiers, etc.). ## Constructors All constructors can die when invalid parameters are given. ### Warnings Currently, constructors will warn if you try to create a far future DateTime (year >= 5000) with any time zone besides floating or UTC. This can be very slow if the time zone has future DST transitions that need to be calculated. If the date is sufficiently far in the future this can be _really_ slow (minutes). All warnings from DateTime use the `DateTime` category and can be suppressed with: no warnings 'DateTime'; This warning may be removed in the future if [DateTime::TimeZone](https://metacpan.org/pod/DateTime::TimeZone) is made much faster. ### DateTime->new( ... ) This class method accepts parameters for each date and time component: "year", "month", "day", "hour", "minute", "second", "nanosecond". It also accepts "locale", "time\_zone", and "formatter" parameters. my $dt = DateTime->new( year => 1966, month => 10, day => 25, hour => 7, minute => 15, second => 47, nanosecond => 500000000, time_zone => 'America/Chicago', ); DateTime validates the "month", "day", "hour", "minute", and "second", and "nanosecond" parameters. The valid values for these parameters are: - month An integer from 1-12. - day An integer from 1-31, and it must be within the valid range of days for the specified month. - hour An integer from 0-23. - minute An integer from 0-59. - second An integer from 0-61 (to allow for leap seconds). Values of 60 or 61 are only allowed when they match actual leap seconds. - nanosecond An integer >= 0. If this number is greater than 1 billion, it will be normalized into the second value for the DateTime object. Invalid parameter types (like an array reference) will cause the constructor to die. The value for seconds may be from 0 to 61, to account for leap seconds. If you give a value greater than 59, DateTime does check to see that it really matches a valid leap second. All of the parameters are optional except for "year". The "month" and "day" parameters both default to 1, while the "hour", "minute", "second", and "nanosecond" parameters all default to 0. The "locale" parameter should be a string containing a locale code, like "en-US" or "zh-Hant-TW", or an object returned by `DateTime::Locale->load`. See the [DateTime::Locale](https://metacpan.org/pod/DateTime::Locale) documentation for details. The "time\_zone" parameter can be either a string or a `DateTime::TimeZone` object. A string will simply be passed to the `DateTime::TimeZone->new` method as its "name" parameter. This string may be an Olson DB time zone name ("America/Chicago"), an offset string ("+0630"), or the words "floating" or "local". See the `DateTime::TimeZone` documentation for more details. The default time zone is "floating". The "formatter" can be either a scalar or an object, but the class specified by the scalar or the object must implement a `format_datetime()` method. #### Parsing Dates **This module does not parse dates!** That means there is no constructor to which you can pass things like "March 3, 1970 12:34". Instead, take a look at the various `DateTime::Format::*` modules on CPAN. These parse all sorts of different date formats, and you're bound to find something that can handle your particular needs. #### Ambiguous Local Times Because of Daylight Saving Time, it is possible to specify a local time that is ambiguous. For example, in the US in 2003, the transition from to saving to standard time occurred on October 26, at 02:00:00 local time. The local clock changed from 01:59:59 (saving time) to 01:00:00 (standard time). This means that the hour from 01:00:00 through 01:59:59 actually occurs twice, though the UTC time continues to move forward. If you specify an ambiguous time, then the latest UTC time is always used, in effect always choosing standard time. In this case, you can simply subtract an hour to the object in order to move to saving time, for example: # This object represent 01:30:00 standard time my $dt = DateTime->new( year => 2003, month => 10, day => 26, hour => 1, minute => 30, second => 0, time_zone => 'America/Chicago', ); print $dt->hms; # prints 01:30:00 # Now the object represent 01:30:00 saving time $dt->subtract( hours => 1 ); print $dt->hms; # still prints 01:30:00 Alternately, you could create the object with the UTC time zone, and then call the `set_time_zone()` method to change the time zone. This is a good way to ensure that the time is not ambiguous. #### Invalid Local Times Another problem introduced by Daylight Saving Time is that certain local times just do not exist. For example, in the US in 2003, the transition from standard to saving time occurred on April 6, at the change to 2:00:00 local time. The local clock changes from 01:59:59 (standard time) to 03:00:00 (saving time). This means that there is no 02:00:00 through 02:59:59 on April 6! Attempting to create an invalid time currently causes a fatal error. This may change in future version of this module. ### DateTime->from\_epoch( epoch => $epoch, ... ) This class method can be used to construct a new DateTime object from an epoch time instead of components. Just as with the `new()` method, it accepts "time\_zone", "locale", and "formatter" parameters. If the epoch value is a floating-point value, it will be rounded to nearest microsecond. By default, the returned object will be in the UTC time zone. ### DateTime->now( ... ) This class method is equivalent to calling `from_epoch()` with the value returned from Perl's `time()` function. Just as with the `new()` method, it accepts "time\_zone" and "locale" parameters. By default, the returned object will be in the UTC time zone. ### DateTime->today( ... ) This class method is equivalent to: DateTime->now(@_)->truncate( to => 'day' ); ### DateTime->from\_object( object => $object, ... ) This class method can be used to construct a new DateTime object from any object that implements the `utc_rd_values()` method. All `DateTime::Calendar` modules must implement this method in order to provide cross-calendar compatibility. This method accepts a "locale" and "formatter" parameter If the object passed to this method has a `time_zone()` method, that is used to set the time zone of the newly created `DateTime.pm` object. Otherwise, the returned object will be in the floating time zone. ### DateTime->last\_day\_of\_month( ... ) This constructor takes the same arguments as can be given to the `new()` method, except for "day". Additionally, both "year" and "month" are required. ### DateTime->from\_day\_of\_year( ... ) This constructor takes the same arguments as can be given to the `new()` method, except that it does not accept a "month" or "day" argument. Instead, it requires both "year" and "day\_of\_year". The day of year must be between 1 and 366, and 366 is only allowed for leap years. ### $dt->clone() This object method returns a new object that is replica of the object upon which the method is called. ## "Get" Methods This class has many methods for retrieving information about an object. ### $dt->year() Returns the year. ### $dt->ce\_year() Returns the year according to the BCE/CE numbering system. The year before year 1 in this system is year -1, aka "1 BCE". ### $dt->era\_name() Returns the long name of the current era, something like "Before Christ". See the [Locales](#locales) section for more details. ### $dt->era\_abbr() Returns the abbreviated name of the current era, something like "BC". See the [Locales](#locales) section for more details. ### $dt->christian\_era() Returns a string, either "BC" or "AD", according to the year. ### $dt->secular\_era() Returns a string, either "BCE" or "CE", according to the year. ### $dt->year\_with\_era() Returns a string containing the year immediately followed by its era abbreviation. The year is the absolute value of `ce_year()`, so that year 1 is "1AD" and year 0 is "1BC". ### $dt->year\_with\_christian\_era() Like `year_with_era()`, but uses the christian\_era() method to get the era name. ### $dt->year\_with\_secular\_era() Like `year_with_era()`, but uses the secular\_era() method to get the era name. ### $dt->month() Returns the month of the year, from 1..12. Also available as `$dt->mon()`. ### $dt->month\_name() Returns the name of the current month. See the [Locales](#locales) section for more details. ### $dt->month\_abbr() Returns the abbreviated name of the current month. See the [Locales](#locales) section for more details. ### $dt->day() Returns the day of the month, from 1..31. Also available as `$dt->mday()` and `$dt->day_of_month()`. ### $dt->day\_of\_week() Returns the day of the week as a number, from 1..7, with 1 being Monday and 7 being Sunday. Also available as `$dt->wday()` and `$dt->dow()`. ### $dt->local\_day\_of\_week() Returns the day of the week as a number, from 1..7. The day corresponding to 1 will vary based on the locale. ### $dt->day\_name() Returns the name of the current day of the week. See the [Locales](#locales) section for more details. ### $dt->day\_abbr() Returns the abbreviated name of the current day of the week. See the [Locales](#locales) section for more details. ### $dt->day\_of\_year() Returns the day of the year. Also available as `$dt->doy()`. ### $dt->quarter() Returns the quarter of the year, from 1..4. ### $dt->quarter\_name() Returns the name of the current quarter. See the [Locales](#locales) section for more details. ### $dt->quarter\_abbr() Returns the abbreviated name of the current quarter. See the [Locales](#locales) section for more details. ### $dt->day\_of\_quarter() Returns the day of the quarter. Also available as `$dt->doq()`. ### $dt->weekday\_of\_month() Returns a number from 1..5 indicating which week day of the month this is. For example, June 9, 2003 is the second Monday of the month, and so this method returns 2 for that day. ### $dt->ymd( $optional\_separator ), $dt->mdy(...), $dt->dmy(...) Each method returns the year, month, and day, in the order indicated by the method name. Years are zero-padded to four digits. Months and days are 0-padded to two digits. By default, the values are separated by a dash (-), but this can be overridden by passing a value to the method. The `$dt->ymd()` method is also available as `$dt->date()`. ### $dt->hour() Returns the hour of the day, from 0..23. ### $dt->hour\_1() Returns the hour of the day, from 1..24. ### $dt->hour\_12() Returns the hour of the day, from 1..12. ### $dt->hour\_12\_0() Returns the hour of the day, from 0..11. ### $dt->am\_or\_pm() Returns the appropriate localized abbreviation, depending on the current hour. ### $dt->minute() Returns the minute of the hour, from 0..59. Also available as `$dt->min()`. ### $dt->second() Returns the second, from 0..61. The values 60 and 61 are used for leap seconds. Also available as `$dt->sec()`. ### $dt->fractional\_second() Returns the second, as a real number from 0.0 until 61.999999999 The values 60 and 61 are used for leap seconds. ### $dt->millisecond() Returns the fractional part of the second as milliseconds (1E-3 seconds). Half a second is 500 milliseconds. This value will always be rounded down to the nearest integer. ### $dt->microsecond() Returns the fractional part of the second as microseconds (1E-6 seconds). Half a second is 500\_000 microseconds. This value will always be rounded down to the nearest integer. ### $dt->nanosecond() Returns the fractional part of the second as nanoseconds (1E-9 seconds). Half a second is 500\_000\_000 nanoseconds. ### $dt->hms( $optional\_separator ) Returns the hour, minute, and second, all zero-padded to two digits. If no separator is specified, a colon (:) is used by default. Also available as `$dt->time()`. ### $dt->datetime( $optional\_separator ) This method is equivalent to: $dt->ymd('-') . 'T' . $dt->hms(':') The `$optional_separator` parameter allows you to override the separator between the date and time, for e.g. `$dt->datetime(q{ })`. This method is also available as `$dt->iso8601()`, but it's not really a very good ISO8601 format, as it lacks a time zone. If called as `$dt->iso8601()` you cannot change the separator, as ISO8601 specifies that "T" must be used to separate them. ### $dt->stringify() This method returns a stringified version of the object. It is how stringification overloading is implemented. If the object has a formatter, then its `format_datetime()` method is used to produce a string. Otherwise, this method calls `$dt->iso8601()` to produce a string. See ["Formatters And Stringification"](#formatters-and-stringification) for details. ### $dt->is\_leap\_year() This method returns a true or false value indicating whether or not the datetime object is in a leap year. ### $dt->is\_last\_day\_of\_month() This method returns a true or false value indicating whether or not the datetime object is the last day of the month. ### $dt->month\_length() This method returns the number of days in the current month. ### $dt->quarter\_length() This method returns the number of days in the current quarter. ### $dt->year\_length() This method returns the number of days in the current year. ### $dt->week() ($week_year, $week_number) = $dt->week; Returns information about the calendar week which contains this datetime object. The values returned by this method are also available separately through the week\_year and week\_number methods. The first week of the year is defined by ISO as the one which contains the fourth day of January, which is equivalent to saying that it's the first week to overlap the new year by at least four days. Typically the week year will be the same as the year that the object is in, but dates at the very beginning of a calendar year often end up in the last week of the prior year, and similarly, the final few days of the year may be placed in the first week of the next year. ### $dt->week\_year() Returns the year of the week. See `$dt->week()` for details. ### $dt->week\_number() Returns the week of the year, from 1..53. See `$dt->week()` for details. ### $dt->week\_of\_month() The week of the month, from 0..5. The first week of the month is the first week that contains a Thursday. This is based on the ICU definition of week of month, and correlates to the ISO8601 week of year definition. A day in the week _before_ the week with the first Thursday will be week 0. ### $dt->jd(), $dt->mjd() These return the Julian Day and Modified Julian Day, respectively. The value returned is a floating point number. The fractional portion of the number represents the time portion of the datetime. ### $dt->time\_zone() This returns the `DateTime::TimeZone` object for the datetime object. ### $dt->offset() This returns the offset from UTC, in seconds, of the datetime object according to the time zone. ### $dt->is\_dst() Returns a boolean indicating whether or not the datetime object is currently in Daylight Saving Time or not. ### $dt->time\_zone\_long\_name() This is a shortcut for `$dt->time_zone->name`. It's provided so that one can use "%{time\_zone\_long\_name}" as a strftime format specifier. ### $dt->time\_zone\_short\_name() This method returns the time zone abbreviation for the current time zone, such as "PST" or "GMT". These names are **not** definitive, and should not be used in any application intended for general use by users around the world. ### $dt->strftime( $format, ... ) This method implements functionality similar to the `strftime()` method in C. However, if given multiple format strings, then it will return multiple scalars, one for each format string. See the ["strftime Patterns"](#strftime-patterns) section for a list of all possible strftime patterns. If you give a pattern that doesn't exist, then it is simply treated as text. ### $dt->format\_cldr( $format, ... ) This method implements formatting based on the CLDR date patterns. If given multiple format strings, then it will return multiple scalars, one for each format string. See the ["CLDR Patterns"](#cldr-patterns) section for a list of all possible CLDR patterns. If you give a pattern that doesn't exist, then it is simply treated as text. ### $dt->epoch() Return the UTC epoch value for the datetime object. Datetimes before the start of the epoch will be returned as a negative number. The return value from this method is always an integer. Since the epoch does not account for leap seconds, the epoch time for 1972-12-31T23:59:60 (UTC) is exactly the same as that for 1973-01-01T00:00:00. ### $dt->hires\_epoch() Returns the epoch as a floating point number. The floating point portion of the value represents the nanosecond value of the object. This method is provided for compatibility with the `Time::HiRes` module. Note that this method suffers from the imprecision of floating point numbers, and the result may end up rounded to an arbitrary degree depending on your platform. my $dt = DateTime->new( year => 2012, nanosecond => 4 ); say $dt->hires_epoch(); On my system, this simply prints `1325376000` because adding `0.000000004` to `1325376000` returns `1325376000`. ### $dt->is\_finite(), $dt->is\_infinite() These methods allow you to distinguish normal datetime objects from infinite ones. Infinite datetime objects are documented in [DateTime::Infinite](https://metacpan.org/pod/DateTime::Infinite). ### $dt->utc\_rd\_values() Returns the current UTC Rata Die days, seconds, and nanoseconds as a three element list. This exists primarily to allow other calendar modules to create objects based on the values provided by this object. ### $dt->local\_rd\_values() Returns the current local Rata Die days, seconds, and nanoseconds as a three element list. This exists for the benefit of other modules which might want to use this information for date math, such as `DateTime::Event::Recurrence`. ### $dt->leap\_seconds() Returns the number of leap seconds that have happened up to the datetime represented by the object. For floating datetimes, this always returns 0. ### $dt->utc\_rd\_as\_seconds() Returns the current UTC Rata Die days and seconds purely as seconds. This number ignores any fractional seconds stored in the object, as well as leap seconds. ### $dt->locale() Returns the current locale object. ### $dt->formatter() Returns current formatter object or class. See ["Formatters And Stringification"](#formatters-and-stringification) for details. ## "Set" Methods The remaining methods provided by `DateTime.pm`, except where otherwise specified, return the object itself, thus making method chaining possible. For example: my $dt = DateTime->now->set_time_zone( 'Australia/Sydney' ); my $first = DateTime ->last_day_of_month( year => 2003, month => 3 ) ->add( days => 1 ) ->subtract( seconds => 1 ); ### $dt->set( .. ) This method can be used to change the local components of a date time. This method accepts any parameter allowed by the `new()` method except for "locale" or "time\_zone". Use `set_locale()` and `set_time_zone()` for those instead. This method performs parameter validation just like the `new()` method. **Do not use this method to do date math. Use the `add()` and `subtract()` methods instead.** ### $dt->set\_year(), $dt->set\_month(), etc. DateTime has a `set_*` method for every item that can be passed to the constructor: - $dt->set\_year() - $dt->set\_month() - $dt->set\_day() - $dt->set\_hour() - $dt->set\_minute() - $dt->set\_second() - $dt->set\_nanosecond() These are shortcuts to calling `set()` with a single key. They all take a single parameter. ### $dt->truncate( to => ... ) This method allows you to reset some of the local time components in the object to their "zero" values. The "to" parameter is used to specify which values to truncate, and it may be one of "year", "quarter", "month", "week", "local\_week", "day", "hour", "minute", or "second". For example, if "month" is specified, then the local day becomes 1, and the hour, minute, and second all become 0. If "week" is given, then the datetime is set to the Monday of the week in which it occurs, and the time components are all set to 0. If you truncate to "local\_week", then the first day of the week is locale-dependent. For example, in the `en-US` locale, the first day of the week is Sunday. ### $dt->set\_locale( $locale ) Sets the object's locale. You can provide either a locale code like "en-US" or an object returned by `DateTime::Locale->load`. ### $dt->set\_time\_zone( $tz ) This method accepts either a time zone object or a string that can be passed as the "name" parameter to `DateTime::TimeZone->new()`. If the new time zone's offset is different from the old time zone, then the _local_ time is adjusted accordingly. For example: my $dt = DateTime->new( year => 2000, month => 5, day => 10, hour => 15, minute => 15, time_zone => 'America/Los_Angeles', ); print $dt->hour; # prints 15 $dt->set_time_zone( 'America/Chicago' ); print $dt->hour; # prints 17 If the old time zone was a floating time zone, then no adjustments to the local time are made, except to account for leap seconds. If the new time zone is floating, then the _UTC_ time is adjusted in order to leave the local time untouched. Fans of Tsai Ming-Liang's films will be happy to know that this does work: my $dt = DateTime->now( time_zone => 'Asia/Taipei' ); $dt->set_time_zone( 'Europe/Paris' ); Yes, now we can know "ni3 na4 bian1 ji2dian3?" ### $dt->set\_formatter( $formatter ) Set the formatter for the object. See ["Formatters And Stringification"](#formatters-and-stringification) for details. You can set this to `undef` to revert to the default formatter. ## Math Methods Like the set methods, math related methods always return the object itself, to allow for chaining: $dt->add( days => 1 )->subtract( seconds => 1 ); ### $dt->duration\_class() This returns `DateTime::Duration`, but exists so that a subclass of `DateTime.pm` can provide a different value. ### $dt->add\_duration( $duration\_object ) This method adds a `DateTime::Duration` to the current datetime. See the [DateTime::Duration](https://metacpan.org/pod/DateTime::Duration) docs for more details. ### $dt->add( parameters for DateTime::Duration ) This method is syntactic sugar around the `add_duration()` method. It simply creates a new `DateTime::Duration` object using the parameters given, and then calls the `add_duration()` method. ### $dt->add( $duration\_object ) A synonym of `$dt->add_duration( $duration_object )`. ### $dt->subtract\_duration( $duration\_object ) When given a `DateTime::Duration` object, this method simply calls `invert()` on that object and passes that new duration to the `add_duration` method. ### $dt->subtract( DateTime::Duration->new parameters ) Like `add()`, this is syntactic sugar for the `subtract_duration()` method. ### $dt->subtract( $duration\_object ) A synonym of `$dt->subtract_duration( $duration_object )`. ### $dt->subtract\_datetime( $datetime ) This method returns a new `DateTime::Duration` object representing the difference between the two dates. The duration is **relative** to the object from which `$datetime` is subtracted. For example: 2003-03-15 00:00:00.00000000 - 2003-02-15 00:00:00.00000000 ------------------------------- = 1 month Note that this duration is not an absolute measure of the amount of time between the two datetimes, because the length of a month varies, as well as due to the presence of leap seconds. The returned duration may have deltas for months, days, minutes, seconds, and nanoseconds. ### $dt->delta\_md( $datetime ) ### $dt->delta\_days( $datetime ) Each of these methods returns a new `DateTime::Duration` object representing some portion of the difference between two datetimes. The `delta_md()` method returns a duration which contains only the month and day portions of the duration is represented. The `delta_days()` method returns a duration which contains only days. The `delta_md` and `delta_days` methods truncate the duration so that any fractional portion of a day is ignored. Both of these methods operate on the date portion of a datetime only, and so effectively ignore the time zone. Unlike the subtraction methods, **these methods always return a positive (or zero) duration**. ### $dt->delta\_ms( $datetime ) Returns a duration which contains only minutes and seconds. Any day and month differences to minutes are converted to minutes and seconds. This method also **always return a positive (or zero) duration**. ### $dt->subtract\_datetime\_absolute( $datetime ) This method returns a new `DateTime::Duration` object representing the difference between the two dates in seconds and nanoseconds. This is the only way to accurately measure the absolute amount of time between two datetimes, since units larger than a second do not represent a fixed number of seconds. Note that because of leap seconds, this may not return the same result as doing this math based on the value returned by `$dt->epoch()`. ## Class Methods ### DateTime->DefaultLocale( $locale ) This can be used to specify the default locale to be used when creating DateTime objects. If unset, then "en-US" is used. ### DateTime->compare( $dt1, $dt2 ), DateTime->compare\_ignore\_floating( $dt1, $dt2 ) $cmp = DateTime->compare( $dt1, $dt2 ); $cmp = DateTime->compare_ignore_floating( $dt1, $dt2 ); Compare two DateTime objects. The semantics are compatible with Perl's `sort()` function; it returns -1 if $dt1 < $dt2, 0 if $dt1 == $dt2, 1 if $dt1 \> $dt2. If one of the two DateTime objects has a floating time zone, it will first be converted to the time zone of the other object. This is what you want most of the time, but it can lead to inconsistent results when you compare a number of DateTime objects, some of which are floating, and some of which are in other time zones. If you want to have consistent results (because you want to sort a number of objects, for example), you can use the `compare_ignore_floating()` method: @dates = sort { DateTime->compare_ignore_floating($a, $b) } @dates; In this case, objects with a floating time zone will be sorted as if they were UTC times. Since DateTime objects overload comparison operators, this: @dates = sort @dates; is equivalent to this: @dates = sort { DateTime->compare($a, $b) } @dates; DateTime objects can be compared to any other calendar class that implements the `utc_rd_values()` method. ## Testing Code That Uses DateTime If you are trying to test code that calls uses DateTime, you may want to be able to explicitly set the value returned by Perl's `time()` builtin. This builtin is called by `DateTime->now()` and `DateTime->today()`. You can override `CORE::GLOBAL::time()`, but this will only work if you do this **before** loading DateTime. If doing this is inconvenient, you can also override `DateTime::_core_time()`: no warnings 'redefine'; local *DateTime::_core_time = sub { return 42 }; DateTime is guaranteed to call this subroutine to get the current `time()` value. You can also override the `_core_time()` sub in a subclass of DateTime and use that. ## How DateTime Math Works It's important to have some understanding of how datetime math is implemented in order to effectively use this module and `DateTime::Duration`. ### Making Things Simple If you want to simplify your life and not have to think too hard about the nitty-gritty of datetime math, I have several recommendations: - use the floating time zone If you do not care about time zones or leap seconds, use the "floating" timezone: my $dt = DateTime->now( time_zone => 'floating' ); Math done on two objects in the floating time zone produces very predictable results. Note that in most cases you will want to start by creating an object in a specific zone and _then_ convert it to the floating time zone. When an object goes from a real zone to the floating zone, the time for the object remains the same. This means that passing the floating zone to a constructor may not do what you want. my $dt = DateTime->now( time_zone => 'floating' ); is equivalent to my $dt = DateTime->now( time_zone => 'UTC' )->set_time_zone('floating'); This might not be what you wanted. Instead, you may prefer to do this: my $dt = DateTime->now( time_zone => 'local' )->set_time_zone('floating'); - use UTC for all calculations If you do care about time zones (particularly DST) or leap seconds, try to use non-UTC time zones for presentation and user input only. Convert to UTC immediately and convert back to the local time zone for presentation: my $dt = DateTime->new( %user_input, time_zone => $user_tz ); $dt->set_time_zone('UTC'); # do various operations - store it, retrieve it, add, subtract, etc. $dt->set_time_zone($user_tz); print $dt->datetime; - math on non-UTC time zones If you need to do date math on objects with non-UTC time zones, please read the caveats below carefully. The results `DateTime.pm` produces are predictable and correct, and mostly intuitive, but datetime math gets very ugly when time zones are involved, and there are a few strange corner cases involving subtraction of two datetimes across a DST change. If you can always use the floating or UTC time zones, you can skip ahead to [Leap Seconds and Date Math](https://metacpan.org/pod/Leap Seconds and Date Math) - date vs datetime math If you only care about the date (calendar) portion of a datetime, you should use either `delta_md()` or `delta_days()`, not `subtract_datetime()`. This will give predictable, unsurprising results, free from DST-related complications. - subtract\_datetime() and add\_duration() You must convert your datetime objects to the UTC time zone before doing date math if you want to make sure that the following formulas are always true: $dt2 - $dt1 = $dur $dt1 + $dur = $dt2 $dt2 - $dur = $dt1 Note that using `delta_days` ensures that this formula always works, regardless of the timezone of the objects involved, as does using `subtract_datetime_absolute()`. Other methods of subtraction are not always reversible. - never do math on two objects where only one is in the floating time zone The date math code accounts for leap seconds whenever the `DateTime` object is not in the floating time zone. If you try to do math where one object is in the floating zone and the other isn't, the results will be confusing and wrong. ### Adding a Duration to a Datetime The parts of a duration can be broken down into five parts. These are months, days, minutes, seconds, and nanoseconds. Adding one month to a date is different than adding 4 weeks or 28, 29, 30, or 31 days. Similarly, due to DST and leap seconds, adding a day can be different than adding 86,400 seconds, and adding a minute is not exactly the same as 60 seconds. We cannot convert between these units, except for seconds and nanoseconds, because there is no fixed conversion between the two units, because of things like leap seconds, DST changes, etc. `DateTime.pm` always adds (or subtracts) days, then months, minutes, and then seconds and nanoseconds. If there are any boundary overflows, these are normalized at each step. For the days and months the local (not UTC) values are used. For minutes and seconds, the local values are used. This generally just works. This means that adding one month and one day to February 28, 2003 will produce the date April 1, 2003, not March 29, 2003. my $dt = DateTime->new( year => 2003, month => 2, day => 28 ); $dt->add( months => 1, days => 1 ); # 2003-04-01 - the result On the other hand, if we add months first, and then separately add days, we end up with March 29, 2003: $dt->add( months => 1 )->add( days => 1 ); # 2003-03-29 We see similar strangeness when math crosses a DST boundary: my $dt = DateTime->new( year => 2003, month => 4, day => 5, hour => 1, minute => 58, time_zone => "America/Chicago", ); $dt->add( days => 1, minutes => 3 ); # 2003-04-06 02:01:00 $dt->add( minutes => 3 )->add( days => 1 ); # 2003-04-06 03:01:00 Note that if you converted the datetime object to UTC first you would get predictable results. If you want to know how many seconds a duration object represents, you have to add it to a datetime to find out, so you could do: my $now = DateTime->now( time_zone => 'UTC' ); my $later = $now->clone->add_duration($duration); my $seconds_dur = $later->subtract_datetime_absolute($now); This returns a duration which only contains seconds and nanoseconds. If we were add the duration to a different datetime object we might get a different number of seconds. [DateTime::Duration](https://metacpan.org/pod/DateTime::Duration) supports three different end-of-month algorithms for adding months. This comes into play when an addition results in a day past the end of the month (for example, adding one month to January 30). # 2010-08-31 + 1 month = 2010-10-01 $dt->add( months => 1, end_of_month => 'wrap' ); # 2010-01-30 + 1 month = 2010-02-28 $dt->add( months => 1, end_of_month => 'limit' ); # 2010-04-30 + 1 month = 2010-05-31 $dt->add( months => 1, end_of_month => 'preserve' ); By default, it uses "wrap" for positive durations and "preserve" for negative durations. See [DateTime::Duration](https://metacpan.org/pod/DateTime::Duration) for a detailed explanation of these algorithms. If you need to do lots of work with durations, take a look at Rick Measham's `DateTime::Format::Duration` module, which lets you present information from durations in many useful ways. There are other subtract/delta methods in DateTime.pm to generate different types of durations. These methods are `subtract_datetime()`, `subtract_datetime_absolute()`, `delta_md()`, `delta_days()`, and `delta_ms()`. ### Datetime Subtraction Date subtraction is done solely based on the two object's local datetimes, with one exception to handle DST changes. Also, if the two datetime objects are in different time zones, one of them is converted to the other's time zone first before subtraction. This is best explained through examples: The first of these probably makes the most sense: my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, time_zone => 'America/Chicago', ); # not DST my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, time_zone => 'America/Chicago', ); # is DST my $dur = $dt2->subtract_datetime($dt1); # 6 months Nice and simple. This one is a little trickier, but still fairly logical: my $dt1 = DateTime->new( year => 2003, month => 4, day => 5, hour => 1, minute => 58, time_zone => "America/Chicago", ); # is DST my $dt2 = DateTime->new( year => 2003, month => 4, day => 7, hour => 2, minute => 1, time_zone => "America/Chicago", ); # not DST my $dur = $dt2->subtract_datetime($dt1); # 2 days and 3 minutes Which contradicts the result this one gives, even though they both make sense: my $dt1 = DateTime->new( year => 2003, month => 4, day => 5, hour => 1, minute => 58, time_zone => "America/Chicago", ); # is DST my $dt2 = DateTime->new( year => 2003, month => 4, day => 6, hour => 3, minute => 1, time_zone => "America/Chicago", ); # not DST my $dur = $dt2->subtract_datetime($dt1); # 1 day and 3 minutes This last example illustrates the "DST" exception mentioned earlier. The exception accounts for the fact 2003-04-06 only lasts 23 hours. And finally: my $dt2 = DateTime->new( year => 2003, month => 10, day => 26, hour => 1, time_zone => 'America/Chicago', ); my $dt1 = $dt2->clone->subtract( hours => 1 ); my $dur = $dt2->subtract_datetime($dt1); # 60 minutes This seems obvious until you realize that subtracting 60 minutes from `$dt2` in the above example still leaves the clock time at "01:00:00". This time we are accounting for a 25 hour day. ### Reversibility Date math operations are not always reversible. This is because of the way that addition operations are ordered. As was discussed earlier, adding 1 day and 3 minutes in one call to `add()` is not the same as first adding 3 minutes and 1 day in two separate calls. If we take a duration returned from `subtract_datetime()` and then try to add or subtract that duration from one of the datetimes we just used, we sometimes get interesting results: my $dt1 = DateTime->new( year => 2003, month => 4, day => 5, hour => 1, minute => 58, time_zone => "America/Chicago", ); my $dt2 = DateTime->new( year => 2003, month => 4, day => 6, hour => 3, minute => 1, time_zone => "America/Chicago", ); my $dur = $dt2->subtract_datetime($dt1); # 1 day and 3 minutes $dt1->add_duration($dur); # gives us $dt2 $dt2->subtract_duration($dur); # gives us 2003-04-05 02:58:00 - 1 hour later than $dt1 The `subtract_duration()` operation gives us a (perhaps) unexpected answer because it first subtracts one day to get 2003-04-05T03:01:00 and then subtracts 3 minutes to get the final result. If we explicitly reverse the order we can get the original value of `$dt1`. This can be facilitated by `DateTime::Duration`'s `calendar_duration()` and `clock_duration()` methods: $dt2->subtract_duration( $dur->clock_duration ) ->subtract_duration( $dur->calendar_duration ); ### Leap Seconds and Date Math The presence of leap seconds can cause even more anomalies in date math. For example, the following is a legal datetime: my $dt = DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 60, time_zone => 'UTC' ); If we do the following: $dt->add( months => 1 ); Then the datetime is now "1973-02-01 00:00:00", because there is no 23:59:60 on 1973-01-31. Leap seconds also force us to distinguish between minutes and seconds during date math. Given the following datetime: my $dt = DateTime->new( year => 1972, month => 12, day => 31, hour => 23, minute => 59, second => 30, time_zone => 'UTC' ); we will get different results when adding 1 minute than we get if we add 60 seconds. This is because in this case, the last minute of the day, beginning at 23:59:00, actually contains 61 seconds. Here are the results we get: # 1972-12-31 23:59:30 - our starting datetime $dt->clone->add( minutes => 1 ); # 1973-01-01 00:00:30 - one minute later $dt->clone->add( seconds => 60 ); # 1973-01-01 00:00:29 - 60 seconds later $dt->clone->add( seconds => 61 ); # 1973-01-01 00:00:30 - 61 seconds later ### Local vs. UTC and 24 hours vs. 1 day When math crosses a daylight saving boundary, a single day may have more or less than 24 hours. For example, if you do this: my $dt = DateTime->new( year => 2003, month => 4, day => 5, hour => 2, time_zone => 'America/Chicago', ); $dt->add( days => 1 ); then you will produce an _invalid_ local time, and therefore an exception will be thrown. However, this works: my $dt = DateTime->new( year => 2003, month => 4, day => 5, hour => 2, time_zone => 'America/Chicago', ); $dt->add( hours => 24 ); and produces a datetime with the local time of "03:00". If all this makes your head hurt, there is a simple alternative. Just convert your datetime object to the "UTC" time zone before doing date math on it, and switch it back to the local time zone afterwards. This avoids the possibility of having date math throw an exception, and makes sure that 1 day equals 24 hours. Of course, this may not always be desirable, so caveat user! ## Overloading This module explicitly overloads the addition (+), subtraction (-), string and numeric comparison operators. This means that the following all do sensible things: my $new_dt = $dt + $duration_obj; my $new_dt = $dt - $duration_obj; my $duration_obj = $dt - $new_dt; foreach my $dt ( sort @dts ) { ... } Additionally, the fallback parameter is set to true, so other derivable operators (+=, -=, etc.) will work properly. Do not expect increment (++) or decrement (--) to do anything useful. The string comparison operators, `eq` or `ne`, will use the string value to compare with non-DateTime objects. DateTime objects do not have a numeric value, using `==` or `<=>` to compare a DateTime object with a non-DateTime object will result in an exception. To safely sort mixed DateTime and non-DateTime objects, use `sort { $a cmp $b } @dates`. The module also overloads stringification using the object's formatter, defaulting to `iso8601()` method. See ["Formatters And Stringification"](#formatters-and-stringification) for details. ## Formatters And Stringification You can optionally specify a "formatter", which is usually a DateTime::Format::\* object/class, to control the stringification of the DateTime object. Any of the constructor methods can accept a formatter argument: my $formatter = DateTime::Format::Strptime->new(...); my $dt = DateTime->new(year => 2004, formatter => $formatter); Or, you can set it afterwards: $dt->set_formatter($formatter); $formatter = $dt->formatter(); Once you set the formatter, the overloaded stringification method will use the formatter. If unspecified, the `iso8601()` method is used. A formatter can be handy when you know that in your application you want to stringify your DateTime objects into a special format all the time, for example to a different language. If you provide a formatter class name or object, it must implement a `format_datetime` method. This method will be called with just the DateTime object as its argument. ## CLDR Patterns The CLDR pattern language is both more powerful and more complex than strftime. Unlike strftime patterns, you often have to explicitly escape text that you do not want formatted, as the patterns are simply letters without any prefix. For example, "yyyy-MM-dd" is a valid CLDR pattern. If you want to include any lower or upper case ASCII characters as-is, you can surround them with single quotes ('). If you want to include a single quote, you must escape it as two single quotes (''). 'Today is ' EEEE 'It is now' h 'o''clock' a Spaces and any non-letter text will always be passed through as-is. Many CLDR patterns which produce numbers will pad the number with leading zeroes depending on the length of the format specifier. For example, "h" represents the current hour from 1-12. If you specify "hh" then the 1-9 will have a leading zero prepended. However, CLDR often uses five of a letter to represent the narrow form of a pattern. This inconsistency is necessary for backwards compatibility. CLDR often distinguishes between the "format" and "stand-alone" forms of a pattern. The format pattern is used when the thing in question is being placed into a larger string. The stand-alone form is used when displaying that item by itself, for example in a calendar. It also often provides three sizes for each item, wide (the full name), abbreviated, and narrow. The narrow form is often just a single character, for example "T" for "Tuesday", and may not be unique. CLDR provides a fairly complex system for localizing time zones that we ignore entirely. The time zone patterns just use the information provided by `DateTime::TimeZone`, and _do not follow the CLDR spec_. The output of a CLDR pattern is always localized, when applicable. CLDR provides the following patterns: - G{1,3} The abbreviated era (BC, AD). - GGGG The wide era (Before Christ, Anno Domini). - GGGGG The narrow era, if it exists (and it mostly doesn't). - y and y{3,} The year, zero-prefixed as needed. Negative years will start with a "-", and this will be included in the length calculation. In other, words the "yyyyy" pattern will format year -1234 as "-1234", not "-01234". - yy This is a special case. It always produces a two-digit year, so "1976" becomes "76". Negative years will start with a "-", making them one character longer. - Y{1,} The year in "week of the year" calendars, from `$dt->week_year()`. - u{1,} Same as "y" except that "uu" is not a special case. - Q{1,2} The quarter as a number (1..4). - QQQ The abbreviated format form for the quarter. - QQQQ The wide format form for the quarter. - q{1,2} The quarter as a number (1..4). - qqq The abbreviated stand-alone form for the quarter. - qqqq The wide stand-alone form for the quarter. - M{1,2\] The numerical month. - MMM The abbreviated format form for the month. - MMMM The wide format form for the month. - MMMMM The narrow format form for the month. - L{1,2\] The numerical month. - LLL The abbreviated stand-alone form for the month. - LLLL The wide stand-alone form for the month. - LLLLL The narrow stand-alone form for the month. - w{1,2} The week of the year, from `$dt->week_number()`. - W The week of the month, from `$dt->week_of_month()`. - d{1,2} The numeric day of the month. - D{1,3} The numeric day of the year. - F The day of the week in the month, from `$dt->weekday_of_month()`. - g{1,} The modified Julian day, from `$dt->mjd()`. - E{1,3} and eee The abbreviated format form for the day of the week. - EEEE and eeee The wide format form for the day of the week. - EEEEE and eeeee The narrow format form for the day of the week. - e{1,2} The _local_ numeric day of the week, from 1 to 7. This number depends on what day is considered the first day of the week, which varies by locale. For example, in the US, Sunday is the first day of the week, so this returns 2 for Monday. - c The numeric day of the week from 1 to 7, treating Monday as the first of the week, regardless of locale. - ccc The abbreviated stand-alone form for the day of the week. - cccc The wide stand-alone form for the day of the week. - ccccc The narrow format form for the day of the week. - a The localized form of AM or PM for the time. - h{1,2} The hour from 1-12. - H{1,2} The hour from 0-23. - K{1,2} The hour from 0-11. - k{1,2} The hour from 1-24. - j{1,2} The hour, in 12 or 24 hour form, based on the preferred form for the locale. In other words, this is equivalent to either "h{1,2}" or "H{1,2}". - m{1,2} The minute. - s{1,2} The second. - S{1,} The fractional portion of the seconds, rounded based on the length of the specifier. This returned _without_ a leading decimal point, but may have leading or trailing zeroes. - A{1,} The millisecond of the day, based on the current time. In other words, if it is 12:00:00.00, this returns 43200000. - z{1,3} The time zone short name. - zzzz The time zone long name. - Z{1,3} The time zone offset. - ZZZZ The time zone short name and the offset as one string, so something like "CDT-0500". - ZZZZZ The time zone offset as a sexagesimal number, so something like "-05:00". (This is useful for W3C format.) - v{1,3} The time zone short name. - vvvv The time zone long name. - V{1,3} The time zone short name. - VVVV The time zone long name. ### CLDR "Available Formats" The CLDR data includes pre-defined formats for various patterns such as "month and day" or "time of day". Using these formats lets you render information about a datetime in the most natural way for users from a given locale. These formats are indexed by a key that is itself a CLDR pattern. When you look these up, you get back a different CLDR pattern suitable for the locale. Let's look at some example We'll use `2008-02-05T18:30:30` as our example datetime value, and see how this is rendered for the `en-US` and `fr-FR` locales. - `MMMd` The abbreviated month and day as number. For `en-US`, we get the pattern `MMM d`, which renders as `Feb 5`. For `fr-FR`, we get the pattern `d MMM`, which renders as `5 févr.`. - `yQQQ` The year and abbreviated quarter of year. For `en-US`, we get the pattern `QQQ y`, which renders as `Q1 2008`. For `fr-FR`, we get the same pattern, `QQQ y`, which renders as `T1 2008`. - `hm` The 12-hour time of day without seconds. For `en-US`, we get the pattern `h:mm a`, which renders as `6:30 PM`. For `fr-FR`, we get the exact same pattern and rendering. The available formats for each locale are documented in the POD for that locale. To get back the format, you use the `$locale->format_for` method. For example: say $dt->format_cldr( $dt->locale->format_for('MMMd') ); ## strftime Patterns The following patterns are allowed in the format string given to the `$dt->strftime()` method: - %a The abbreviated weekday name. - %A The full weekday name. - %b The abbreviated month name. - %B The full month name. - %c The default datetime format for the object's locale. - %C The century number (year/100) as a 2-digit integer. - %d The day of the month as a decimal number (range 01 to 31). - %D Equivalent to %m/%d/%y. This is not a good standard format if you want folks from both the United States and the rest of the world to understand the date! - %e Like %d, the day of the month as a decimal number, but a leading zero is replaced by a space. - %F Equivalent to %Y-%m-%d (the ISO 8601 date format) - %G The ISO 8601 year with century as a decimal number. The 4-digit year corresponding to the ISO week number (see %V). This has the same format and value as %Y, except that if the ISO week number belongs to the previous or next year, that year is used instead. (TZ) - %g Like %G, but without century, i.e., with a 2-digit year (00-99). - %h Equivalent to %b. - %H The hour as a decimal number using a 24-hour clock (range 00 to 23). - %I The hour as a decimal number using a 12-hour clock (range 01 to 12). - %j The day of the year as a decimal number (range 001 to 366). - %k The hour (24-hour clock) as a decimal number (range 0 to 23); single digits are preceded by a blank. (See also %H.) - %l The hour (12-hour clock) as a decimal number (range 1 to 12); single digits are preceded by a blank. (See also %I.) - %m The month as a decimal number (range 01 to 12). - %M The minute as a decimal number (range 00 to 59). - %n A newline character. - %N The fractional seconds digits. Default is 9 digits (nanoseconds). %3N milliseconds (3 digits) %6N microseconds (6 digits) %9N nanoseconds (9 digits) This value will always be rounded down to the nearest integer. - %p Either \`AM' or \`PM' according to the given time value, or the corresponding strings for the current locale. Noon is treated as \`pm' and midnight as \`am'. - %P Like %p but in lowercase: \`am' or \`pm' or a corresponding string for the current locale. - %r The time in a.m. or p.m. notation. In the POSIX locale this is equivalent to \`%I:%M:%S %p'. - %R The time in 24-hour notation (%H:%M). (SU) For a version including the seconds, see %T below. - %s The number of seconds since the epoch. - %S The second as a decimal number (range 00 to 61). - %t A tab character. - %T The time in 24-hour notation (%H:%M:%S). - %u The day of the week as a decimal, range 1 to 7, Monday being 1. See also %w. - %U The week number of the current year as a decimal number, range 00 to 53, starting with the first Sunday as the first day of week 01. See also %V and %W. - %V The ISO 8601:1988 week number of the current year as a decimal number, range 01 to 53, where week 1 is the first week that has at least 4 days in the current year, and with Monday as the first day of the week. See also %U and %W. - %w The day of the week as a decimal, range 0 to 6, Sunday being 0. See also %u. - %W The week number of the current year as a decimal number, range 00 to 53, starting with the first Monday as the first day of week 01. - %x The default date format for the object's locale. - %X The default time format for the object's locale. - %y The year as a decimal number without a century (range 00 to 99). - %Y The year as a decimal number including the century. - %z The time-zone as hour offset from UTC. Required to emit RFC822-conformant dates (using "%a, %d %b %Y %H:%M:%S %z"). - %Z The time zone or name or abbreviation. - %% A literal \`%' character. - %{method} Any method name may be specified using the format `%{method}` name where "method" is a valid `DateTime.pm` object method. ## DateTime.pm and Storable DateTime implements Storable hooks in order to reduce the size of a serialized DateTime object. # THE DATETIME PROJECT ECOSYSTEM This module is part of a larger ecosystem of modules in the DateTime family. ## [DateTime::Set](https://metacpan.org/pod/DateTime::Set) The [DateTime::Set](https://metacpan.org/pod/DateTime::Set) module represents sets (including recurrences) of datetimes. Many modules return sets or recurrences. ## Format Modules The various format modules exist to parse and format datetimes. For example, [DateTime::Format::HTTP](https://metacpan.org/pod/DateTime::Format::HTTP) parses dates according to the RFC 1123 format: my $datetime = DateTime::Format::HTTP->parse_datetime('Thu Feb 3 17:03:55 GMT 1994'); print DateTime::Format::HTTP->format_datetime($datetime); Most format modules are suitable for use as a `formatter` with a DateTime object. All format modules start with `DateTime::Format::`. ## Calendar Modules There are a number of modules on CPAN that implement non-Gregorian calendars, such as the Chinese, Mayan, and Julian calendars. All calendar modules start with `DateTime::Calendar::`. ## Event Modules There are a number of modules that calculate the dates for events, such as Easter, Sunrise, etc. All event modules start with `DateTime::Event::`. ## Others There are many other modules that work with DateTime, including modules in the `DateTimeX` namespace, as well as others. See the [datetime wiki](http://datetime.perl.org) and [search.cpan.org](http://search.cpan.org/search?query=datetime&mode=dist) for more details. # KNOWN BUGS The tests in `20infinite.t` seem to fail on some machines, particularly on Win32. This appears to be related to Perl's internal handling of IEEE infinity and NaN, and seems to be highly platform/compiler/phase of moon dependent. If you don't plan to use infinite datetimes you can probably ignore this. This will be fixed (perhaps) in future versions. # SEE ALSO [A Date with Perl](http://www.houseabsolute.com/presentations/a-date-with-perl/) - a talk I've given at a few YAPCs. [datetime@perl.org mailing list](http://lists.perl.org/list/datetime.html) [http://datetime.perl.org/](http://datetime.perl.org/) # SUPPORT Bugs may be submitted at [https://github.com/houseabsolute/DateTime.pm/issues](https://github.com/houseabsolute/DateTime.pm/issues). There is a mailing list available for users of this distribution, [mailto:datetime@perl.org](mailto:datetime@perl.org). I am also usually active on IRC as 'autarch' on `irc://irc.perl.org`. # SOURCE The source code repository for DateTime can be found at [https://github.com/houseabsolute/DateTime.pm](https://github.com/houseabsolute/DateTime.pm). # DONATIONS If you'd like to thank me for the work I've done on this module, please consider making a "donation" to me via PayPal. I spend a lot of free time creating free software, and would appreciate any support you'd care to offer. Please note that **I am not suggesting that you must do this** in order for me to continue working on this particular software. I will continue to do so, inasmuch as I have in the past, for as long as it interests me. Similarly, a donation made in this way will probably not make me work on this software much more, unless I get so many donations that I can consider working on free software full time (let's all have a chuckle at that together). To donate, log into PayPal and send money to autarch@urth.org, or use the button at [http://www.urth.org/~autarch/fs-donation.html](http://www.urth.org/~autarch/fs-donation.html). # AUTHOR Dave Rolsky # CONTRIBUTORS - Ben Bennett - Christian Hansen - Daisuke Maki - Dan Book - Dan Stewart - David E. Wheeler - David Precious - Doug Bell - Flávio Soibelmann Glock - Gianni Ceccarelli - Gregory Oschwald - Hauke D - Iain Truskett <deceased> - Jason McIntosh - Joshua Hoblitt - Karen Etheridge - Michael Conrad - Michael R. Davis - M Somerville - Nick Tonkin <1nickt@users.noreply.github.com> - Olaf Alders - Ovid <curtis\_ovid\_poe@yahoo.com> - Philippe Bruhat (BooK) - Ricardo Signes - Richard Bowen - Ron Hill - Sam Kington - viviparous <viviparous@prc> # COPYRIGHT AND LICENSE This software is Copyright (c) 2003 - 2018 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) The full text of the license can be found in the `LICENSE` file included with this distribution. DateTime-1.46/MANIFEST0000644000175000017500000000554213240151623014134 0ustar autarchautarch# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.010. CONTRIBUTING.md CREDITS Changes DateTime.xs INSTALL LICENSE MANIFEST META.json META.yml Makefile.PL README.md TODO appveyor.yml cpanfile dist.ini inc/LeapSecondsHeader.pm leap_seconds.h leaptab.txt lib/DateTime.pm lib/DateTime/Conflicts.pm lib/DateTime/Duration.pm lib/DateTime/Helpers.pm lib/DateTime/Infinite.pm lib/DateTime/LeapSecond.pm lib/DateTime/PP.pm lib/DateTime/PPExtra.pm lib/DateTime/Types.pm perlcriticrc perltidyrc ppport.h t/00-report-prereqs.dd t/00-report-prereqs.t t/00load.t t/01sanity.t t/02last-day.t t/03components.t t/04epoch.t t/05set.t t/06add.t t/07compare.t t/09greg.t t/10subtract.t t/11duration.t t/12week.t t/13strftime.t t/14locale.t t/15jd.t t/16truncate.t t/17set-return.t t/18today.t t/19leap-second.t t/20infinite.t t/21bad-params.t t/22from-doy.t t/23storable.t t/24from-object.t t/25add-subtract.t t/26dt-leapsecond-pm.t t/27delta.t t/28dow.t t/29overload.t t/30future-tz.t t/31formatter.t t/32leap-second2.t t/33seconds-offset.t t/34set-tz.t t/35rd-values.t t/36invalid-local.t t/37local-add.t t/38local-subtract.t t/39no-so.t t/40leap-years.t t/41cldr-format.t t/42duration-class.t t/43new-params.t t/44set-formatter.t t/45core-time.t t/46warnings.t t/47default-time-zone.t t/48rt-115983.t t/zzz-check-breaks.t tidyall.ini xt/author/clean-namespaces.t xt/author/eol.t xt/author/mojibake.t xt/author/no-tabs.t xt/author/pod-coverage.t xt/author/pod-spell.t xt/author/pod-syntax.t xt/author/portability.t xt/author/pp-00load.t xt/author/pp-01sanity.t xt/author/pp-02last-day.t xt/author/pp-03components.t xt/author/pp-04epoch.t xt/author/pp-05set.t xt/author/pp-06add.t xt/author/pp-07compare.t xt/author/pp-09greg.t xt/author/pp-10subtract.t xt/author/pp-11duration.t xt/author/pp-12week.t xt/author/pp-13strftime.t xt/author/pp-14locale.t xt/author/pp-15jd.t xt/author/pp-16truncate.t xt/author/pp-17set-return.t xt/author/pp-18today.t xt/author/pp-19leap-second.t xt/author/pp-20infinite.t xt/author/pp-21bad-params.t xt/author/pp-22from-doy.t xt/author/pp-23storable.t xt/author/pp-24from-object.t xt/author/pp-25add-subtract.t xt/author/pp-27delta.t xt/author/pp-28dow.t xt/author/pp-29overload.t xt/author/pp-30future-tz.t xt/author/pp-31formatter.t xt/author/pp-32leap-second2.t xt/author/pp-33seconds-offset.t xt/author/pp-34set-tz.t xt/author/pp-35rd-values.t xt/author/pp-36invalid-local.t xt/author/pp-37local-add.t xt/author/pp-38local-subtract.t xt/author/pp-40leap-years.t xt/author/pp-41cldr-format.t xt/author/pp-42duration-class.t xt/author/pp-43new-params.t xt/author/pp-44set-formatter.t xt/author/pp-45core-time.t xt/author/pp-46warnings.t xt/author/pp-47default-time-zone.t xt/author/pp-48rt-115983.t xt/author/pp-is-loaded.t xt/author/test-all-my-deps.t xt/author/test-version.t xt/author/tidyall.t xt/author/xs-is-loaded.t xt/release/cpan-changes.t xt/release/meta-json.t DateTime-1.46/CONTRIBUTING.md0000644000175000017500000001025313240151623015227 0ustar autarchautarch# CONTRIBUTING Thank you for considering contributing to this distribution. This file contains instructions that will help you work with the source code. Please note that if you have any questions or difficulties, you can reach the maintainer(s) through the bug queue described later in this document (preferred), or by emailing the releaser directly. You are not required to follow any of the steps in this document to submit a patch or bug report; these are just recommendations, intended to help you (and help us help you faster). This distribution has a TODO file in the repository; you may want to check there to see if your issue or patch idea is mentioned. The distribution is managed with [Dist::Zilla](https://metacpan.org/release/Dist-Zilla). However, you can still compile and test the code with the `Makefile.PL` or `Build.PL` in the repository: perl Makefile.PL make make test or perl Build.PL ./Build ./Build test As well as: $ prove -bvr t or $ perl -Mblib t/some_test_file.t You may need to satisfy some dependencies. The easiest way to satisfy dependencies is to install the last release. This is available at https://metacpan.org/release/DateTime If you use cpanminus, you can do it without downloading the tarball first: $ cpanm --reinstall --installdeps --with-recommends DateTime Dist::Zilla is a very powerful authoring tool, but requires a number of author-specific plugins. If you would like to use it for contributing, install it from CPAN, then run one of the following commands, depending on your CPAN client: $ cpan `dzil authordeps --missing` or $ dzil authordeps --missing | cpanm They may also be additional requirements not needed by the dzil build which are needed for tests or other development: $ cpan `dzil listdeps --author --missing` or $ dzil listdeps --author --missing | cpanm Or, you can use the 'dzil stale' command to install all requirements at once: $ cpan Dist::Zilla::App::Command::stale $ cpan `dzil stale --all` or $ cpanm Dist::Zilla::App::Command::stale $ dzil stale --all | cpanm You can also do this via cpanm directly: $ cpanm --reinstall --installdeps --with-develop --with-recommends DateTime Once installed, here are some dzil commands you might try: $ dzil build $ dzil test $ dzil test --release $ dzil xtest $ dzil listdeps --json $ dzil build --notgz You can learn more about Dist::Zilla at http://dzil.org/. The code for this distribution is [hosted at GitHub](https://github.com/houseabsolute/DateTime.pm). You can submit code changes by forking the repository, pushing your code changes to your clone, and then submitting a pull request. Detailed instructions for doing that is available here: https://help.github.com/articles/creating-a-pull-request If you have found a bug, but do not have an accompanying patch to fix it, you can submit an issue report [via the web](https://github.com/houseabsolute/DateTime.pm/issues) ). There is a mailing list available for users of this distribution, datetime@perl.org ## Travis All pull requests for this distribution will be automatically tested by [Travis](https://travis-ci.org/) and the build status will be reported on the pull request page. If your build fails, please take a look at the output. ## TidyAll This distribution uses [Code::TidyAll](https://metacpan.org/release/Code-TidyAll) to enforce a uniform coding style. This is tested as part of the author testing suite. You can install and run tidyall by running the following commands: $ cpanm Code::TidyAll $ tidyall -a Please run this before committing your changes and address any issues it brings up. ## Contributor Names If you send a patch or pull request, your name and email address will be included in the documentation as a contributor (using the attribution on the commit or patch), unless you specifically request for it not to be. If you wish to be listed under a different name or address, you should submit a pull request to the .mailmap file to contain the correct mapping. This file was generated via Dist::Zilla::Plugin::GenerateFile::FromShareDir 0.013 from a template file originating in Dist-Zilla-PluginBundle-DROLSKY-0.89. DateTime-1.46/cpanfile0000644000175000017500000000515013240151623014502 0ustar autarchautarchrequires "Carp" => "0"; requires "DateTime::Locale" => "1.06"; requires "DateTime::TimeZone" => "2.02"; requires "Dist::CheckConflicts" => "0.02"; requires "POSIX" => "0"; requires "Params::ValidationCompiler" => "0.26"; requires "Scalar::Util" => "0"; requires "Specio" => "0.18"; requires "Specio::Declare" => "0"; requires "Specio::Exporter" => "0"; requires "Specio::Library::Builtins" => "0"; requires "Specio::Library::Numeric" => "0"; requires "Specio::Library::String" => "0"; requires "Try::Tiny" => "0"; requires "XSLoader" => "0"; requires "base" => "0"; requires "integer" => "0"; requires "namespace::autoclean" => "0.19"; requires "overload" => "0"; requires "parent" => "0"; requires "perl" => "5.008004"; requires "strict" => "0"; requires "warnings" => "0"; requires "warnings::register" => "0"; on 'test' => sub { requires "CPAN::Meta::Check" => "0.011"; requires "CPAN::Meta::Requirements" => "0"; requires "ExtUtils::MakeMaker" => "0"; requires "File::Spec" => "0"; requires "Storable" => "0"; requires "Test::Fatal" => "0"; requires "Test::More" => "0.96"; requires "Test::Warnings" => "0.005"; requires "utf8" => "0"; }; on 'test' => sub { recommends "CPAN::Meta" => "2.120900"; }; on 'configure' => sub { requires "Dist::CheckConflicts" => "0.02"; requires "ExtUtils::MakeMaker" => "0"; }; on 'configure' => sub { suggests "JSON::PP" => "2.27300"; }; on 'develop' => sub { requires "Code::TidyAll" => "0.56"; requires "Code::TidyAll::Plugin::SortLines::Naturally" => "0.000003"; requires "Code::TidyAll::Plugin::Test::Vars" => "0.02"; requires "Cwd" => "0"; requires "Devel::PPPort" => "3.23"; requires "Module::Implementation" => "0"; requires "Parallel::ForkManager" => "1.19"; requires "Perl::Critic" => "1.126"; requires "Perl::Tidy" => "20160302"; requires "Pod::Coverage::TrustPod" => "0"; requires "Pod::Wordlist" => "0"; requires "Storable" => "0"; requires "Test::CPAN::Changes" => "0.19"; requires "Test::CPAN::Meta::JSON" => "0.16"; requires "Test::CleanNamespaces" => "0.15"; requires "Test::Code::TidyAll" => "0.50"; requires "Test::DependentModules" => "0"; requires "Test::EOL" => "0"; requires "Test::Fatal" => "0"; requires "Test::Mojibake" => "0"; requires "Test::More" => "0.96"; requires "Test::NoTabs" => "0"; requires "Test::Pod" => "1.41"; requires "Test::Pod::Coverage" => "1.08"; requires "Test::Portability::Files" => "0"; requires "Test::Spelling" => "0.12"; requires "Test::Vars" => "0.009"; requires "Test::Version" => "2.05"; requires "Test::Warnings" => "0.005"; requires "autodie" => "0"; requires "utf8" => "0"; }; DateTime-1.46/LICENSE0000644000175000017500000002152713240151623014011 0ustar autarchautarchThis software is Copyright (c) 2003 - 2018 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) The Artistic License 2.0 Copyright (c) 2000-2006, The Perl Foundation. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software. You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement. Definitions "Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package. "Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures. "You" and "your" means any person who would like to copy, distribute, or modify the Package. "Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version. "Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization. "Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees. "Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder. "Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder. "Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future. "Source" form means the source code, documentation source, and configuration files for the Package. "Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form. Permission for Use and Modification Without Distribution (1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version. Permissions for Redistribution of the Standard Version (2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package. (3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License. Distribution of Modified Versions of the Package as Source (4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following: (a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version. (b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version. (c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under (i) the Original License or (ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed. Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source (5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license. (6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version. Aggregating or Linking the Package (7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation. (8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package. Items That are Not Considered Part of a Modified Version (9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license. General Provisions (10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license. (11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license. (12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder. (13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed. (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DateTime-1.46/META.json0000644000175000017500000012215113240151623014420 0ustar autarchautarch{ "abstract" : "A date and time object for Perl", "author" : [ "Dave Rolsky " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.010, CPAN::Meta::Converter version 2.150010", "license" : [ "artistic_2" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "DateTime", "prereqs" : { "configure" : { "requires" : { "Dist::CheckConflicts" : "0.02", "ExtUtils::MakeMaker" : "0" }, "suggests" : { "JSON::PP" : "2.27300" } }, "develop" : { "requires" : { "Code::TidyAll" : "0.56", "Code::TidyAll::Plugin::SortLines::Naturally" : "0.000003", "Code::TidyAll::Plugin::Test::Vars" : "0.02", "Cwd" : "0", "Devel::PPPort" : "3.23", "Module::Implementation" : "0", "Parallel::ForkManager" : "1.19", "Perl::Critic" : "1.126", "Perl::Tidy" : "20160302", "Pod::Coverage::TrustPod" : "0", "Pod::Wordlist" : "0", "Storable" : "0", "Test::CPAN::Changes" : "0.19", "Test::CPAN::Meta::JSON" : "0.16", "Test::CleanNamespaces" : "0.15", "Test::Code::TidyAll" : "0.50", "Test::DependentModules" : "0", "Test::EOL" : "0", "Test::Fatal" : "0", "Test::Mojibake" : "0", "Test::More" : "0.96", "Test::NoTabs" : "0", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::Portability::Files" : "0", "Test::Spelling" : "0.12", "Test::Vars" : "0.009", "Test::Version" : "2.05", "Test::Warnings" : "0.005", "autodie" : "0", "utf8" : "0" } }, "runtime" : { "requires" : { "Carp" : "0", "DateTime::Locale" : "1.06", "DateTime::TimeZone" : "2.02", "Dist::CheckConflicts" : "0.02", "POSIX" : "0", "Params::ValidationCompiler" : "0.26", "Scalar::Util" : "0", "Specio" : "0.18", "Specio::Declare" : "0", "Specio::Exporter" : "0", "Specio::Library::Builtins" : "0", "Specio::Library::Numeric" : "0", "Specio::Library::String" : "0", "Try::Tiny" : "0", "XSLoader" : "0", "base" : "0", "integer" : "0", "namespace::autoclean" : "0.19", "overload" : "0", "parent" : "0", "perl" : "5.008004", "strict" : "0", "warnings" : "0", "warnings::register" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "CPAN::Meta::Check" : "0.011", "CPAN::Meta::Requirements" : "0", "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "Storable" : "0", "Test::Fatal" : "0", "Test::More" : "0.96", "Test::Warnings" : "0.005", "utf8" : "0" } } }, "provides" : { "DateTime" : { "file" : "lib/DateTime.pm", "version" : "1.46" }, "DateTime::Duration" : { "file" : "lib/DateTime/Duration.pm", "version" : "1.46" }, "DateTime::Helpers" : { "file" : "lib/DateTime/Helpers.pm", "version" : "1.46" }, "DateTime::Infinite" : { "file" : "lib/DateTime/Infinite.pm", "version" : "1.46" }, "DateTime::Infinite::Future" : { "file" : "lib/DateTime/Infinite.pm", "version" : "1.46" }, "DateTime::Infinite::Past" : { "file" : "lib/DateTime/Infinite.pm", "version" : "1.46" }, "DateTime::LeapSecond" : { "file" : "lib/DateTime/LeapSecond.pm", "version" : "1.46" }, "DateTime::PP" : { "file" : "lib/DateTime/PP.pm", "version" : "1.46" }, "DateTime::PPExtra" : { "file" : "lib/DateTime/PPExtra.pm", "version" : "1.46" }, "DateTime::Types" : { "file" : "lib/DateTime/Types.pm", "version" : "1.46" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/houseabsolute/DateTime.pm/issues" }, "homepage" : "http://metacpan.org/release/DateTime", "repository" : { "type" : "git", "url" : "git://github.com/houseabsolute/DateTime.pm.git", "web" : "https://github.com/houseabsolute/DateTime.pm" }, "x_MailingList" : "datetime@perl.org" }, "version" : "1.46", "x_Dist_Zilla" : { "perl" : { "version" : "5.026001" }, "plugins" : [ { "class" : "Dist::Zilla::Plugin::PruneCruft", "name" : "PruneCruft", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::MakeMaker", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : 1 } }, "name" : "@DROLSKY/MakeMaker", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::Git::GatherDir", "config" : { "Dist::Zilla::Plugin::GatherDir" : { "exclude_filename" : [ "CONTRIBUTING.md", "LICENSE", "Makefile.PL", "README.md", "cpanfile", "leap_seconds.h", "ppport.h" ], "exclude_match" : [], "follow_symlinks" : 0, "include_dotfiles" : 0, "prefix" : "", "prune_directory" : [], "root" : "." }, "Dist::Zilla::Plugin::Git::GatherDir" : { "include_untracked" : 0 } }, "name" : "@DROLSKY/Git::GatherDir", "version" : "2.043" }, { "class" : "Dist::Zilla::Plugin::ManifestSkip", "name" : "@DROLSKY/ManifestSkip", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::License", "name" : "@DROLSKY/License", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::ExecDir", "name" : "@DROLSKY/ExecDir", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::ShareDir", "name" : "@DROLSKY/ShareDir", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::Manifest", "name" : "@DROLSKY/Manifest", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::CheckVersionIncrement", "name" : "@DROLSKY/CheckVersionIncrement", "version" : "0.121750" }, { "class" : "Dist::Zilla::Plugin::TestRelease", "name" : "@DROLSKY/TestRelease", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::ConfirmRelease", "name" : "@DROLSKY/ConfirmRelease", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::UploadToCPAN", "name" : "@DROLSKY/UploadToCPAN", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::VersionFromMainModule", "name" : "@DROLSKY/VersionFromMainModule", "version" : "0.03" }, { "class" : "Dist::Zilla::Plugin::Authority", "name" : "@DROLSKY/Authority", "version" : "1.009" }, { "class" : "Dist::Zilla::Plugin::AutoPrereqs", "name" : "@DROLSKY/AutoPrereqs", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromBuild", "name" : "@DROLSKY/CopyFilesFromBuild", "version" : "0.170880" }, { "class" : "Dist::Zilla::Plugin::GitHub::Meta", "name" : "@DROLSKY/GitHub::Meta", "version" : "0.44" }, { "class" : "Dist::Zilla::Plugin::GitHub::Update", "config" : { "Dist::Zilla::Plugin::GitHub::Update" : { "metacpan" : 1 } }, "name" : "@DROLSKY/GitHub::Update", "version" : "0.44" }, { "class" : "Dist::Zilla::Plugin::MetaResources", "name" : "@DROLSKY/MetaResources", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::MetaProvides::Package", "config" : { "Dist::Zilla::Plugin::MetaProvides::Package" : { "finder_objects" : [ { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : "@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM", "version" : "6.010" } ], "include_underscores" : 0 }, "Dist::Zilla::Role::MetaProvider::Provider" : { "$Dist::Zilla::Role::MetaProvider::Provider::VERSION" : "2.002004", "inherit_missing" : 1, "inherit_version" : 1, "meta_noindex" : 1 }, "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000033", "version" : "0.004" } }, "name" : "@DROLSKY/MetaProvides::Package", "version" : "2.004003" }, { "class" : "Dist::Zilla::Plugin::Meta::Contributors", "name" : "@DROLSKY/Meta::Contributors", "version" : "0.003" }, { "class" : "Dist::Zilla::Plugin::MetaConfig", "name" : "@DROLSKY/MetaConfig", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::MetaJSON", "name" : "@DROLSKY/MetaJSON", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::MetaYAML", "name" : "@DROLSKY/MetaYAML", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::NextRelease", "name" : "@DROLSKY/NextRelease", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "test", "type" : "requires" } }, "name" : "@DROLSKY/Test::More with subtest", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "develop", "type" : "requires" } }, "name" : "@DROLSKY/Modules for use with tidyall", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "develop", "type" : "requires" } }, "name" : "@DROLSKY/Test::Version which fixes https://github.com/plicease/Test-Version/issues/7", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::PromptIfStale", "config" : { "Dist::Zilla::Plugin::PromptIfStale" : { "check_all_plugins" : 0, "check_all_prereqs" : 0, "modules" : [ "Dist::Zilla::PluginBundle::DROLSKY" ], "phase" : "build", "run_under_travis" : 0, "skip" : [] } }, "name" : "@DROLSKY/Dist::Zilla::PluginBundle::DROLSKY", "version" : "0.054" }, { "class" : "Dist::Zilla::Plugin::PromptIfStale", "config" : { "Dist::Zilla::Plugin::PromptIfStale" : { "check_all_plugins" : 1, "check_all_prereqs" : 1, "modules" : [], "phase" : "release", "run_under_travis" : 0, "skip" : [ "Dist::Zilla::Plugin::DROLSKY::Contributors", "Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch", "Dist::Zilla::Plugin::DROLSKY::License", "Dist::Zilla::Plugin::DROLSKY::TidyAll", "Dist::Zilla::Plugin::DROLSKY::WeaverConfig", "Pod::Weaver::PluginBundle::DROLSKY" ] } }, "name" : "@DROLSKY/PromptIfStale", "version" : "0.054" }, { "class" : "Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable", "name" : "@DROLSKY/Test::Pod::Coverage::Configurable", "version" : "0.07" }, { "class" : "Dist::Zilla::Plugin::Test::PodSpelling", "config" : { "Dist::Zilla::Plugin::Test::PodSpelling" : { "directories" : [ "bin", "lib" ], "spell_cmd" : "", "stopwords" : [ "Anno", "BCE", "CLDR", "CPAN", "DATETIME", "DROLSKY", "DROLSKY's", "DateTime", "DateTimes", "Datetime", "Datetimes", "Domini", "EEEE", "EEEEE", "Fl\u00e1vio", "Formatters", "GGGG", "GGGGG", "Glock", "Hant", "IEEE", "IEEE", "LLL", "LLLL", "LLLLL", "Liang", "Liang's", "MMM", "MMMM", "MMMMM", "Measham", "Measham's", "POSIX", "PayPal", "PayPal", "QQQ", "QQQQ", "Rata", "Rata", "Rolsky", "Rolsky's", "SU", "Soibelmann", "Storable", "TW", "TZ", "Tsai", "UTC", "VVVV", "YAPCs", "ZZZZ", "ZZZZZ", "afterwards", "bian", "ccc", "cccc", "ccccc", "conformant", "datetime", "datetime's", "datetimes", "decrement", "dian", "drolsky", "durations", "eee", "eeee", "eeeee", "fallback", "formatter", "hh", "iCal", "ji", "mutiplication", "na", "namespace", "ni", "nitty", "other's", "proleptic", "qqq", "qqqq", "sexagesimal", "subclasses", "uu", "vvvv", "wiki", "yy", "yyyy", "yyyyy", "zh", "zzzz" ], "wordlist" : "Pod::Wordlist" } }, "name" : "@DROLSKY/Test::PodSpelling", "version" : "2.007005" }, { "class" : "Dist::Zilla::Plugin::PodSyntaxTests", "name" : "@DROLSKY/PodSyntaxTests", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::RunExtraTests", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : 1 } }, "name" : "@DROLSKY/RunExtraTests", "version" : "0.029" }, { "class" : "Dist::Zilla::Plugin::MojibakeTests", "name" : "@DROLSKY/MojibakeTests", "version" : "0.8" }, { "class" : "Dist::Zilla::Plugin::Test::CleanNamespaces", "config" : { "Dist::Zilla::Plugin::Test::CleanNamespaces" : { "filename" : "xt/author/clean-namespaces.t", "skips" : [ "DateTime::Conflicts" ] } }, "name" : "@DROLSKY/Test::CleanNamespaces", "version" : "0.006" }, { "class" : "Dist::Zilla::Plugin::Test::CPAN::Changes", "config" : { "Dist::Zilla::Plugin::Test::CPAN::Changes" : { "changelog" : "Changes" } }, "name" : "@DROLSKY/Test::CPAN::Changes", "version" : "0.012" }, { "class" : "Dist::Zilla::Plugin::Test::CPAN::Meta::JSON", "name" : "@DROLSKY/Test::CPAN::Meta::JSON", "version" : "0.004" }, { "class" : "Dist::Zilla::Plugin::Test::EOL", "config" : { "Dist::Zilla::Plugin::Test::EOL" : { "filename" : "xt/author/eol.t", "finder" : [ ":ExecFiles", ":InstallModules", ":TestFiles" ], "trailing_whitespace" : 1 } }, "name" : "@DROLSKY/Test::EOL", "version" : "0.19" }, { "class" : "Dist::Zilla::Plugin::Test::NoTabs", "config" : { "Dist::Zilla::Plugin::Test::NoTabs" : { "filename" : "xt/author/no-tabs.t", "finder" : [ ":InstallModules", ":ExecFiles", ":TestFiles" ] } }, "name" : "@DROLSKY/Test::NoTabs", "version" : "0.15" }, { "class" : "Dist::Zilla::Plugin::Test::Portability", "config" : { "Dist::Zilla::Plugin::Test::Portability" : { "options" : "" } }, "name" : "@DROLSKY/Test::Portability", "version" : "2.001000" }, { "class" : "Dist::Zilla::Plugin::Test::TidyAll", "name" : "@DROLSKY/Test::TidyAll", "version" : "0.04" }, { "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs", "name" : "@DROLSKY/Test::ReportPrereqs", "version" : "0.027" }, { "class" : "Dist::Zilla::Plugin::Test::Version", "name" : "@DROLSKY/Test::Version", "version" : "1.09" }, { "class" : "Dist::Zilla::Plugin::DROLSKY::Contributors", "name" : "@DROLSKY/DROLSKY::Contributors", "version" : "0.89" }, { "class" : "Dist::Zilla::Plugin::Git::Contributors", "config" : { "Dist::Zilla::Plugin::Git::Contributors" : { "git_version" : "2.16.1", "include_authors" : 0, "include_releaser" : 1, "order_by" : "name", "paths" : [] } }, "name" : "@DROLSKY/Git::Contributors", "version" : "0.032" }, { "class" : "Dist::Zilla::Plugin::SurgicalPodWeaver", "config" : { "Dist::Zilla::Plugin::PodWeaver" : { "config_plugins" : [ "@DROLSKY" ], "finder" : [ ":InstallModules", ":ExecFiles" ], "plugins" : [ { "class" : "Pod::Weaver::Plugin::EnsurePod5", "name" : "@CorePrep/EnsurePod5", "version" : "4.015" }, { "class" : "Pod::Weaver::Plugin::H1Nester", "name" : "@CorePrep/H1Nester", "version" : "4.015" }, { "class" : "Pod::Weaver::Plugin::SingleEncoding", "name" : "@DROLSKY/SingleEncoding", "version" : "4.015" }, { "class" : "Pod::Weaver::Plugin::Transformer", "name" : "@DROLSKY/List", "version" : "4.015" }, { "class" : "Pod::Weaver::Plugin::Transformer", "name" : "@DROLSKY/Verbatim", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@DROLSKY/header", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Name", "name" : "@DROLSKY/Name", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Version", "name" : "@DROLSKY/Version", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@DROLSKY/prelude", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "SYNOPSIS", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "DESCRIPTION", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "OVERVIEW", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "ATTRIBUTES", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "METHODS", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "FUNCTIONS", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "TYPES", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Leftovers", "name" : "@DROLSKY/Leftovers", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@DROLSKY/postlude", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::GenerateSection", "name" : "@DROLSKY/generate SUPPORT", "version" : "1.06" }, { "class" : "Pod::Weaver::Section::AllowOverride", "name" : "@DROLSKY/allow override SUPPORT", "version" : "0.05" }, { "class" : "Pod::Weaver::Section::GenerateSection", "name" : "@DROLSKY/generate SOURCE", "version" : "1.06" }, { "class" : "Pod::Weaver::Section::GenerateSection", "name" : "@DROLSKY/generate DONATIONS", "version" : "1.06" }, { "class" : "Pod::Weaver::Section::Authors", "name" : "@DROLSKY/Authors", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Contributors", "name" : "@DROLSKY/Contributors", "version" : "0.009" }, { "class" : "Pod::Weaver::Section::Legal", "name" : "@DROLSKY/Legal", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@DROLSKY/footer", "version" : "4.015" } ] } }, "name" : "@DROLSKY/SurgicalPodWeaver", "version" : "0.0023" }, { "class" : "Dist::Zilla::Plugin::DROLSKY::WeaverConfig", "name" : "@DROLSKY/DROLSKY::WeaverConfig", "version" : "0.89" }, { "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod", "config" : { "Dist::Zilla::Role::FileWatcher" : { "version" : "0.006" } }, "name" : "@DROLSKY/README.md in build", "version" : "0.163250" }, { "class" : "Dist::Zilla::Plugin::GenerateFile::FromShareDir", "config" : { "Dist::Zilla::Plugin::GenerateFile::FromShareDir" : { "destination_filename" : "CONTRIBUTING.md", "dist" : "Dist-Zilla-PluginBundle-DROLSKY", "encoding" : "UTF-8", "has_xs" : 1, "location" : "build", "source_filename" : "CONTRIBUTING.md" }, "Dist::Zilla::Role::RepoFileInjector" : { "allow_overwrite" : 1, "repo_root" : ".", "version" : "0.007" } }, "name" : "@DROLSKY/Generate CONTRIBUTING.md", "version" : "0.013" }, { "class" : "Dist::Zilla::Plugin::InstallGuide", "name" : "@DROLSKY/InstallGuide", "version" : "1.200007" }, { "class" : "Dist::Zilla::Plugin::CPANFile", "name" : "@DROLSKY/CPANFile", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::PPPort", "name" : "@DROLSKY/PPPort", "version" : "0.008" }, { "class" : "Dist::Zilla::Plugin::DROLSKY::License", "name" : "@DROLSKY/DROLSKY::License", "version" : "0.89" }, { "class" : "Dist::Zilla::Plugin::CheckStrictVersion", "name" : "@DROLSKY/CheckStrictVersion", "version" : "0.001" }, { "class" : "Dist::Zilla::Plugin::CheckSelfDependency", "config" : { "Dist::Zilla::Plugin::CheckSelfDependency" : { "finder" : [ ":InstallModules" ] }, "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000033", "version" : "0.004" } }, "name" : "@DROLSKY/CheckSelfDependency", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::CheckPrereqsIndexed", "name" : "@DROLSKY/CheckPrereqsIndexed", "version" : "0.020" }, { "class" : "Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch", "config" : { "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.16.1", "repo_root" : "." } }, "name" : "@DROLSKY/DROLSKY::Git::CheckFor::CorrectBranch", "version" : "0.89" }, { "class" : "Dist::Zilla::Plugin::EnsureChangesHasContent", "name" : "@DROLSKY/EnsureChangesHasContent", "version" : "0.02" }, { "class" : "Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts", "config" : { "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.16.1", "repo_root" : "." } }, "name" : "@DROLSKY/Git::CheckFor::MergeConflicts", "version" : "0.014" }, { "class" : "Dist::Zilla::Plugin::DROLSKY::TidyAll", "name" : "@DROLSKY/DROLSKY::TidyAll", "version" : "0.89" }, { "class" : "Dist::Zilla::Plugin::Git::Check", "config" : { "Dist::Zilla::Plugin::Git::Check" : { "untracked_files" : "die" }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "CONTRIBUTING.md", "Changes", "LICENSE", "Makefile.PL", "README.md", "cpanfile", "leap_seconds.h", "ppport.h", "tidyall.ini" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.16.1", "repo_root" : "." } }, "name" : "@DROLSKY/Git::Check", "version" : "2.043" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "v%v%n%n%c" }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "CONTRIBUTING.md", "Changes", "LICENSE", "Makefile.PL", "README.md", "cpanfile", "leap_seconds.h", "ppport.h", "tidyall.ini" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.16.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@DROLSKY/Commit generated files", "version" : "2.043" }, { "class" : "Dist::Zilla::Plugin::Git::Tag", "config" : { "Dist::Zilla::Plugin::Git::Tag" : { "branch" : null, "changelog" : "Changes", "signed" : 0, "tag" : "v1.46", "tag_format" : "v%v", "tag_message" : "v%v" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.16.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@DROLSKY/Git::Tag", "version" : "2.043" }, { "class" : "Dist::Zilla::Plugin::Git::Push", "config" : { "Dist::Zilla::Plugin::Git::Push" : { "push_to" : [ "origin" ], "remotes_must_exist" : 1 }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.16.1", "repo_root" : "." } }, "name" : "@DROLSKY/Git::Push", "version" : "2.043" }, { "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease", "config" : { "Dist::Zilla::Plugin::BumpVersionAfterRelease" : { "finders" : [ ":ExecFiles", ":InstallModules" ], "global" : 0, "munge_makefile_pl" : 1 } }, "name" : "@DROLSKY/BumpVersionAfterRelease", "version" : "0.017" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "Bump version after release" }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Changes", "dist.ini" ], "allow_dirty_match" : [ "(?^:.+)" ], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.16.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@DROLSKY/Commit version bump", "version" : "2.043" }, { "class" : "Dist::Zilla::Plugin::Git::Push", "config" : { "Dist::Zilla::Plugin::Git::Push" : { "push_to" : [ "origin" ], "remotes_must_exist" : 1 }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.16.1", "repo_root" : "." } }, "name" : "@DROLSKY/Push version bump", "version" : "2.043" }, { "class" : "Dist::Zilla::Plugin::lib", "config" : { "Dist::Zilla::Plugin::lib" : { "lib" : [ "inc" ] } }, "name" : "lib", "version" : "0.001002" }, { "class" : "LeapSecondsHeader", "name" : "=LeapSecondsHeader", "version" : null }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromBuild", "name" : "CopyFilesFromBuild", "version" : "0.170880" }, { "class" : "Dist::Zilla::Plugin::MetaResources", "name" : "MetaResources", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "develop", "type" : "requires" } }, "name" : "DevelopRequires", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::PurePerlTests", "name" : "PurePerlTests", "version" : "0.06" }, { "class" : "Dist::Zilla::Plugin::Conflicts", "name" : "Conflicts", "version" : "0.19" }, { "class" : "Dist::Zilla::Plugin::Test::CheckBreaks", "config" : { "Dist::Zilla::Plugin::Test::CheckBreaks" : { "conflicts_module" : [ "DateTime::Conflicts" ], "no_forced_deps" : 0 }, "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000033", "version" : "0.004" } }, "name" : "Test::CheckBreaks", "version" : "0.019" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":InstallModules", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":IncModules", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":TestFiles", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExtraTestFiles", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExecFiles", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":PerlExecFiles", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ShareFiles", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":MainModule", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":AllFiles", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":NoFiles", "version" : "6.010" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : "@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM", "version" : "6.010" } ], "zilla" : { "class" : "Dist::Zilla::Dist::Builder", "config" : { "is_trial" : 0 }, "version" : "6.010" } }, "x_authority" : "cpan:DROLSKY", "x_breaks" : { "DateTime::Format::Mail" : "<= 0.402" }, "x_contributors" : [ "Ben Bennett ", "Christian Hansen ", "Daisuke Maki ", "Dan Book ", "Dan Stewart ", "David E. Wheeler ", "David Precious ", "Doug Bell ", "Fl\u00e1vio Soibelmann Glock ", "Gianni Ceccarelli ", "Gregory Oschwald ", "Hauke D ", "Iain Truskett ", "Jason McIntosh ", "Joshua Hoblitt ", "Karen Etheridge ", "Michael Conrad ", "Michael R. Davis ", "M Somerville ", "Nick Tonkin <1nickt@users.noreply.github.com>", "Olaf Alders ", "Ovid ", "Philippe Bruhat (BooK) ", "Ricardo Signes ", "Richard Bowen ", "Ron Hill ", "Sam Kington ", "viviparous " ], "x_serialization_backend" : "Cpanel::JSON::XS version 3.0239" } DateTime-1.46/lib/0000775000175000017500000000000013240151623013545 5ustar autarchautarchDateTime-1.46/lib/DateTime/0000775000175000017500000000000013240151623015241 5ustar autarchautarchDateTime-1.46/lib/DateTime/Duration.pm0000644000175000017500000004436013240151623017371 0ustar autarchautarchpackage DateTime::Duration; use strict; use warnings; use namespace::autoclean; our $VERSION = '1.46'; use Carp (); use DateTime; use DateTime::Helpers; use DateTime::Types; use Params::ValidationCompiler 0.26 qw( validation_for ); use Scalar::Util qw( blessed ); use overload ( fallback => 1, '+' => '_add_overload', '-' => '_subtract_overload', '*' => '_multiply_overload', '<=>' => '_compare_overload', 'cmp' => '_compare_overload', ); sub MAX_NANOSECONDS () {1_000_000_000} # 1E9 = almost 32 bits my @all_units = qw( months days minutes seconds nanoseconds ); { my %units = map { $_ => { # XXX - what we really want is to accept an integer, Inf, -Inf, # and NaN, but I can't figure out how to accept NaN since it never # compares to anything. type => t('Defined'), default => 0, } } qw( years months weeks days hours minutes seconds nanoseconds ); my $check = validation_for( name => '_check_new_params', name_is_optional => 1, params => { %units, end_of_month => { type => t('EndOfMonthMode'), optional => 1, }, }, ); sub new { my $class = shift; my %p = $check->(@_); my $self = bless {}, $class; $self->{months} = ( $p{years} * 12 ) + $p{months}; $self->{days} = ( $p{weeks} * 7 ) + $p{days}; $self->{minutes} = ( $p{hours} * 60 ) + $p{minutes}; $self->{seconds} = $p{seconds}; if ( $p{nanoseconds} ) { $self->{nanoseconds} = $p{nanoseconds}; $self->_normalize_nanoseconds; } else { # shortcut - if they don't need nanoseconds $self->{nanoseconds} = 0; } $self->{end_of_month} = ( defined $p{end_of_month} ? $p{end_of_month} : $self->{months} < 0 ? 'preserve' : 'wrap' ); return $self; } } # make the signs of seconds, nanos the same; 0 < abs(nanos) < MAX_NANOS # NB this requires nanoseconds != 0 (callers check this already) sub _normalize_nanoseconds { my $self = shift; return if ( $self->{nanoseconds} == DateTime::INFINITY() || $self->{nanoseconds} == DateTime::NEG_INFINITY() || $self->{nanoseconds} eq DateTime::NAN() ); my $seconds = $self->{seconds} + $self->{nanoseconds} / MAX_NANOSECONDS; $self->{seconds} = int($seconds); $self->{nanoseconds} = $self->{nanoseconds} % MAX_NANOSECONDS; $self->{nanoseconds} -= MAX_NANOSECONDS if $seconds < 0; } sub clone { bless { %{ $_[0] } }, ref $_[0] } sub years { abs( $_[0]->in_units('years') ) } sub months { abs( $_[0]->in_units( 'months', 'years' ) ) } sub weeks { abs( $_[0]->in_units('weeks') ) } sub days { abs( $_[0]->in_units( 'days', 'weeks' ) ) } sub hours { abs( $_[0]->in_units('hours') ) } sub minutes { abs( $_[0]->in_units( 'minutes', 'hours' ) ) } sub seconds { abs( $_[0]->in_units('seconds') ) } sub nanoseconds { abs( $_[0]->in_units( 'nanoseconds', 'seconds' ) ) } sub is_positive { $_[0]->_has_positive && !$_[0]->_has_negative } sub is_negative { !$_[0]->_has_positive && $_[0]->_has_negative } sub _has_positive { ( grep { $_ > 0 } @{ $_[0] }{@all_units} ) ? 1 : 0; } sub _has_negative { ( grep { $_ < 0 } @{ $_[0] }{@all_units} ) ? 1 : 0; } sub is_zero { return 0 if grep { $_ != 0 } @{ $_[0] }{@all_units}; return 1; } sub delta_months { $_[0]->{months} } sub delta_days { $_[0]->{days} } sub delta_minutes { $_[0]->{minutes} } sub delta_seconds { $_[0]->{seconds} } sub delta_nanoseconds { $_[0]->{nanoseconds} } sub deltas { map { $_ => $_[0]->{$_} } @all_units; } sub in_units { my $self = shift; my @units = @_; my %units = map { $_ => 1 } @units; my %ret; my ( $months, $days, $minutes, $seconds ) = @{$self}{qw( months days minutes seconds )}; if ( $units{years} ) { $ret{years} = int( $months / 12 ); $months -= $ret{years} * 12; } if ( $units{months} ) { $ret{months} = $months; } if ( $units{weeks} ) { $ret{weeks} = int( $days / 7 ); $days -= $ret{weeks} * 7; } if ( $units{days} ) { $ret{days} = $days; } if ( $units{hours} ) { $ret{hours} = int( $minutes / 60 ); $minutes -= $ret{hours} * 60; } if ( $units{minutes} ) { $ret{minutes} = $minutes; } if ( $units{seconds} ) { $ret{seconds} = $seconds; $seconds = 0; } if ( $units{nanoseconds} ) { $ret{nanoseconds} = $seconds * MAX_NANOSECONDS + $self->{nanoseconds}; } wantarray ? @ret{@units} : $ret{ $units[0] }; } sub is_wrap_mode { $_[0]->{end_of_month} eq 'wrap' ? 1 : 0 } sub is_limit_mode { $_[0]->{end_of_month} eq 'limit' ? 1 : 0 } sub is_preserve_mode { $_[0]->{end_of_month} eq 'preserve' ? 1 : 0 } sub end_of_month_mode { $_[0]->{end_of_month} } sub calendar_duration { my $self = shift; return ( ref $self ) ->new( map { $_ => $self->{$_} } qw( months days end_of_month ) ); } sub clock_duration { my $self = shift; return ( ref $self ) ->new( map { $_ => $self->{$_} } qw( minutes seconds nanoseconds end_of_month ) ); } sub inverse { my $self = shift; my %p = @_; my %new; foreach my $u (@all_units) { $new{$u} = $self->{$u}; # avoid -0 bug $new{$u} *= -1 if $new{$u}; } $new{end_of_month} = $p{end_of_month} if exists $p{end_of_month}; return ( ref $self )->new(%new); } sub add_duration { my ( $self, $dur ) = @_; foreach my $u (@all_units) { $self->{$u} += $dur->{$u}; } $self->_normalize_nanoseconds if $self->{nanoseconds}; return $self; } sub add { my $self = shift; return $self->add_duration( $self->_duration_object_from_args(@_) ); } sub subtract { my $self = shift; return $self->subtract_duration( $self->_duration_object_from_args(@_) ); } # Syntactic sugar for add and subtract: use a duration object if it's # supplied, otherwise build a new one from the arguments. sub _duration_object_from_args { my $self = shift; return $_[0] if @_ == 1 && blessed( $_[0] ) && $_[0]->isa(__PACKAGE__); return __PACKAGE__->new(@_); } sub subtract_duration { return $_[0]->add_duration( $_[1]->inverse ) } sub multiply { my $self = shift; my $multiplier = shift; foreach my $u (@all_units) { $self->{$u} *= $multiplier; } $self->_normalize_nanoseconds if $self->{nanoseconds}; return $self; } sub compare { my ( undef, $dur1, $dur2, $dt ) = @_; $dt ||= DateTime->now; return DateTime->compare( $dt->clone->add_duration($dur1), $dt->clone->add_duration($dur2) ); } sub _add_overload { my ( $d1, $d2, $rev ) = @_; ( $d1, $d2 ) = ( $d2, $d1 ) if $rev; if ( DateTime::Helpers::isa( $d2, 'DateTime' ) ) { $d2->add_duration($d1); return; } # will also work if $d1 is a DateTime.pm object return $d1->clone->add_duration($d2); } sub _subtract_overload { my ( $d1, $d2, $rev ) = @_; ( $d1, $d2 ) = ( $d2, $d1 ) if $rev; Carp::croak( 'Cannot subtract a DateTime object from a DateTime::Duration object') if DateTime::Helpers::isa( $d2, 'DateTime' ); return $d1->clone->subtract_duration($d2); } sub _multiply_overload { my $self = shift; my $new = $self->clone; return $new->multiply(@_); } sub _compare_overload { Carp::croak( 'DateTime::Duration does not overload comparison.' . ' See the documentation on the compare() method for details.' ); } 1; # ABSTRACT: Duration objects for date math __END__ =pod =encoding UTF-8 =head1 NAME DateTime::Duration - Duration objects for date math =head1 VERSION version 1.46 =head1 SYNOPSIS use DateTime::Duration; $dur = DateTime::Duration->new( years => 3, months => 5, weeks => 1, days => 1, hours => 6, minutes => 15, seconds => 45, nanoseconds => 12000 ); my ( $days, $hours, $seconds ) = $dur->in_units('days', 'hours', 'seconds'); # Human-readable accessors, always positive, but consider using # DateTime::Format::Duration instead $dur->years; $dur->months; $dur->weeks; $dur->days; $dur->hours; $dur->minutes; $dur->seconds; $dur->nanoseconds; $dur->is_wrap_mode $dur->is_limit_mode $dur->is_preserve_mode print $dur->end_of_month_mode; # Multiply all values by -1 my $opposite = $dur->inverse; my $bigger = $dur1 + $dur2; my $smaller = $dur1 - $dur2; # the result could be negative my $bigger = $dur1 * 3; my $base_dt = DateTime->new( year => 2000 ); my @sorted = sort { DateTime::Duration->compare( $a, $b, $base_dt ) } @durations; if ( $dur->is_positive ) { ... } if ( $dur->is_zero ) { ... } if ( $dur->is_negative ) { ... } =head1 DESCRIPTION This is a simple class for representing duration objects. These objects are used whenever you do date math with DateTime.pm. See the L section of the DateTime.pm documentation for more details. The short course: One cannot in general convert between seconds, minutes, days, and months, so this class will never do so. Instead, create the duration with the desired units to begin with, for example by calling the appropriate subtraction/delta method on a C object. =head1 METHODS Like C itself, C returns the object from mutator methods in order to make method chaining possible. C has the following methods: =head2 DateTime::Duration->new( ... ) This method takes the parameters "years", "months", "weeks", "days", "hours", "minutes", "seconds", "nanoseconds", and "end_of_month". All of these except "end_of_month" are numbers. If any of the numbers are negative, the entire duration is negative. All of the numbers B. Internally, years as just treated as 12 months. Similarly, weeks are treated as 7 days, and hours are converted to minutes. Seconds and nanoseconds are both treated separately. The "end_of_month" parameter must be either "wrap", "limit", or "preserve". This parameter specifies how date math that crosses the end of a month is handled. In "wrap" mode, adding months or years that result in days beyond the end of the new month will roll over into the following month. For instance, adding one year to Feb 29 will result in Mar 1. If you specify "end_of_month" mode as "limit", the end of the month is never crossed. Thus, adding one year to Feb 29, 2000 will result in Feb 28, 2001. If you were to then add three more years this will result in Feb 28, 2004. If you specify "end_of_month" mode as "preserve", the same calculation is done as for "limit" except that if the original date is at the end of the month the new date will also be. For instance, adding one month to Feb 29, 2000 will result in Mar 31, 2000. For positive durations, the "end_of_month" parameter defaults to wrap. For negative durations, the default is "preserve". This should match how most people "intuitively" expect datetime math to work. =head2 $dur->clone() Returns a new object with the same properties as the object on which this method was called. =head2 $dur->in_units( ... ) Returns the length of the duration in the units (any of those that can be passed to C) given as arguments. All lengths are integral, but may be negative. Smaller units are computed from what remains after taking away the larger units given, so for example: my $dur = DateTime::Duration->new( years => 1, months => 15 ); $dur->in_units( 'years' ); # 2 $dur->in_units( 'months' ); # 27 $dur->in_units( 'years', 'months' ); # (2, 3) $dur->in_units( 'weeks', 'days' ); # (0, 0) ! The last example demonstrates that there will not be any conversion between units which don't have a fixed conversion rate. The only conversions possible are: =over 8 =item * years <=> months =item * weeks <=> days =item * hours <=> minutes =item * seconds <=> nanoseconds =back For the explanation of why this is the case, please see the L section of the DateTime.pm documentation Note that the numbers returned by this method may not match the values given to the constructor. In list context, in_units returns the lengths in the order of the units given. In scalar context, it returns the length in the first unit (but still computes in terms of all given units). If you need more flexibility in presenting information about durations, please take a look a C. =head2 $dur->is_positive(), $dur->is_zero(), $dur->is_negative() Indicates whether or not the duration is positive, zero, or negative. If the duration contains both positive and negative units, then it will return false for B of these methods. =head2 $dur->is_wrap_mode(), $dur->is_limit_mode(), $dur->is_preserve_mode() Indicates what mode is used for end of month wrapping. =head2 $dur->end_of_month_mode() Returns one of "wrap", "limit", or "preserve". =head2 $dur->calendar_duration() Returns a new object with the same I delta (months and days only) and end of month mode as the current object. =head2 $dur->clock_duration() Returns a new object with the same I deltas (minutes, seconds, and nanoseconds) and end of month mode as the current object. =head2 $dur->inverse( ... ) Returns a new object with the same deltas as the current object, but multiple by -1. The end of month mode for the new object will be the default end of month mode, which depends on whether the new duration is positive or negative. You can set the end of month mode in the inverted duration explicitly by passing "end_of_month => ..." to the C method. =head2 $dur->add_duration( $duration_object ), $dur->subtract_duration( $duration_object ) Adds or subtracts one duration from another. =head2 $dur->add( ... ), $dur->subtract( ... ) These accept either constructor parameters for a new C object or an already-constructed duration object. =head2 $dur->multiply( $number ) Multiplies each unit in the by the specified number. =head2 DateTime::Duration->compare( $duration1, $duration2, $base_datetime ) This is a class method that can be used to compare or sort durations. Comparison is done by adding each duration to the specified C object and comparing the resulting datetimes. This is necessary because without a base, many durations are not comparable. For example, 1 month may or may not be longer than 29 days, depending on what datetime it is added to. If no base datetime is given, then the result of C<< DateTime->now >> is used instead. Using this default will give non-repeatable results if used to compare two duration objects containing different units. It will also give non-repeatable results if the durations contain multiple types of units, such as months and days. However, if you know that both objects only consist of one type of unit (months I days I hours, etc.), and each duration contains the same type of unit, then the results of the comparison will be repeatable. =head2 $dur->delta_months(), $dur->delta_days(), $dur->delta_minutes(), $dur->delta_seconds(), $dur->delta_nanoseconds() These methods provide the information C needs for doing date math. The numbers returned may be positive or negative. This is mostly useful for doing date math in L. =head2 $dur->deltas() Returns a hash with the keys "months", "days", "minutes", "seconds", and "nanoseconds", containing all the delta information for the object. This is mostly useful for doing date math in L. =head2 $dur->years(), $dur->months(), $dur->weeks(), $dur->days(), $dur->hours(), $dur->minutes(), $dur->seconds(), $dur->nanoseconds() These methods return numbers indicating how many of the given unit the object represents, after having done a conversion to any larger units. For example, days are first converted to weeks, and then the remainder is returned. These numbers are always positive. Here's what each method returns: $dur->years() == abs( $dur->in_units('years') ) $dur->months() == abs( ( $dur->in_units( 'months', 'years' ) )[0] ) $dur->weeks() == abs( $dur->in_units( 'weeks' ) ) $dur->days() == abs( ( $dur->in_units( 'days', 'weeks' ) )[0] ) $dur->hours() == abs( $dur->in_units( 'hours' ) ) $dur->minutes == abs( ( $dur->in_units( 'minutes', 'hours' ) )[0] ) $dur->seconds == abs( $dur->in_units( 'seconds' ) ) $dur->nanoseconds() == abs( ( $dur->in_units( 'nanoseconds', 'seconds' ) )[0] ) If this seems confusing, remember that you can always use the C method to specify exactly what you want. Better yet, if you are trying to generate output suitable for humans, use the C module. =head2 Overloading This class overloads addition, subtraction, and mutiplication. Comparison is B overloaded. If you attempt to compare durations using C<< <=> >> or C, then an exception will be thrown! Use the C class method instead. =head1 SEE ALSO datetime@perl.org mailing list http://datetime.perl.org/ =head1 SUPPORT Support for this module is provided via the datetime@perl.org email list. See http://lists.perl.org/ for more details. Bugs may be submitted at L. There is a mailing list available for users of this distribution, L. I am also usually active on IRC as 'autarch' on C. =head1 SOURCE The source code repository for DateTime can be found at L. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2003 - 2018 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) The full text of the license can be found in the F file included with this distribution. =cut DateTime-1.46/lib/DateTime/PP.pm0000644000175000017500000001265413240151623016124 0ustar autarchautarchpackage DateTime::PP; use strict; use warnings; our $VERSION = '1.46'; ## no critic (Variables::ProhibitPackageVars) $DateTime::IsPurePerl = 1; ## use critic my @MonthLengths = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); my @LeapYearMonthLengths = @MonthLengths; $LeapYearMonthLengths[1]++; my @EndOfLastMonthDayOfYear; { my $x = 0; foreach my $length (@MonthLengths) { push @EndOfLastMonthDayOfYear, $x; $x += $length; } } my @EndOfLastMonthDayOfLeapYear = @EndOfLastMonthDayOfYear; $EndOfLastMonthDayOfLeapYear[$_]++ for 2 .. 11; ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines) sub _time_as_seconds { shift; my ( $hour, $min, $sec ) = @_; $hour ||= 0; $min ||= 0; $sec ||= 0; my $secs = $hour * 3600 + $min * 60 + $sec; return $secs; } sub _rd2ymd { my $class = shift; use integer; my $d = shift; my $rd = $d; my $yadj = 0; my ( $c, $y, $m ); # add 306 days to make relative to Mar 1, 0 if ( ( $d += 306 ) <= 0 ) { # avoid ambiguity in C division of negatives $yadj = -( -$d / 146097 + 1 ); $d -= $yadj * 146097; } $c = ( $d * 4 - 1 ) / 146097; # calc # of centuries $d is after 29 Feb of yr 0 $d -= $c * 146097 / 4; # (4 centuries = 146097 days) $y = ( $d * 4 - 1 ) / 1461; # calc number of years into the century, $d -= $y * 1461 / 4; # again March-based (4 yrs =~ 146[01] days) $m = ( $d * 12 + 1093 ) / 367; # get the month (3..14 represent March through $d -= ( $m * 367 - 1094 ) / 12; # February of following year) $y += $c * 100 + $yadj * 400; # get the real year, which is off by # one if month is January or February if ( $m > 12 ) { ++$y; $m -= 12; } if ( $_[0] ) { my $dow; if ( $rd < -6 ) { $dow = ( $rd + 6 ) % 7; $dow += $dow ? 8 : 1; } else { $dow = ( ( $rd + 6 ) % 7 ) + 1; } my $doy = $class->_end_of_last_month_day_of_year( $y, $m ); $doy += $d; my $quarter; { no integer; $quarter = int( ( 1 / 3.1 ) * $m ) + 1; } my $qm = ( 3 * $quarter ) - 2; my $doq = ( $doy - $class->_end_of_last_month_day_of_year( $y, $qm ) ); return ( $y, $m, $d, $dow, $doy, $quarter, $doq ); } return ( $y, $m, $d ); } sub _ymd2rd { shift; # ignore class use integer; my ( $y, $m, $d ) = @_; my $adj; # make month in range 3..14 (treat Jan & Feb as months 13..14 of # prev year) if ( $m <= 2 ) { $y -= ( $adj = ( 14 - $m ) / 12 ); $m += 12 * $adj; } elsif ( $m > 14 ) { $y += ( $adj = ( $m - 3 ) / 12 ); $m -= 12 * $adj; } # make year positive (oh, for a use integer 'sane_div'!) if ( $y < 0 ) { $d -= 146097 * ( $adj = ( 399 - $y ) / 400 ); $y += 400 * $adj; } # add: day of month, days of previous 0-11 month period that began # w/March, days of previous 0-399 year period that began w/March # of a 400-multiple year), days of any 400-year periods before # that, and finally subtract 306 days to adjust from Mar 1, year # 0-relative to Jan 1, year 1-relative (whew) $d += ( $m * 367 - 1094 ) / 12 + $y % 100 * 1461 / 4 + ( $y / 100 * 36524 + $y / 400 ) - 306; } sub _seconds_as_components { shift; my $secs = shift; my $utc_secs = shift; my $modifier = shift || 0; use integer; $secs -= $modifier; my $hour = $secs / 3600; $secs -= $hour * 3600; my $minute = $secs / 60; my $second = $secs - ( $minute * 60 ); if ( $utc_secs && $utc_secs >= 86400 ) { # there is no such thing as +3 or more leap seconds! die "Invalid UTC RD seconds value: $utc_secs" if $utc_secs > 86401; $second += $utc_secs - 86400 + 60; $minute = 59; $hour--; $hour = 23 if $hour < 0; } return ( $hour, $minute, $second ); } sub _end_of_last_month_day_of_year { my $class = shift; my ( $y, $m ) = @_; $m--; return ( $class->_is_leap_year($y) ? $EndOfLastMonthDayOfLeapYear[$m] : $EndOfLastMonthDayOfYear[$m] ); } sub _is_leap_year { shift; my $year = shift; # According to Bjorn Tackmann, this line prevents an infinite loop # when running the tests under Qemu. I cannot reproduce this on # Ubuntu or with Strawberry Perl on Win2K. return 0 if $year == DateTime::INFINITY() || $year == DateTime::NEG_INFINITY(); return 0 if $year % 4; return 1 if $year % 100; return 0 if $year % 400; return 1; } sub _day_length { DateTime::LeapSecond::day_length( $_[1] ) } sub _accumulated_leap_seconds { DateTime::LeapSecond::leap_seconds( $_[1] ) } my @subs = qw( _time_as_seconds _rd2ymd _ymd2rd _seconds_as_components _end_of_last_month_day_of_year _is_leap_year _day_length _accumulated_leap_seconds ); for my $sub (@subs) { ## no critic (TestingAndDebugging::ProhibitNoStrict) no strict 'refs'; *{ 'DateTime::' . $sub } = __PACKAGE__->can($sub); } # This is down here so that _ymd2rd is available when it loads, # because it will load DateTime::LeapSecond, which needs # DateTime->_ymd2rd to be available when it is loading require DateTime::PPExtra; 1; DateTime-1.46/lib/DateTime/LeapSecond.pm0000644000175000017500000001134013240151623017611 0ustar autarchautarchpackage DateTime::LeapSecond; use strict; use warnings; use namespace::autoclean; our $VERSION = '1.46'; our ( @RD, @LEAP_SECONDS, %RD_LENGTH ); use DateTime; # Generates a Perl binary decision tree sub _make_utx { my ( $beg, $end, $tab, $op ) = @_; my $step = int( ( $end - $beg ) / 2 ); my $tmp; if ( $step <= 0 ) { $tmp = "${tab}return $LEAP_SECONDS[$beg + 1];\n"; return $tmp; } $tmp = "${tab}if (\$val < " . $RD[ $beg + $step ] . ") {\n"; $tmp .= _make_utx( $beg, $beg + $step, $tab . q{ }, $op ); $tmp .= "${tab}}\n"; $tmp .= "${tab}else {\n"; $tmp .= _make_utx( $beg + $step, $end, $tab . q{ }, $op ); $tmp .= "${tab}}\n"; return $tmp; } # Process BEGIN data and write binary tree decision table sub _init { my $value = -1; while (@_) { my ( $year, $mon, $mday, $leap_seconds ) = ( shift, shift, shift, shift ); # print "$year,$mon,$mday\n"; ## no critic (Subroutines::ProtectPrivateSubs) my $utc_epoch = DateTime->_ymd2rd( $year, ( $mon =~ /Jan/i ? 1 : 7 ), $mday ); $value++; push @LEAP_SECONDS, $value; push @RD, $utc_epoch; $RD_LENGTH{ $utc_epoch - 1 } = $leap_seconds; # warn "$year,$mon,$mday = $utc_epoch +$value"; } push @LEAP_SECONDS, ++$value; my $tmp; # write binary tree decision table $tmp = "sub leap_seconds {\n"; $tmp .= " my \$val = shift;\n"; $tmp .= _make_utx( -1, 1 + $#RD, q{ }, '+' ); $tmp .= "}; 1\n"; # NOTE: uncomment the line below to see the code: #warn $tmp; ## no critic (BuiltinFunctions::ProhibitStringyEval) eval $tmp or die $@; } sub extra_seconds { exists $RD_LENGTH{ $_[0] } ? $RD_LENGTH{ $_[0] } : 0; } sub day_length { exists $RD_LENGTH{ $_[0] } ? 86400 + $RD_LENGTH{ $_[0] } : 86400; } sub _initialize { # There are no leap seconds before 1972, because that's the # year this system was implemented. # # year month day number-of-leapseconds # _init( qw( 1972 Jul. 1 +1 1973 Jan. 1 +1 1974 Jan. 1 +1 1975 Jan. 1 +1 1976 Jan. 1 +1 1977 Jan. 1 +1 1978 Jan. 1 +1 1979 Jan. 1 +1 1980 Jan. 1 +1 1981 Jul. 1 +1 1982 Jul. 1 +1 1983 Jul. 1 +1 1985 Jul. 1 +1 1988 Jan. 1 +1 1990 Jan. 1 +1 1991 Jan. 1 +1 1992 Jul. 1 +1 1993 Jul. 1 +1 1994 Jul. 1 +1 1996 Jan. 1 +1 1997 Jul. 1 +1 1999 Jan. 1 +1 2006 Jan. 1 +1 2009 Jan. 1 +1 2012 Jul. 1 +1 2015 Jul. 1 +1 2017 Jan. 1 +1 ) ); } __PACKAGE__->_initialize(); 1; # ABSTRACT: leap seconds table and utilities __END__ =pod =encoding UTF-8 =head1 NAME DateTime::LeapSecond - leap seconds table and utilities =head1 VERSION version 1.46 =head1 SYNOPSIS use DateTime; use DateTime::LeapSecond; print "Leap seconds between years 1990 and 2000 are "; print DateTime::Leapsecond::leap_seconds( $utc_rd_2000 ) - DateTime::Leapsecond::leap_seconds( $utc_rd_1990 ); =head1 DESCRIPTION This module is used to calculate leap seconds for a given Rata Die day. It is used when DateTime.pm cannot compile the XS version of this code. This library is known to be accurate for dates until Jun 2017. There are no leap seconds before 1972, because that's the year this system was implemented. =over 4 =item * leap_seconds( $rd ) Returns the number of accumulated leap seconds for a given day. =item * extra_seconds( $rd ) Returns the number of leap seconds for a given day, in the range -2 .. 2. =item * day_length( $rd ) Returns the number of seconds for a given day, in the range 86398 .. 86402. =back =head1 SEE ALSO L http://datetime.perl.org =head1 SUPPORT Bugs may be submitted at L. There is a mailing list available for users of this distribution, L. I am also usually active on IRC as 'autarch' on C. =head1 SOURCE The source code repository for DateTime can be found at L. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2003 - 2018 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) The full text of the license can be found in the F file included with this distribution. =cut DateTime-1.46/lib/DateTime/Types.pm0000644000175000017500000000724413240151623016710 0ustar autarchautarchpackage DateTime::Types; use strict; use warnings; use namespace::autoclean; our $VERSION = '1.46'; use parent 'Specio::Exporter'; use Specio 0.18; use Specio::Declare; use Specio::Library::Builtins -reexport; use Specio::Library::Numeric -reexport; use Specio::Library::String; any_can_type( 'ConvertibleObject', methods => ['utc_rd_values'], ); declare( 'DayOfMonth', parent => t('Int'), inline => sub { $_[0]->parent->inline_check( $_[1] ) . " && $_[1] >= 1 && $_[1] <= 31"; }, ); declare( 'DayOfYear', parent => t('Int'), inline => sub { $_[0]->parent->inline_check( $_[1] ) . " && $_[1] >= 1 && $_[1] <= 366"; }, ); object_isa_type( 'Duration', class => 'DateTime::Duration', ); enum( 'EndOfMonthMode', values => [qw( wrap limit preserve )], ); any_can_type( 'Formatter', methods => ['format_datetime'], ); my $locale_object = declare( 'LocaleObject', parent => t('Object'), inline => sub { # Can't use $_[1] directly because 5.8 gives very weird errors my $var = $_[1]; <<"EOF"; ( $var->isa('DateTime::Locale::FromData') || $var->isa('DateTime::Locale::Base') ) EOF }, ); union( 'Locale', of => [ t('NonEmptySimpleStr'), $locale_object ], ); my $time_zone_object = object_can_type( 'TZObject', methods => [ qw( is_floating is_utc name offset_for_datetime short_name_for_datetime ) ], ); declare( 'TimeZone', of => [ t('NonEmptySimpleStr'), $time_zone_object ], ); declare( 'Hour', parent => t('PositiveOrZeroInt'), inline => sub { $_[0]->parent->inline_check( $_[1] ) . " && $_[1] >= 0 && $_[1] <= 23"; }, ); declare( 'Minute', parent => t('PositiveOrZeroInt'), inline => sub { $_[0]->parent->inline_check( $_[1] ) . " && $_[1] >= 0 && $_[1] <= 59"; }, ); declare( 'Month', parent => t('PositiveInt'), inline => sub { $_[0]->parent->inline_check( $_[1] ) . " && $_[1] >= 1 && $_[1] <= 12"; }, ); declare( 'Nanosecond', parent => t('PositiveOrZeroInt'), ); declare( 'Second', parent => t('PositiveOrZeroInt'), inline => sub { $_[0]->parent->inline_check( $_[1] ) . " && $_[1] >= 0 && $_[1] <= 61"; }, ); enum( 'TruncationLevel', values => [ qw( year quarter month day hour minute second nanosecond week local_week ) ], ); declare( 'Year', parent => t('Int'), ); 1; # ABSTRACT: Types used for parameter checking in DateTime __END__ =pod =encoding UTF-8 =head1 NAME DateTime::Types - Types used for parameter checking in DateTime =head1 VERSION version 1.46 =head1 DESCRIPTION This module has no user-facing parts. =for Pod::Coverage .* =head1 SUPPORT Bugs may be submitted at L. There is a mailing list available for users of this distribution, L. I am also usually active on IRC as 'autarch' on C. =head1 SOURCE The source code repository for DateTime can be found at L. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2003 - 2018 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) The full text of the license can be found in the F file included with this distribution. =cut DateTime-1.46/lib/DateTime/Infinite.pm0000644000175000017500000001367013240151623017351 0ustar autarchautarch## no critic (Modules::ProhibitMultiplePackages) package DateTime::Infinite; use strict; use warnings; use namespace::autoclean; our $VERSION = '1.46'; use DateTime; use DateTime::TimeZone; use base qw(DateTime); foreach my $m (qw( set set_time_zone truncate )) { ## no critic (TestingAndDebugging::ProhibitNoStrict) no strict 'refs'; *{"DateTime::Infinite::$m"} = sub { return $_[0] }; } sub is_finite {0} sub is_infinite {1} ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines) sub _rd2ymd { return $_[2] ? ( $_[1] ) x 7 : ( $_[1] ) x 3; } sub _seconds_as_components { return ( $_[1] ) x 3; } sub ymd { return $_[0]->iso8601; } sub mdy { return $_[0]->iso8601; } sub dmy { return $_[0]->iso8601; } sub hms { return $_[0]->iso8601; } sub hour_12 { return $_[0]->_infinity_string; } sub hour_12_0 { return $_[0]->_infinity_string; } sub datetime { return $_[0]->_infinity_string; } sub stringify { return $_[0]->_infinity_string; } sub _infinity_string { return $_[0]->{utc_rd_days} == DateTime::INFINITY ? DateTime::INFINITY . q{} : DateTime::NEG_INFINITY . q{}; } sub _week_values { [ $_[0]->{utc_rd_days}, $_[0]->{utc_rd_days} ] } sub STORABLE_freeze {return} sub STORABLE_thaw {return} package DateTime::Infinite::Future; use strict; use warnings; use base qw(DateTime::Infinite); { my $Pos = bless { utc_rd_days => DateTime::INFINITY, utc_rd_secs => DateTime::INFINITY, local_rd_days => DateTime::INFINITY, local_rd_secs => DateTime::INFINITY, rd_nanosecs => DateTime::INFINITY, tz => DateTime::TimeZone->new( name => 'floating' ), locale => FakeLocale->instance(), }, __PACKAGE__; $Pos->_calc_utc_rd; $Pos->_calc_local_rd; sub new {$Pos} } package DateTime::Infinite::Past; use strict; use warnings; use base qw(DateTime::Infinite); { my $Neg = bless { utc_rd_days => DateTime::NEG_INFINITY, utc_rd_secs => DateTime::NEG_INFINITY, local_rd_days => DateTime::NEG_INFINITY, local_rd_secs => DateTime::NEG_INFINITY, rd_nanosecs => DateTime::NEG_INFINITY, tz => DateTime::TimeZone->new( name => 'floating' ), locale => FakeLocale->instance(), }, __PACKAGE__; $Neg->_calc_utc_rd; $Neg->_calc_local_rd; sub new {$Neg} } package # hide from PAUSE FakeLocale; use strict; use warnings; use DateTime::Locale; my $Instance; sub instance { return $Instance ||= bless { locale => DateTime::Locale->load('en_US') }, __PACKAGE__; } sub id { return 'infinite'; } sub language_id { return 'infinite'; } sub name { 'Fake locale for Infinite DateTime objects'; } sub language { 'Fake locale for Infinite DateTime objects'; } my @methods = qw( script_id territory_id variant_id script territory variant native_name native_language native_script native_territory native_variant ); for my $meth (@methods) { ## no critic (TestingAndDebugging::ProhibitNoStrict) no strict 'refs'; *{$meth} = sub {undef}; } # Totally arbitrary sub first_day_of_week { return 1; } sub prefers_24_hour_time { return 0; } our $AUTOLOAD; ## no critic (ClassHierarchies::ProhibitAutoloading) sub AUTOLOAD { my $self = shift; my ($meth) = $AUTOLOAD =~ /::(\w+)$/; if ( $meth =~ /format/ && $meth !~ /^(?:day|month|quarter)/ ) { return $self->{locale}->$meth(@_); } return []; } 1; # ABSTRACT: Infinite past and future DateTime objects __END__ =pod =encoding UTF-8 =head1 NAME DateTime::Infinite - Infinite past and future DateTime objects =head1 VERSION version 1.46 =head1 SYNOPSIS my $future = DateTime::Infinite::Future->new(); my $past = DateTime::Infinite::Past->new(); =head1 DESCRIPTION This module provides two L subclasses, C and C. The objects are in the "floating" timezone, and this cannot be changed. =head1 METHODS The only constructor for these two classes is the C method, as shown in the L. This method takes no parameters. All "get" methods in this module simply return infinity, positive or negative. If the method is expected to return a string, it returns the string representation of positive or negative infinity used by your system. For example, on my system calling C returns a number which when printed appears either "Inf" or "-Inf". This also applies to methods that are compound stringifications, which return the same strings even for things like C or C The object is not mutable, so the C, C, and C methods are all do-nothing methods that simply return the object they are called with. Obviously, the C method returns false and the C method returns true. =head1 SEE ALSO datetime@perl.org mailing list http://datetime.perl.org/ =head1 BUGS There seem to be lots of problems when dealing with infinite numbers on Win32. This may be a problem with this code, Perl, or Win32's IEEE math implementation. Either way, the module may not be well-behaved on Win32 operating systems. Bugs may be submitted at L. There is a mailing list available for users of this distribution, L. I am also usually active on IRC as 'autarch' on C. =head1 SOURCE The source code repository for DateTime can be found at L. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2003 - 2018 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) The full text of the license can be found in the F file included with this distribution. =cut DateTime-1.46/lib/DateTime/Conflicts.pm0000644000175000017500000000161313240151623017522 0ustar autarchautarchpackage # hide from PAUSE DateTime::Conflicts; use strict; use warnings; # this module was generated with Dist::Zilla::Plugin::Conflicts 0.19 use Dist::CheckConflicts -dist => 'DateTime', -conflicts => { 'DateTime::Format::Mail' => '0.402', }, -also => [ qw( Carp DateTime::Locale DateTime::TimeZone Dist::CheckConflicts POSIX Params::ValidationCompiler Scalar::Util Specio Specio::Declare Specio::Exporter Specio::Library::Builtins Specio::Library::Numeric Specio::Library::String Try::Tiny XSLoader base integer namespace::autoclean overload parent strict warnings warnings::register ) ], ; 1; # ABSTRACT: Provide information on conflicts for DateTime # Dist::Zilla: -PodWeaver DateTime-1.46/lib/DateTime/Helpers.pm0000644000175000017500000000061413240151623017200 0ustar autarchautarchpackage DateTime::Helpers; use strict; use warnings; our $VERSION = '1.46'; use Scalar::Util (); sub can { my $object = shift; my $method = shift; return unless Scalar::Util::blessed($object); return $object->can($method); } sub isa { my $object = shift; my $method = shift; return unless Scalar::Util::blessed($object); return $object->isa($method); } 1; DateTime-1.46/lib/DateTime/PPExtra.pm0000644000175000017500000000330413240151623017120 0ustar autarchautarchpackage DateTime::PPExtra; use strict; use warnings; our $VERSION = '1.46'; use DateTime::LeapSecond; ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines) sub _normalize_tai_seconds { return if grep { $_ == DateTime::INFINITY() || $_ == DateTime::NEG_INFINITY() } @_[ 1, 2 ]; # This must be after checking for infinity, because it breaks in # presence of use integer ! use integer; my $adj; if ( $_[2] < 0 ) { $adj = ( $_[2] - 86399 ) / 86400; } else { $adj = $_[2] / 86400; } $_[1] += $adj; $_[2] -= $adj * 86400; } sub _normalize_leap_seconds { # args: 0 => days, 1 => seconds my $delta_days; use integer; # rough adjust - can adjust many days if ( $_[2] < 0 ) { $delta_days = ( $_[2] - 86399 ) / 86400; } else { $delta_days = $_[2] / 86400; } my $new_day = $_[1] + $delta_days; my $delta_seconds = ( 86400 * $delta_days ) + DateTime::LeapSecond::leap_seconds($new_day) - DateTime::LeapSecond::leap_seconds( $_[1] ); $_[2] -= $delta_seconds; $_[1] = $new_day; # fine adjust - up to 1 day my $day_length = DateTime::LeapSecond::day_length($new_day); if ( $_[2] >= $day_length ) { $_[2] -= $day_length; $_[1]++; } elsif ( $_[2] < 0 ) { $day_length = DateTime::LeapSecond::day_length( $new_day - 1 ); $_[2] += $day_length; $_[1]--; } } my @subs = qw( _normalize_tai_seconds _normalize_leap_seconds ); for my $sub (@subs) { ## no critic (TestingAndDebugging::ProhibitNoStrict) no strict 'refs'; *{ 'DateTime::' . $sub } = __PACKAGE__->can($sub); } 1; DateTime-1.46/lib/DateTime.pm0000644000175000017500000040155213240151623015604 0ustar autarchautarch## no critic (Modules::ProhibitExcessMainComplexity) package DateTime; use 5.008004; use strict; use warnings; use warnings::register; use namespace::autoclean 0.19; our $VERSION = '1.46'; use Carp; use DateTime::Duration; use DateTime::Helpers; use DateTime::Locale 1.06; use DateTime::TimeZone 2.02; use DateTime::Types; use POSIX qw( floor fmod ); use Params::ValidationCompiler 0.26 qw( validation_for ); use Scalar::Util qw( blessed ); use Try::Tiny; ## no critic (Variables::ProhibitPackageVars) our $IsPurePerl; { my $loaded = 0; unless ( $ENV{PERL_DATETIME_PP} ) { try { require XSLoader; XSLoader::load( __PACKAGE__, exists $DateTime::{VERSION} && ${ $DateTime::{VERSION} } ? ${ $DateTime::{VERSION} } : 42 ); $loaded = 1; $IsPurePerl = 0; } catch { die $_ if $_ && $_ !~ /object version|loadable object/; }; } if ($loaded) { ## no critic (Variables::ProtectPrivateVars) require DateTime::PPExtra unless defined &DateTime::_normalize_tai_seconds; } else { require DateTime::PP; } } # for some reason, overloading doesn't work unless fallback is listed # early. # # 3rd parameter ( $_[2] ) means the parameters are 'reversed'. # see: "Calling conventions for binary operations" in overload docs. # use overload ( fallback => 1, '<=>' => '_compare_overload', 'cmp' => '_string_compare_overload', q{""} => 'stringify', bool => sub {1}, '-' => '_subtract_overload', '+' => '_add_overload', 'eq' => '_string_equals_overload', 'ne' => '_string_not_equals_overload', ); # Have to load this after overloading is defined, after BEGIN blocks # or else weird crashes ensue require DateTime::Infinite; sub MAX_NANOSECONDS () {1_000_000_000} # 1E9 = almost 32 bits sub INFINITY () { 100**100**100**100 } sub NEG_INFINITY () { -1 * ( 100**100**100**100 ) } sub NAN () { INFINITY - INFINITY } sub SECONDS_PER_DAY () {86400} sub duration_class () {'DateTime::Duration'} my ( @MonthLengths, @LeapYearMonthLengths, @QuarterLengths, @LeapYearQuarterLengths, ); BEGIN { @MonthLengths = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); @LeapYearMonthLengths = @MonthLengths; $LeapYearMonthLengths[1]++; @QuarterLengths = ( 90, 91, 92, 92 ); @LeapYearQuarterLengths = @QuarterLengths; $LeapYearQuarterLengths[0]++; } { # I'd rather use Class::Data::Inheritable for this, but there's no # way to add the module-loading behavior to an accessor it # creates, despite what its docs say! my $DefaultLocale; sub DefaultLocale { shift; if (@_) { my $lang = shift; $DefaultLocale = DateTime::Locale->load($lang); } return $DefaultLocale; } } __PACKAGE__->DefaultLocale('en-US'); { my $validator = validation_for( name => '_check_new_params', name_is_optional => 1, params => { year => { type => t('Year') }, month => { type => t('Month'), default => 1, }, day => { type => t('DayOfMonth'), default => 1, }, hour => { type => t('Hour'), default => 0, }, minute => { type => t('Minute'), default => 0, }, second => { type => t('Second'), default => 0, }, nanosecond => { type => t('Nanosecond'), default => 0, }, locale => { type => t('Locale'), optional => 1, }, formatter => { type => t('Formatter'), optional => 1, }, time_zone => { type => t('TimeZone'), optional => 1, }, }, ); sub new { my $class = shift; my %p = $validator->(@_); Carp::croak( "Invalid day of month (day = $p{day} - month = $p{month} - year = $p{year})\n" ) if $p{day} > 28 && $p{day} > $class->_month_length( $p{year}, $p{month} ); return $class->_new(%p); } } sub _new { my $class = shift; my %p = @_; Carp::croak('Constructor called with reference, we expected a package') if ref $class; # If this method is called from somewhere other than new(), then some of # these defaults may not get applied. $p{month} = 1 unless exists $p{month}; $p{day} = 1 unless exists $p{day}; $p{hour} = 0 unless exists $p{hour}; $p{minute} = 0 unless exists $p{minute}; $p{second} = 0 unless exists $p{second}; $p{nanosecond} = 0 unless exists $p{nanosecond}; $p{time_zone} = $class->_default_time_zone unless exists $p{time_zone}; my $self = bless {}, $class; $self->_set_locale( $p{locale} ); $self->{tz} = ( ref $p{time_zone} ? $p{time_zone} : DateTime::TimeZone->new( name => $p{time_zone} ) ); $self->{local_rd_days} = $class->_ymd2rd( @p{qw( year month day )} ); $self->{local_rd_secs} = $class->_time_as_seconds( @p{qw( hour minute second )} ); $self->{offset_modifier} = 0; $self->{rd_nanosecs} = $p{nanosecond}; $self->{formatter} = $p{formatter}; $self->_normalize_nanoseconds( $self->{local_rd_secs}, $self->{rd_nanosecs} ); # Set this explicitly since it can't be calculated accurately # without knowing our time zone offset, and it's possible that the # offset can't be calculated without having at least a rough guess # of the datetime's year. This year need not be correct, as long # as its equal or greater to the correct number, so we fudge by # adding one to the local year given to the constructor. $self->{utc_year} = $p{year} + 1; $self->_maybe_future_dst_warning( $p{year}, $p{time_zone} ); $self->_calc_utc_rd; $self->_handle_offset_modifier( $p{second} ); $self->_calc_local_rd; if ( $p{second} > 59 ) { if ( $self->{tz}->is_floating || # If true, this means that the actual calculated leap # second does not occur in the second given to new() ( $self->{utc_rd_secs} - 86399 < $p{second} - 59 ) ) { Carp::croak("Invalid second value ($p{second})\n"); } } return $self; } # Warning: do not use this environment variable unless you have no choice in # the matter. sub _default_time_zone { return $ENV{PERL_DATETIME_DEFAULT_TZ} || 'floating'; } sub _set_locale { my $self = shift; my $locale = shift; if ( defined $locale && ref $locale ) { $self->{locale} = $locale; } else { $self->{locale} = $locale ? DateTime::Locale->load($locale) : $self->DefaultLocale(); } return; } # This method exists for the benefit of internal methods which create # a new object based on the current object, like set() and truncate(). sub _new_from_self { my $self = shift; my %p = @_; my %old = map { $_ => $self->$_() } qw( year month day hour minute second nanosecond locale time_zone ); $old{formatter} = $self->formatter() if defined $self->formatter(); my $method = delete $p{_skip_validation} ? '_new' : 'new'; return ( ref $self )->$method( %old, %p ); } sub _handle_offset_modifier { my $self = shift; $self->{offset_modifier} = 0; return if $self->{tz}->is_floating; my $second = shift; my $utc_is_valid = shift; my $utc_rd_days = $self->{utc_rd_days}; my $offset = $utc_is_valid ? $self->offset : $self->_offset_for_local_datetime; if ( $offset >= 0 && $self->{local_rd_secs} >= $offset ) { if ( $second < 60 && $offset > 0 ) { $self->{offset_modifier} = $self->_day_length( $utc_rd_days - 1 ) - SECONDS_PER_DAY; $self->{local_rd_secs} += $self->{offset_modifier}; } elsif ( $second == 60 && ( ( $self->{local_rd_secs} == $offset && $offset > 0 ) || ( $offset == 0 && $self->{local_rd_secs} > 86399 ) ) ) { my $mod = $self->_day_length( $utc_rd_days - 1 ) - SECONDS_PER_DAY; unless ( $mod == 0 ) { $self->{utc_rd_secs} -= $mod; $self->_normalize_seconds; } } } elsif ($offset < 0 && $self->{local_rd_secs} >= SECONDS_PER_DAY + $offset ) { if ( $second < 60 ) { $self->{offset_modifier} = $self->_day_length( $utc_rd_days - 1 ) - SECONDS_PER_DAY; $self->{local_rd_secs} += $self->{offset_modifier}; } elsif ($second == 60 && $self->{local_rd_secs} == SECONDS_PER_DAY + $offset ) { my $mod = $self->_day_length( $utc_rd_days - 1 ) - SECONDS_PER_DAY; unless ( $mod == 0 ) { $self->{utc_rd_secs} -= $mod; $self->_normalize_seconds; } } } } sub _calc_utc_rd { my $self = shift; delete $self->{utc_c}; if ( $self->{tz}->is_utc || $self->{tz}->is_floating ) { $self->{utc_rd_days} = $self->{local_rd_days}; $self->{utc_rd_secs} = $self->{local_rd_secs}; } else { my $offset = $self->_offset_for_local_datetime; $offset += $self->{offset_modifier}; $self->{utc_rd_days} = $self->{local_rd_days}; $self->{utc_rd_secs} = $self->{local_rd_secs} - $offset; } # We account for leap seconds in the new() method and nowhere else # except date math. $self->_normalize_tai_seconds( $self->{utc_rd_days}, $self->{utc_rd_secs} ); } sub _normalize_seconds { my $self = shift; return if $self->{utc_rd_secs} >= 0 && $self->{utc_rd_secs} <= 86399; if ( $self->{tz}->is_floating ) { $self->_normalize_tai_seconds( $self->{utc_rd_days}, $self->{utc_rd_secs} ); } else { $self->_normalize_leap_seconds( $self->{utc_rd_days}, $self->{utc_rd_secs} ); } } sub _calc_local_rd { my $self = shift; delete $self->{local_c}; # We must short circuit for UTC times or else we could end up with # loops between DateTime.pm and DateTime::TimeZone if ( $self->{tz}->is_utc || $self->{tz}->is_floating ) { $self->{local_rd_days} = $self->{utc_rd_days}; $self->{local_rd_secs} = $self->{utc_rd_secs}; } else { my $offset = $self->offset; $self->{local_rd_days} = $self->{utc_rd_days}; $self->{local_rd_secs} = $self->{utc_rd_secs} + $offset; # intentionally ignore leap seconds here $self->_normalize_tai_seconds( $self->{local_rd_days}, $self->{local_rd_secs} ); $self->{local_rd_secs} += $self->{offset_modifier}; } $self->_calc_local_components; } sub _calc_local_components { my $self = shift; @{ $self->{local_c} }{ qw( year month day day_of_week day_of_year quarter day_of_quarter) } = $self->_rd2ymd( $self->{local_rd_days}, 1 ); @{ $self->{local_c} }{qw( hour minute second )} = $self->_seconds_as_components( $self->{local_rd_secs}, $self->{utc_rd_secs}, $self->{offset_modifier} ); } { my $validator = validation_for( name => '_check_from_epoch_params', name_is_optional => 1, params => { epoch => { type => t('Num') }, formatter => { type => t('Formatter'), optional => 1 }, locale => { type => t('Locale'), optional => 1 }, time_zone => { type => t('TimeZone'), optional => 1 }, }, ); sub from_epoch { my $class = shift; my %p = $validator->(@_); my %args; # This does two things. First, if given a negative non-integer epoch, # it will round the epoch _down_ to the next second and then adjust # the nanoseconds to be positive. In other words, -0.5 corresponds to # a second of -1 and a nanosecond value of 500,000. Before this code # was implemented our handling of negative non-integer epochs was # quite broken, and would end up rounding some values up, so that -0.5 # become 0.5 (which is obviously wrong!). # # Second, it rounds any decimal values to the nearest microsecond # (1E6). Here's what Christian Hansen, who wrote this patch, says: # # Perl is typically compiled with NV as a double. A double with a # significand precision of 53 bits can only represent a nanosecond # epoch without loss of precision if the duration from zero epoch # is less than ≈ ±104 days. With microseconds the duration is # ±104,000 days, which is ≈ ±285 years. if ( int $p{epoch} != $p{epoch} ) { my ( $floor, $nano, $second ); $floor = $nano = fmod( $p{epoch}, 1.0 ); $second = floor( $p{epoch} - $floor ); if ( $nano < 0 ) { $nano += 1; } $p{epoch} = $second + floor( $floor - $nano ); $args{nanosecond} = floor( $nano * 1E6 + 0.5 ) * 1E3; } # Note, for very large negative values this may give a # blatantly wrong answer. @args{qw( second minute hour day month year )} = ( gmtime( $p{epoch} ) )[ 0 .. 5 ]; $args{year} += 1900; $args{month}++; my $self = $class->_new( %p, %args, time_zone => 'UTC' ); $self->_maybe_future_dst_warning( $self->year(), $p{time_zone} ); $self->set_time_zone( $p{time_zone} ) if exists $p{time_zone}; return $self; } } sub now { my $class = shift; return $class->from_epoch( epoch => $class->_core_time(), @_ ); } sub _maybe_future_dst_warning { shift; my $year = shift; my $tz = shift; return unless $year >= 5000 && $tz; my $tz_name = ref $tz ? $tz->name() : $tz; return if $tz_name eq 'floating' || $tz_name eq 'UTC'; warnings::warnif( "You are creating a DateTime object with a far future year ($year) and a time zone ($tz_name)." . ' If the time zone you specified has future DST changes this will be very slow.' ); } # use scalar time in case someone's loaded Time::Piece sub _core_time { return scalar time; } sub today { shift->now(@_)->truncate( to => 'day' ) } { my $validator = validation_for( name => '_check_from_object_params', name_is_optional => 1, params => { object => { type => t('ConvertibleObject') }, locale => { type => t('Locale'), optional => 1, }, formatter => { type => t('Formatter'), optional => 1, }, }, ); sub from_object { my $class = shift; my %p = $validator->(@_); my $object = delete $p{object}; if ( $object->isa('DateTime::Infinite') ) { return $object->clone; } my ( $rd_days, $rd_secs, $rd_nanosecs ) = $object->utc_rd_values; # A kludge because until all calendars are updated to return all # three values, $rd_nanosecs could be undef $rd_nanosecs ||= 0; # This is a big hack to let _seconds_as_components operate naively # on the given value. If the object _is_ on a leap second, we'll # add that to the generated seconds value later. my $leap_seconds = 0; if ( $object->can('time_zone') && !$object->time_zone->is_floating && $rd_secs > 86399 && $rd_secs <= $class->_day_length($rd_days) ) { $leap_seconds = $rd_secs - 86399; $rd_secs -= $leap_seconds; } my %args; @args{qw( year month day )} = $class->_rd2ymd($rd_days); @args{qw( hour minute second )} = $class->_seconds_as_components($rd_secs); $args{nanosecond} = $rd_nanosecs; $args{second} += $leap_seconds; my $new = $class->new( %p, %args, time_zone => 'UTC' ); if ( $object->can('time_zone') ) { $new->set_time_zone( $object->time_zone ); } else { $new->set_time_zone( $class->_default_time_zone ); } return $new; } } { my $validator = validation_for( name => '_check_last_day_of_month_params', name_is_optional => 1, params => { year => { type => t('Year') }, month => { type => t('Month') }, day => { type => t('DayOfMonth'), default => 1, }, hour => { type => t('Hour'), default => 0, }, minute => { type => t('Minute'), default => 0, }, second => { type => t('Second'), default => 0, }, nanosecond => { type => t('Nanosecond'), default => 0, }, locale => { type => t('Locale'), optional => 1, }, formatter => { type => t('Formatter'), optional => 1, }, time_zone => { type => t('TimeZone'), optional => 1, }, }, ); sub last_day_of_month { my $class = shift; my %p = $validator->(@_); my $day = $class->_month_length( $p{year}, $p{month} ); return $class->_new( %p, day => $day ); } } sub _month_length { return ( $_[0]->_is_leap_year( $_[1] ) ? $LeapYearMonthLengths[ $_[2] - 1 ] : $MonthLengths[ $_[2] - 1 ] ); } { my $validator = validation_for( name => '_check_from_day_of_year_params', name_is_optional => 1, params => { year => { type => t('Year') }, day_of_year => { type => t('DayOfYear') }, hour => { type => t('Hour'), default => 0, }, minute => { type => t('Minute'), default => 0, }, second => { type => t('Second'), default => 0, }, nanosecond => { type => t('Nanosecond'), default => 0, }, locale => { type => t('Locale'), optional => 1, }, formatter => { type => t('Formatter'), optional => 1, }, time_zone => { type => t('TimeZone'), optional => 1, }, }, ); sub from_day_of_year { my $class = shift; my %p = $validator->(@_); Carp::croak("$p{year} is not a leap year.\n") if $p{day_of_year} == 366 && !$class->_is_leap_year( $p{year} ); my $month = 1; my $day = delete $p{day_of_year}; if ( $day > 31 ) { my $length = $class->_month_length( $p{year}, $month ); while ( $day > $length ) { $day -= $length; $month++; $length = $class->_month_length( $p{year}, $month ); } } return $class->_new( %p, month => $month, day => $day, ); } } sub formatter { $_[0]->{formatter} } sub clone { bless { %{ $_[0] } }, ref $_[0] } sub year { Carp::carp('year() is a read-only accessor') if @_ > 1; return $_[0]->{local_c}{year}; } sub ce_year { $_[0]->{local_c}{year} <= 0 ? $_[0]->{local_c}{year} - 1 : $_[0]->{local_c}{year}; } sub era_name { $_[0]->{locale}->era_wide->[ $_[0]->_era_index() ] } sub era_abbr { $_[0]->{locale}->era_abbreviated->[ $_[0]->_era_index() ] } # deprecated *era = \&era_abbr; sub _era_index { $_[0]->{local_c}{year} <= 0 ? 0 : 1 } sub christian_era { $_[0]->ce_year > 0 ? 'AD' : 'BC' } sub secular_era { $_[0]->ce_year > 0 ? 'CE' : 'BCE' } sub year_with_era { ( abs $_[0]->ce_year ) . $_[0]->era_abbr } sub year_with_christian_era { ( abs $_[0]->ce_year ) . $_[0]->christian_era } sub year_with_secular_era { ( abs $_[0]->ce_year ) . $_[0]->secular_era } sub month { Carp::carp('month() is a read-only accessor') if @_ > 1; return $_[0]->{local_c}{month}; } *mon = \&month; sub month_0 { $_[0]->{local_c}{month} - 1 } *mon_0 = \&month_0; sub month_name { $_[0]->{locale}->month_format_wide->[ $_[0]->month_0() ] } sub month_abbr { $_[0]->{locale}->month_format_abbreviated->[ $_[0]->month_0() ]; } sub day_of_month { Carp::carp('day_of_month() is a read-only accessor') if @_ > 1; $_[0]->{local_c}{day}; } *day = \&day_of_month; *mday = \&day_of_month; sub weekday_of_month { use integer; ( ( $_[0]->day - 1 ) / 7 ) + 1 } sub quarter { $_[0]->{local_c}{quarter} } sub quarter_name { $_[0]->{locale}->quarter_format_wide->[ $_[0]->quarter_0() ]; } sub quarter_abbr { $_[0]->{locale}->quarter_format_abbreviated->[ $_[0]->quarter_0() ]; } sub quarter_0 { $_[0]->{local_c}{quarter} - 1 } sub day_of_month_0 { $_[0]->{local_c}{day} - 1 } *day_0 = \&day_of_month_0; *mday_0 = \&day_of_month_0; sub day_of_week { $_[0]->{local_c}{day_of_week} } *wday = \&day_of_week; *dow = \&day_of_week; sub day_of_week_0 { $_[0]->{local_c}{day_of_week} - 1 } *wday_0 = \&day_of_week_0; *dow_0 = \&day_of_week_0; sub local_day_of_week { my $self = shift; return 1 + ( $self->day_of_week - $self->{locale}->first_day_of_week ) % 7; } sub day_name { $_[0]->{locale}->day_format_wide->[ $_[0]->day_of_week_0() ] } sub day_abbr { $_[0]->{locale}->day_format_abbreviated->[ $_[0]->day_of_week_0() ]; } sub day_of_quarter { $_[0]->{local_c}{day_of_quarter} } *doq = \&day_of_quarter; sub day_of_quarter_0 { $_[0]->day_of_quarter - 1 } *doq_0 = \&day_of_quarter_0; sub day_of_year { $_[0]->{local_c}{day_of_year} } *doy = \&day_of_year; sub day_of_year_0 { $_[0]->{local_c}{day_of_year} - 1 } *doy_0 = \&day_of_year_0; sub am_or_pm { $_[0]->{locale}->am_pm_abbreviated->[ $_[0]->hour() < 12 ? 0 : 1 ]; } sub ymd { my ( $self, $sep ) = @_; $sep = '-' unless defined $sep; return sprintf( '%0.4d%s%0.2d%s%0.2d', $self->year, $sep, $self->{local_c}{month}, $sep, $self->{local_c}{day} ); } *date = sub { shift->ymd(@_) }; sub mdy { my ( $self, $sep ) = @_; $sep = '-' unless defined $sep; return sprintf( '%0.2d%s%0.2d%s%0.4d', $self->{local_c}{month}, $sep, $self->{local_c}{day}, $sep, $self->year ); } sub dmy { my ( $self, $sep ) = @_; $sep = '-' unless defined $sep; return sprintf( '%0.2d%s%0.2d%s%0.4d', $self->{local_c}{day}, $sep, $self->{local_c}{month}, $sep, $self->year ); } sub hour { Carp::carp('hour() is a read-only accessor') if @_ > 1; return $_[0]->{local_c}{hour}; } sub hour_1 { $_[0]->{local_c}{hour} == 0 ? 24 : $_[0]->{local_c}{hour} } sub hour_12 { my $h = $_[0]->hour % 12; return $h ? $h : 12 } sub hour_12_0 { $_[0]->hour % 12 } sub minute { Carp::carp('minute() is a read-only accessor') if @_ > 1; return $_[0]->{local_c}{minute}; } *min = \&minute; sub second { Carp::carp('second() is a read-only accessor') if @_ > 1; return $_[0]->{local_c}{second}; } *sec = \&second; sub fractional_second { $_[0]->second + $_[0]->nanosecond / MAX_NANOSECONDS } sub nanosecond { Carp::carp('nanosecond() is a read-only accessor') if @_ > 1; return $_[0]->{rd_nanosecs}; } sub millisecond { floor( $_[0]->{rd_nanosecs} / 1000000 ) } sub microsecond { floor( $_[0]->{rd_nanosecs} / 1000 ) } sub leap_seconds { my $self = shift; return 0 if $self->{tz}->is_floating; return $self->_accumulated_leap_seconds( $self->{utc_rd_days} ); } sub stringify { my $self = shift; return $self->iso8601 unless $self->{formatter}; return $self->{formatter}->format_datetime($self); } sub hms { my ( $self, $sep ) = @_; $sep = ':' unless defined $sep; return sprintf( '%0.2d%s%0.2d%s%0.2d', $self->{local_c}{hour}, $sep, $self->{local_c}{minute}, $sep, $self->{local_c}{second} ); } # don't want to override CORE::time() *DateTime::time = sub { shift->hms(@_) }; sub iso8601 { $_[0]->datetime('T') } sub datetime { my ( $self, $sep ) = @_; $sep = 'T' unless defined $sep; return join $sep, $self->ymd('-'), $self->hms(':'); } sub is_leap_year { $_[0]->_is_leap_year( $_[0]->year ) } sub month_length { $_[0]->_month_length( $_[0]->year, $_[0]->month ); } sub quarter_length { return ( $_[0]->_is_leap_year( $_[0]->year ) ? $LeapYearQuarterLengths[ $_[0]->quarter - 1 ] : $QuarterLengths[ $_[0]->quarter - 1 ] ); } sub year_length { $_[0]->_is_leap_year( $_[0]->year ) ? 366 : 365; } sub is_last_day_of_month { $_[0]->day == $_[0]->_month_length( $_[0]->year, $_[0]->month ); } sub week { my $self = shift; $self->{utc_c}{week_year} ||= $self->_week_values; return @{ $self->{utc_c}{week_year} }[ 0, 1 ]; } # This algorithm comes from # https://en.wikipedia.org/wiki/ISO_week_date#Calculating_the_week_number_of_a_given_date sub _week_values { my $self = shift; my $week = int( ( ( $self->day_of_year - $self->day_of_week ) + 10 ) / 7 ); my $year = $self->year; if ( $week == 0 ) { $year--; return [ $year, $self->_weeks_in_year($year) ]; } elsif ( $week == 53 && $self->_weeks_in_year($year) == 52 ) { return [ $year + 1, 1 ]; } return [ $year, $week ]; } sub _weeks_in_year { my $self = shift; my $year = shift; my $dow = $self->_ymd2rd( $year, 1, 1 ) % 7; # Years starting with a Thursday and leap years starting with a Wednesday # have 53 weeks. return ( $dow == 4 || ( $dow == 3 && $self->_is_leap_year($year) ) ) ? 53 : 52; } sub week_year { ( $_[0]->week )[0] } sub week_number { ( $_[0]->week )[1] } # ISO says that the first week of a year is the first week containing # a Thursday. Extending that says that the first week of the month is # the first week containing a Thursday. ICU agrees. sub week_of_month { my $self = shift; my $thu = $self->day + 4 - $self->day_of_week; return int( ( $thu + 6 ) / 7 ); } sub time_zone { Carp::carp('time_zone() is a read-only accessor') if @_ > 1; return $_[0]->{tz}; } sub offset { $_[0]->{tz}->offset_for_datetime( $_[0] ) } sub _offset_for_local_datetime { $_[0]->{tz}->offset_for_local_datetime( $_[0] ); } sub is_dst { $_[0]->{tz}->is_dst_for_datetime( $_[0] ) } sub time_zone_long_name { $_[0]->{tz}->name } sub time_zone_short_name { $_[0]->{tz}->short_name_for_datetime( $_[0] ) } sub locale { Carp::carp('locale() is a read-only accessor') if @_ > 1; return $_[0]->{locale}; } sub utc_rd_values { @{ $_[0] }{ 'utc_rd_days', 'utc_rd_secs', 'rd_nanosecs' }; } sub local_rd_values { @{ $_[0] }{ 'local_rd_days', 'local_rd_secs', 'rd_nanosecs' }; } # NOTE: no nanoseconds, no leap seconds sub utc_rd_as_seconds { ( $_[0]->{utc_rd_days} * SECONDS_PER_DAY ) + $_[0]->{utc_rd_secs}; } # NOTE: no nanoseconds, no leap seconds sub local_rd_as_seconds { ( $_[0]->{local_rd_days} * SECONDS_PER_DAY ) + $_[0]->{local_rd_secs}; } # RD 1 is MJD 678,576 - a simple offset sub mjd { my $self = shift; my $mjd = $self->{utc_rd_days} - 678_576; my $day_length = $self->_day_length( $self->{utc_rd_days} ); return ( $mjd + ( $self->{utc_rd_secs} / $day_length ) + ( $self->{rd_nanosecs} / $day_length / MAX_NANOSECONDS ) ); } sub jd { $_[0]->mjd + 2_400_000.5 } { my %strftime_patterns = ( 'a' => sub { $_[0]->day_abbr }, 'A' => sub { $_[0]->day_name }, 'b' => sub { $_[0]->month_abbr }, 'B' => sub { $_[0]->month_name }, 'c' => sub { $_[0]->format_cldr( $_[0]->{locale}->datetime_format_default() ); }, 'C' => sub { int( $_[0]->year / 100 ) }, 'd' => sub { sprintf( '%02d', $_[0]->day_of_month ) }, 'D' => sub { $_[0]->strftime('%m/%d/%y') }, 'e' => sub { sprintf( '%2d', $_[0]->day_of_month ) }, 'F' => sub { $_[0]->ymd('-') }, 'g' => sub { substr( $_[0]->week_year, -2 ) }, 'G' => sub { $_[0]->week_year }, 'H' => sub { sprintf( '%02d', $_[0]->hour ) }, 'I' => sub { sprintf( '%02d', $_[0]->hour_12 ) }, 'j' => sub { sprintf( '%03d', $_[0]->day_of_year ) }, 'k' => sub { sprintf( '%2d', $_[0]->hour ) }, 'l' => sub { sprintf( '%2d', $_[0]->hour_12 ) }, 'm' => sub { sprintf( '%02d', $_[0]->month ) }, 'M' => sub { sprintf( '%02d', $_[0]->minute ) }, 'n' => sub {"\n"}, # should this be OS-sensitive? 'N' => \&_format_nanosecs, 'p' => sub { $_[0]->am_or_pm() }, 'P' => sub { lc $_[0]->am_or_pm() }, 'r' => sub { $_[0]->strftime('%I:%M:%S %p') }, 'R' => sub { $_[0]->strftime('%H:%M') }, 's' => sub { $_[0]->epoch }, 'S' => sub { sprintf( '%02d', $_[0]->second ) }, 't' => sub {"\t"}, 'T' => sub { $_[0]->strftime('%H:%M:%S') }, 'u' => sub { $_[0]->day_of_week }, 'U' => sub { my $sun = $_[0]->day_of_year - ( $_[0]->day_of_week + 7 ) % 7; return sprintf( '%02d', int( ( $sun + 6 ) / 7 ) ); }, 'V' => sub { sprintf( '%02d', $_[0]->week_number ) }, 'w' => sub { my $dow = $_[0]->day_of_week; return $dow % 7; }, 'W' => sub { my $mon = $_[0]->day_of_year - ( $_[0]->day_of_week + 6 ) % 7; return sprintf( '%02d', int( ( $mon + 6 ) / 7 ) ); }, 'x' => sub { $_[0]->format_cldr( $_[0]->{locale}->date_format_default() ); }, 'X' => sub { $_[0]->format_cldr( $_[0]->{locale}->time_format_default() ); }, 'y' => sub { sprintf( '%02d', substr( $_[0]->year, -2 ) ) }, 'Y' => sub { return $_[0]->year }, 'z' => sub { DateTime::TimeZone->offset_as_string( $_[0]->offset ) }, 'Z' => sub { $_[0]->{tz}->short_name_for_datetime( $_[0] ) }, '%' => sub {'%'}, ); $strftime_patterns{h} = $strftime_patterns{b}; sub strftime { my $self = shift; # make a copy or caller's scalars get munged my @patterns = @_; my @r; foreach my $p (@patterns) { $p =~ s/ (?: %\{(\w+)\} # method name like %{day_name} | %([%a-zA-Z]) # single character specifier like %d | %(\d+)N # special case for %N ) / ( $1 ? ( $self->can($1) ? $self->$1() : "\%{$1}" ) : $2 ? ( $strftime_patterns{$2} ? $strftime_patterns{$2}->($self) : "\%$2" ) : $3 ? $strftime_patterns{N}->($self, $3) : '' # this won't happen ) /sgex; return $p unless wantarray; push @r, $p; } return @r; } } { # It's an array because the order in which the regexes are checked # is important. These patterns are similar to the ones Java uses, # but not quite the same. See # http://www.unicode.org/reports/tr35/tr35-9.html#Date_Format_Patterns. my @patterns = ( qr/GGGGG/ => sub { $_[0]->{locale}->era_narrow->[ $_[0]->_era_index() ] }, qr/GGGG/ => 'era_name', qr/G{1,3}/ => 'era_abbr', qr/(y{3,5})/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->year() ) }, # yy is a weird special case, where it must be exactly 2 digits qr/yy/ => sub { my $year = $_[0]->year(); my $y2 = length $year > 2 ? substr( $year, -2, 2 ) : $year; $y2 *= -1 if $year < 0; $_[0]->_zero_padded_number( 'yy', $y2 ); }, qr/y/ => sub { $_[0]->year() }, qr/(u+)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->year() ) }, qr/(Y+)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->week_year() ) }, qr/QQQQ/ => 'quarter_name', qr/QQQ/ => 'quarter_abbr', qr/(QQ?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->quarter() ) }, qr/qqqq/ => sub { $_[0]->{locale}->quarter_stand_alone_wide() ->[ $_[0]->quarter_0() ]; }, qr/qqq/ => sub { $_[0]->{locale}->quarter_stand_alone_abbreviated() ->[ $_[0]->quarter_0() ]; }, qr/(qq?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->quarter() ) }, qr/MMMMM/ => sub { $_[0]->{locale}->month_format_narrow->[ $_[0]->month_0() ] } , qr/MMMM/ => 'month_name', qr/MMM/ => 'month_abbr', qr/(MM?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->month() ) }, qr/LLLLL/ => sub { $_[0]->{locale}->month_stand_alone_narrow->[ $_[0]->month_0() ]; }, qr/LLLL/ => sub { $_[0]->{locale}->month_stand_alone_wide->[ $_[0]->month_0() ]; }, qr/LLL/ => sub { $_[0]->{locale} ->month_stand_alone_abbreviated->[ $_[0]->month_0() ]; }, qr/(LL?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->month() ) }, qr/(ww?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->week_number() ) }, qr/W/ => 'week_of_month', qr/(dd?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->day_of_month() ) }, qr/(D{1,3})/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->day_of_year() ) }, qr/F/ => 'weekday_of_month', qr/(g+)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->mjd() ) }, qr/EEEEE/ => sub { $_[0]->{locale}->day_format_narrow->[ $_[0]->day_of_week_0() ]; }, qr/EEEE/ => 'day_name', qr/E{1,3}/ => 'day_abbr', qr/eeeee/ => sub { $_[0]->{locale}->day_format_narrow->[ $_[0]->day_of_week_0() ]; }, qr/eeee/ => 'day_name', qr/eee/ => 'day_abbr', qr/(ee?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->local_day_of_week() ); }, qr/ccccc/ => sub { $_[0]->{locale} ->day_stand_alone_narrow->[ $_[0]->day_of_week_0() ]; }, qr/cccc/ => sub { $_[0]->{locale}->day_stand_alone_wide->[ $_[0]->day_of_week_0() ]; }, qr/ccc/ => sub { $_[0]->{locale} ->day_stand_alone_abbreviated->[ $_[0]->day_of_week_0() ]; }, qr/(cc?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->day_of_week() ) }, qr/a/ => 'am_or_pm', qr/(hh?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->hour_12() ) }, qr/(HH?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->hour() ) }, qr/(KK?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->hour_12_0() ) }, qr/(kk?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->hour_1() ) }, qr/(jj?)/ => sub { my $h = $_[0]->{locale}->prefers_24_hour_time() ? $_[0]->hour() : $_[0]->hour_12(); $_[0]->_zero_padded_number( $1, $h ); }, qr/(mm?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->minute() ) }, qr/(ss?)/ => sub { $_[0]->_zero_padded_number( $1, $_[0]->second() ) }, # The LDML spec is not 100% clear on how to truncate this field, but # this way seems as good as anything. qr/(S+)/ => sub { $_[0]->_format_nanosecs( length($1) ) }, qr/A+/ => sub { ( $_[0]->{local_rd_secs} * 1000 ) + $_[0]->millisecond() }, qr/zzzz/ => sub { $_[0]->time_zone_long_name() }, qr/z{1,3}/ => sub { $_[0]->time_zone_short_name() }, qr/ZZZZZ/ => sub { substr( my $z = DateTime::TimeZone->offset_as_string( $_[0]->offset() ), -2, 0, ':' ); $z; }, qr/ZZZZ/ => sub { $_[0]->time_zone_short_name() . DateTime::TimeZone->offset_as_string( $_[0]->offset() ); }, qr/Z{1,3}/ => sub { DateTime::TimeZone->offset_as_string( $_[0]->offset() ) }, qr/vvvv/ => sub { $_[0]->time_zone_long_name() }, qr/v{1,3}/ => sub { $_[0]->time_zone_short_name() }, qr/VVVV/ => sub { $_[0]->time_zone_long_name() }, qr/V{1,3}/ => sub { $_[0]->time_zone_short_name() }, ); sub _zero_padded_number { my $self = shift; my $size = length shift; my $val = shift; return sprintf( "%0${size}d", $val ); } sub format_cldr { my $self = shift; # make a copy or caller's scalars get munged my @p = @_; my @r; foreach my $p (@p) { $p =~ s/\G (?: '((?:[^']|'')*)' # quote escaped bit of text # it needs to end with one # quote not followed by # another | (([a-zA-Z])\3*) # could be a pattern | (.) # anything else ) / defined $1 ? $1 : defined $2 ? $self->_cldr_pattern($2) : defined $4 ? $4 : undef # should never get here /sgex; $p =~ s/\'\'/\'/g; return $p unless wantarray; push @r, $p; } return @r; } sub _cldr_pattern { my $self = shift; my $pattern = shift; ## no critic (ControlStructures::ProhibitCStyleForLoops) for ( my $i = 0; $i < @patterns; $i += 2 ) { if ( $pattern =~ /$patterns[$i]/ ) { my $sub = $patterns[ $i + 1 ]; return $self->$sub(); } } return $pattern; } } sub _format_nanosecs { my $self = shift; my $precision = @_ ? shift : 9; my $divide_by = 10**( 9 - $precision ); return sprintf( '%0' . $precision . 'u', floor( $self->{rd_nanosecs} / $divide_by ) ); } sub epoch { my $self = shift; return $self->{utc_c}{epoch} if exists $self->{utc_c}{epoch}; return $self->{utc_c}{epoch} = ( $self->{utc_rd_days} - 719163 ) * SECONDS_PER_DAY + $self->{utc_rd_secs}; } sub hires_epoch { my $self = shift; my $epoch = $self->epoch; return undef unless defined $epoch; my $nano = $self->{rd_nanosecs} / MAX_NANOSECONDS; return $epoch + $nano; } sub is_finite {1} sub is_infinite {0} # added for benefit of DateTime::TimeZone sub utc_year { $_[0]->{utc_year} } # returns a result that is relative to the first datetime sub subtract_datetime { my $dt1 = shift; my $dt2 = shift; $dt2 = $dt2->clone->set_time_zone( $dt1->time_zone ) unless $dt1->time_zone eq $dt2->time_zone; # We only want a negative duration if $dt2 > $dt1 ($self) my ( $bigger, $smaller, $negative ) = ( $dt1 >= $dt2 ? ( $dt1, $dt2, 0 ) : ( $dt2, $dt1, 1 ) ); my $is_floating = $dt1->time_zone->is_floating && $dt2->time_zone->is_floating; my $minute_length = 60; unless ($is_floating) { my ( $utc_rd_days, $utc_rd_secs ) = $smaller->utc_rd_values; if ( $utc_rd_secs >= 86340 && !$is_floating ) { # If the smaller of the two datetimes occurs in the last # UTC minute of the UTC day, then that minute may not be # 60 seconds long. If we need to subtract a minute from # the larger datetime's minutes count in order to adjust # the seconds difference to be positive, we need to know # how long that minute was. If one of the datetimes is # floating, we just assume a minute is 60 seconds. $minute_length = $dt1->_day_length($utc_rd_days) - 86340; } } # This is a gross hack that basically figures out if the bigger of # the two datetimes is the day of a DST change. If it's a 23 hour # day (switching _to_ DST) then we subtract 60 minutes from the # local time. If it's a 25 hour day then we add 60 minutes to the # local time. # # This produces the most "intuitive" results, though there are # still reversibility problems with the resultant duration. # # However, if the two objects are on the same (local) date, and we # are not crossing a DST change, we don't want to invoke the hack # - see 38local-subtract.t my $bigger_min = $bigger->hour * 60 + $bigger->minute; if ( $bigger->time_zone->has_dst_changes && $bigger->is_dst != $smaller->is_dst ) { $bigger_min -= 60 # it's a 23 hour (local) day if ( $bigger->is_dst && do { my $prev_day = try { $bigger->clone->subtract( days => 1 ) }; $prev_day && !$prev_day->is_dst ? 1 : 0; } ); $bigger_min += 60 # it's a 25 hour (local) day if ( !$bigger->is_dst && do { my $prev_day = try { $bigger->clone->subtract( days => 1 ) }; $prev_day && $prev_day->is_dst ? 1 : 0; } ); } my ( $months, $days, $minutes, $seconds, $nanoseconds ) = $dt1->_adjust_for_positive_difference( $bigger->year * 12 + $bigger->month, $smaller->year * 12 + $smaller->month, $bigger->day, $smaller->day, $bigger_min, $smaller->hour * 60 + $smaller->minute, $bigger->second, $smaller->second, $bigger->nanosecond, $smaller->nanosecond, $minute_length, # XXX - using the smaller as the month length is # somewhat arbitrary, we could also use the bigger - # either way we have reversibility problems $dt1->_month_length( $smaller->year, $smaller->month ), ); if ($negative) { for ( $months, $days, $minutes, $seconds, $nanoseconds ) { # Some versions of Perl can end up with -0 if we do "0 * -1"!! $_ *= -1 if $_; } } return $dt1->duration_class->new( months => $months, days => $days, minutes => $minutes, seconds => $seconds, nanoseconds => $nanoseconds, ); } sub _adjust_for_positive_difference { ## no critic (Subroutines::ProhibitManyArgs) my ( $self, $month1, $month2, $day1, $day2, $min1, $min2, $sec1, $sec2, $nano1, $nano2, $minute_length, $month_length, ) = @_; if ( $nano1 < $nano2 ) { $sec1--; $nano1 += MAX_NANOSECONDS; } if ( $sec1 < $sec2 ) { $min1--; $sec1 += $minute_length; } # A day always has 24 * 60 minutes, though the minutes may vary in # length. if ( $min1 < $min2 ) { $day1--; $min1 += 24 * 60; } if ( $day1 < $day2 ) { $month1--; $day1 += $month_length; } return ( $month1 - $month2, $day1 - $day2, $min1 - $min2, $sec1 - $sec2, $nano1 - $nano2, ); } sub subtract_datetime_absolute { my $self = shift; my $dt = shift; my $utc_rd_secs1 = $self->utc_rd_as_seconds; $utc_rd_secs1 += $self->_accumulated_leap_seconds( $self->{utc_rd_days} ) if !$self->time_zone->is_floating; my $utc_rd_secs2 = $dt->utc_rd_as_seconds; $utc_rd_secs2 += $self->_accumulated_leap_seconds( $dt->{utc_rd_days} ) if !$dt->time_zone->is_floating; my $seconds = $utc_rd_secs1 - $utc_rd_secs2; my $nanoseconds = $self->nanosecond - $dt->nanosecond; if ( $nanoseconds < 0 ) { $seconds--; $nanoseconds += MAX_NANOSECONDS; } return $self->duration_class->new( seconds => $seconds, nanoseconds => $nanoseconds, ); } sub delta_md { my $self = shift; my $dt = shift; my ( $smaller, $bigger ) = sort $self, $dt; my ( $months, $days, undef, undef, undef ) = $dt->_adjust_for_positive_difference( $bigger->year * 12 + $bigger->month, $smaller->year * 12 + $smaller->month, $bigger->day, $smaller->day, 0, 0, 0, 0, 0, 0, 60, $smaller->_month_length( $smaller->year, $smaller->month ), ); return $self->duration_class->new( months => $months, days => $days ); } sub delta_days { my $self = shift; my $dt = shift; my $days = abs( ( $self->local_rd_values )[0] - ( $dt->local_rd_values )[0] ); $self->duration_class->new( days => $days ); } sub delta_ms { my $self = shift; my $dt = shift; my ( $smaller, $greater ) = sort $self, $dt; my $days = int( $greater->jd - $smaller->jd ); my $dur = $greater->subtract_datetime($smaller); my %p; $p{hours} = $dur->hours + ( $days * 24 ); $p{minutes} = $dur->minutes; $p{seconds} = $dur->seconds; return $self->duration_class->new(%p); } sub _add_overload { my ( $dt, $dur, $reversed ) = @_; if ($reversed) { ( $dur, $dt ) = ( $dt, $dur ); } unless ( DateTime::Helpers::isa( $dur, 'DateTime::Duration' ) ) { my $class = ref $dt; my $dt_string = overload::StrVal($dt); Carp::croak( "Cannot add $dur to a $class object ($dt_string).\n" . ' Only a DateTime::Duration object can ' . " be added to a $class object." ); } return $dt->clone->add_duration($dur); } sub _subtract_overload { my ( $date1, $date2, $reversed ) = @_; if ($reversed) { ( $date2, $date1 ) = ( $date1, $date2 ); } if ( DateTime::Helpers::isa( $date2, 'DateTime::Duration' ) ) { my $new = $date1->clone; $new->add_duration( $date2->inverse ); return $new; } elsif ( DateTime::Helpers::isa( $date2, 'DateTime' ) ) { return $date1->subtract_datetime($date2); } else { my $class = ref $date1; my $dt_string = overload::StrVal($date1); Carp::croak( "Cannot subtract $date2 from a $class object ($dt_string).\n" . ' Only a DateTime::Duration or DateTime object can ' . " be subtracted from a $class object." ); } } sub add { my $self = shift; return $self->add_duration( $self->_duration_object_from_args(@_) ); } sub subtract { my $self = shift; my %eom; if ( @_ % 2 == 0 ) { my %p = @_; $eom{end_of_month} = delete $p{end_of_month} if exists $p{end_of_month}; } my $dur = $self->_duration_object_from_args(@_)->inverse(%eom); return $self->add_duration($dur); } # Syntactic sugar for add and subtract: use a duration object if it's # supplied, otherwise build a new one from the arguments. sub _duration_object_from_args { my $self = shift; return $_[0] if @_ == 1 && blessed( $_[0] ) && $_[0]->isa( $self->duration_class ); return $self->duration_class->new(@_); } sub subtract_duration { return $_[0]->add_duration( $_[1]->inverse ) } { my $validator = validation_for( name => '_check_add_duration_params', name_is_optional => 1, params => [ { type => t('Duration') }, ], ); ## no critic (Subroutines::ProhibitExcessComplexity) sub add_duration { my $self = shift; my ($dur) = $validator->(@_); # simple optimization return $self if $dur->is_zero; my %deltas = $dur->deltas; # This bit isn't quite right since DateTime::Infinite::Future - # infinite duration should NaN foreach my $val ( values %deltas ) { my $inf; if ( $val == INFINITY ) { $inf = DateTime::Infinite::Future->new; } elsif ( $val == NEG_INFINITY ) { $inf = DateTime::Infinite::Past->new; } if ($inf) { %$self = %$inf; bless $self, ref $inf; return $self; } } return $self if $self->is_infinite; if ( $deltas{days} ) { $self->{local_rd_days} += $deltas{days}; $self->{utc_year} += int( $deltas{days} / 365 ) + 1; } if ( $deltas{months} ) { # For preserve mode, if it is the last day of the month, make # it the 0th day of the following month (which then will # normalize back to the last day of the new month). my ( $y, $m, $d ) = ( $dur->is_preserve_mode ? $self->_rd2ymd( $self->{local_rd_days} + 1 ) : $self->_rd2ymd( $self->{local_rd_days} ) ); $d -= 1 if $dur->is_preserve_mode; if ( !$dur->is_wrap_mode && $d > 28 ) { # find the rd for the last day of our target month $self->{local_rd_days} = $self->_ymd2rd( $y, $m + $deltas{months} + 1, 0 ); # what day of the month is it? (discard year and month) my $last_day = ( $self->_rd2ymd( $self->{local_rd_days} ) )[2]; # if our original day was less than the last day, # use that instead $self->{local_rd_days} -= $last_day - $d if $last_day > $d; } else { $self->{local_rd_days} = $self->_ymd2rd( $y, $m + $deltas{months}, $d ); } $self->{utc_year} += int( $deltas{months} / 12 ) + 1; } if ( $deltas{days} || $deltas{months} ) { $self->_calc_utc_rd; $self->_handle_offset_modifier( $self->second ); } if ( $deltas{minutes} ) { $self->{utc_rd_secs} += $deltas{minutes} * 60; # This intentionally ignores leap seconds $self->_normalize_tai_seconds( $self->{utc_rd_days}, $self->{utc_rd_secs} ); } if ( $deltas{seconds} || $deltas{nanoseconds} ) { $self->{utc_rd_secs} += $deltas{seconds}; if ( $deltas{nanoseconds} ) { $self->{rd_nanosecs} += $deltas{nanoseconds}; $self->_normalize_nanoseconds( $self->{utc_rd_secs}, $self->{rd_nanosecs} ); } $self->_normalize_seconds; # This might be some big number much bigger than 60, but # that's ok (there are tests in 19leap_second.t to confirm # that) $self->_handle_offset_modifier( $self->second + $deltas{seconds} ); } my $new = ( ref $self )->from_object( object => $self, locale => $self->{locale}, ( $self->{formatter} ? ( formatter => $self->{formatter} ) : () ), ); %$self = %$new; return $self; } } sub _compare_overload { # note: $_[1]->compare( $_[0] ) is an error when $_[1] is not a # DateTime (such as the INFINITY value) return undef unless defined $_[1]; return $_[2] ? -$_[0]->compare( $_[1] ) : $_[0]->compare( $_[1] ); } sub _string_compare_overload { my ( $dt1, $dt2, $flip ) = @_; # One is a DateTime object, one isn't. Just stringify and compare. if ( !DateTime::Helpers::can( $dt2, 'utc_rd_values' ) ) { my $sign = $flip ? -1 : 1; return $sign * ( "$dt1" cmp "$dt2" ); } else { my $meth = $dt1->can('_compare_overload'); goto $meth; } } sub compare { shift->_compare( @_, 0 ); } sub compare_ignore_floating { shift->_compare( @_, 1 ); } sub _compare { my ( undef, $dt1, $dt2, $consistent ) = ref $_[0] ? ( undef, @_ ) : @_; return undef unless defined $dt2; if ( !ref $dt2 && ( $dt2 == INFINITY || $dt2 == NEG_INFINITY ) ) { return $dt1->{utc_rd_days} <=> $dt2; } unless ( DateTime::Helpers::can( $dt1, 'utc_rd_values' ) && DateTime::Helpers::can( $dt2, 'utc_rd_values' ) ) { my $dt1_string = overload::StrVal($dt1); my $dt2_string = overload::StrVal($dt2); Carp::croak( 'A DateTime object can only be compared to' . " another DateTime object ($dt1_string, $dt2_string)." ); } if ( !$consistent && DateTime::Helpers::can( $dt1, 'time_zone' ) && DateTime::Helpers::can( $dt2, 'time_zone' ) ) { my $is_floating1 = $dt1->time_zone->is_floating; my $is_floating2 = $dt2->time_zone->is_floating; if ( $is_floating1 && !$is_floating2 ) { $dt1 = $dt1->clone->set_time_zone( $dt2->time_zone ); } elsif ( $is_floating2 && !$is_floating1 ) { $dt2 = $dt2->clone->set_time_zone( $dt1->time_zone ); } } my @dt1_components = $dt1->utc_rd_values; my @dt2_components = $dt2->utc_rd_values; foreach my $i ( 0 .. 2 ) { return $dt1_components[$i] <=> $dt2_components[$i] if $dt1_components[$i] != $dt2_components[$i]; } return 0; } sub _string_equals_overload { my ( $class, $dt1, $dt2 ) = ref $_[0] ? ( undef, @_ ) : @_; if ( !DateTime::Helpers::can( $dt2, 'utc_rd_values' ) ) { return "$dt1" eq "$dt2"; } $class ||= ref $dt1; return !$class->compare( $dt1, $dt2 ); } sub _string_not_equals_overload { return !_string_equals_overload(@_); } sub _normalize_nanoseconds { use integer; # seconds, nanoseconds if ( $_[2] < 0 ) { my $overflow = 1 + $_[2] / MAX_NANOSECONDS; $_[2] += $overflow * MAX_NANOSECONDS; $_[1] -= $overflow; } elsif ( $_[2] >= MAX_NANOSECONDS ) { my $overflow = $_[2] / MAX_NANOSECONDS; $_[2] -= $overflow * MAX_NANOSECONDS; $_[1] += $overflow; } } { my $validator = validation_for( name => '_check_set_params', name_is_optional => 1, params => { year => { type => t('Year'), optional => 1, }, month => { type => t('Month'), optional => 1, }, day => { type => t('DayOfMonth'), optional => 1, }, hour => { type => t('Hour'), optional => 1, }, minute => { type => t('Minute'), optional => 1, }, second => { type => t('Second'), optional => 1, }, nanosecond => { type => t('Nanosecond'), optional => 1, }, locale => { type => t('Locale'), optional => 1, }, }, ); ## no critic (NamingConventions::ProhibitAmbiguousNames) sub set { my $self = shift; my %p = $validator->(@_); if ( $p{locale} ) { carp 'You passed a locale to the set() method.' . ' You should use set_locale() instead, as using set() may alter the local time near a DST boundary.'; } my $new_dt = $self->_new_from_self(%p); %$self = %$new_dt; return $self; } } sub set_year { $_[0]->set( year => $_[1] ) } sub set_month { $_[0]->set( month => $_[1] ) } sub set_day { $_[0]->set( day => $_[1] ) } sub set_hour { $_[0]->set( hour => $_[1] ) } sub set_minute { $_[0]->set( minute => $_[1] ) } sub set_second { $_[0]->set( second => $_[1] ) } sub set_nanosecond { $_[0]->set( nanosecond => $_[1] ) } # These two are special cased because ... if the local time is the hour of a # DST change where the same local time occurs twice then passing it through # _new() can actually change the underlying UTC time, which is bad. { my $validator = validation_for( name => '_check_set_locale_params', name_is_optional => 1, params => [ { type => t( 'Maybe', of => t('Locale') ) }, ], ); sub set_locale { my $self = shift; my ($locale) = $validator->(@_); $self->_set_locale($locale); return $self; } } { my $validator = validation_for( name => '_check_set_formatter_params', name_is_optional => 1, params => [ { type => t( 'Maybe', of => t('Formatter') ) }, ], ); sub set_formatter { my $self = shift; my ($formatter) = $validator->(@_); $self->{formatter} = $formatter; return $self; } } { my %TruncateDefault = ( month => 1, day => 1, hour => 0, minute => 0, second => 0, nanosecond => 0, ); my $validator = validation_for( name => '_check_truncate_params', name_is_optional => 1, params => { to => { type => t('TruncationLevel') }, }, ); my $re = join '|', 'year', 'week', 'local_week', 'quarter', grep { $_ ne 'nanosecond' } keys %TruncateDefault; my $spec = { to => { regex => qr/^(?:$re)$/ } }; ## no critic (Subroutines::ProhibitBuiltinHomonyms) sub truncate { my $self = shift; my %p = $validator->(@_); my %new; if ( $p{to} eq 'week' || $p{to} eq 'local_week' ) { my $first_day_of_week = ( $p{to} eq 'local_week' ) ? $self->{locale}->first_day_of_week : 1; my $day_diff = ( $self->day_of_week - $first_day_of_week ) % 7; if ($day_diff) { $self->add( days => -1 * $day_diff ); } # This can fail if the truncate ends up giving us an invalid local # date time. If that happens we need to reverse the addition we # just did. See https://rt.cpan.org/Ticket/Display.html?id=93347. try { $self->truncate( to => 'day' ); } catch { $self->add( days => $day_diff ); die $_; }; } elsif ( $p{to} eq 'quarter' ) { %new = ( year => $self->year, month => int( ( $self->month - 1 ) / 3 ) * 3 + 1, day => 1, hour => 0, minute => 0, second => 0, nanosecond => 0, ); } else { my $truncate; foreach my $f (qw( year month day hour minute second nanosecond )) { $new{$f} = $truncate ? $TruncateDefault{$f} : $self->$f(); $truncate = 1 if $p{to} eq $f; } } my $new_dt = $self->_new_from_self( %new, _skip_validation => 1 ); %$self = %$new_dt; return $self; } } sub set_time_zone { my ( $self, $tz ) = @_; if ( ref $tz ) { # This is a bit of a hack but it works because time zone objects # are singletons, and if it doesn't work all we lose is a little # bit of speed. return $self if $self->{tz} eq $tz; } else { return $self if $self->{tz}->name() eq $tz; } my $was_floating = $self->{tz}->is_floating; my $old_tz = $self->{tz}; $self->{tz} = ref $tz ? $tz : DateTime::TimeZone->new( name => $tz ); $self->_handle_offset_modifier( $self->second, 1 ); my $e; try { # if it either was or now is floating (but not both) if ( $self->{tz}->is_floating xor $was_floating ) { $self->_calc_utc_rd; } elsif ( !$was_floating ) { $self->_calc_local_rd; } } catch { $e = $_; }; # If we can't recalc the RD values then we shouldn't keep the new TZ. RT # #83940 if ($e) { $self->{tz} = $old_tz; die $e; } return $self; } sub STORABLE_freeze { my $self = shift; my $serialized = q{}; foreach my $key ( qw( utc_rd_days utc_rd_secs rd_nanosecs ) ) { $serialized .= "$key:$self->{$key}|"; } # not used yet, but may be handy in the future. $serialized .= 'version:' . ( $DateTime::VERSION || 'git' ); # Formatter needs to be returned as a reference since it may be # undef or a class name, and Storable will complain if extra # return values aren't refs return $serialized, $self->{locale}, $self->{tz}, \$self->{formatter}; } sub STORABLE_thaw { my $self = shift; shift; my $serialized = shift; my %serialized = map { split /:/ } split /\|/, $serialized; my ( $locale, $tz, $formatter ); # more recent code version if (@_) { ( $locale, $tz, $formatter ) = @_; } else { $tz = DateTime::TimeZone->new( name => delete $serialized{tz} ); $locale = DateTime::Locale->load( delete $serialized{locale} ); } delete $serialized{version}; my $object = bless { utc_vals => [ $serialized{utc_rd_days}, $serialized{utc_rd_secs}, $serialized{rd_nanosecs}, ], tz => $tz, }, 'DateTime::_Thawed'; my %formatter = defined $$formatter ? ( formatter => $$formatter ) : (); my $new = ( ref $self )->from_object( object => $object, locale => $locale, %formatter, ); %$self = %$new; return $self; } ## no critic (Modules::ProhibitMultiplePackages) package # hide from PAUSE DateTime::_Thawed; sub utc_rd_values { @{ $_[0]->{utc_vals} } } sub time_zone { $_[0]->{tz} } 1; # ABSTRACT: A date and time object for Perl __END__ =pod =encoding UTF-8 =head1 NAME DateTime - A date and time object for Perl =head1 VERSION version 1.46 =head1 SYNOPSIS use DateTime; $dt = DateTime->new( year => 1964, month => 10, day => 16, hour => 16, minute => 12, second => 47, nanosecond => 500000000, time_zone => 'Asia/Taipei', ); $dt = DateTime->from_epoch( epoch => $epoch ); $dt = DateTime->now; # same as ( epoch => time() ) $year = $dt->year; $month = $dt->month; # 1-12 $day = $dt->day; # 1-31 $dow = $dt->day_of_week; # 1-7 (Monday is 1) $hour = $dt->hour; # 0-23 $minute = $dt->minute; # 0-59 $second = $dt->second; # 0-61 (leap seconds!) $doy = $dt->day_of_year; # 1-366 (leap years) $doq = $dt->day_of_quarter; # 1.. $qtr = $dt->quarter; # 1-4 # all of the start-at-1 methods above have corresponding start-at-0 # methods, such as $dt->day_of_month_0, $dt->month_0 and so on $ymd = $dt->ymd; # 2002-12-06 $ymd = $dt->ymd('/'); # 2002/12/06 $mdy = $dt->mdy; # 12-06-2002 $mdy = $dt->mdy('/'); # 12/06/2002 $dmy = $dt->dmy; # 06-12-2002 $dmy = $dt->dmy('/'); # 06/12/2002 $hms = $dt->hms; # 14:02:29 $hms = $dt->hms('!'); # 14!02!29 $is_leap = $dt->is_leap_year; # these are localizable, see Locales section $month_name = $dt->month_name; # January, February, ... $month_abbr = $dt->month_abbr; # Jan, Feb, ... $day_name = $dt->day_name; # Monday, Tuesday, ... $day_abbr = $dt->day_abbr; # Mon, Tue, ... # May not work for all possible datetime, see the docs on this # method for more details. $epoch_time = $dt->epoch; $dt2 = $dt + $duration_object; $dt3 = $dt - $duration_object; $duration_object = $dt - $dt2; $dt->set( year => 1882 ); $dt->set_time_zone( 'America/Chicago' ); $dt->set_formatter( $formatter ); =head1 DESCRIPTION DateTime is a class for the representation of date/time combinations, and is part of the Perl DateTime project. For details on this project please see L. The DateTime site has a FAQ which may help answer many "how do I do X?" questions. The FAQ is at L. It represents the Gregorian calendar, extended backwards in time before its creation (in 1582). This is sometimes known as the "proleptic Gregorian calendar". In this calendar, the first day of the calendar (the epoch), is the first day of year 1, which corresponds to the date which was (incorrectly) believed to be the birth of Jesus Christ. The calendar represented does have a year 0, and in that way differs from how dates are often written using "BCE/CE" or "BC/AD". For infinite datetimes, please see the L module. =head1 USAGE =head2 0-based Versus 1-based Numbers The DateTime.pm module follows a simple logic for determining whether or not a given number is 0-based or 1-based. Month, day of month, day of week, and day of year are 1-based. Any method that is 1-based also has an equivalent 0-based method ending in "_0". So for example, this class provides both C and C methods. The C method still treats Monday as the first day of the week. All I