DateTime-TimeZone

 view release on metacpan or  search on metacpan

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

package DateTime::TimeZone;

use 5.008004;

use strict;
use warnings;
use namespace::autoclean;

our $VERSION = '2.68';

# Note that while we make use of DateTime::Duration in this module if we
# actually try to load it here all hell breaks loose with circular
# dependencies.
use DateTime::TimeZone::Catalog;
use DateTime::TimeZone::Floating;
use DateTime::TimeZone::Local;
use DateTime::TimeZone::OffsetOnly;
use DateTime::TimeZone::OlsonDB::Change;
use DateTime::TimeZone::UTC;
use Module::Runtime qw( require_module );
use Params::ValidationCompiler 0.13 qw( validation_for );
use Specio::Library::Builtins;
use Specio::Library::String;
use Try::Tiny;

## no critic (ValuesAndExpressions::ProhibitConstantPragma)
use constant INFINITY     => 100**1000;
use constant NEG_INFINITY => -1 * ( 100**1000 );

# the offsets for each span element
use constant UTC_START   => 0;
use constant UTC_END     => 1;
use constant LOCAL_START => 2;
use constant LOCAL_END   => 3;
use constant OFFSET      => 4;
use constant IS_DST      => 5;
use constant SHORT_NAME  => 6;

my %SpecialName = map { $_ => 1 }
    qw( EST MST HST CET EET MET WET EST5EDT CST6CDT MST7MDT PST8PDT );

{
    my $validator = validation_for(
        name             => '_check_new_params',
        name_is_optional => 1,
        params           => {
            name => {
                type => t('NonEmptyStr'),
            },
        },
    );

    sub new {
        shift;
        my %p = $validator->(@_);

        if ( exists $DateTime::TimeZone::Catalog::LINKS{ $p{name} } ) {
            $p{name} = $DateTime::TimeZone::Catalog::LINKS{ $p{name} };
        }
        elsif ( exists $DateTime::TimeZone::Catalog::LINKS{ uc $p{name} } ) {
            $p{name} = $DateTime::TimeZone::Catalog::LINKS{ uc $p{name} };
        }

        unless ( $p{name} =~ m{/}
            || $SpecialName{ $p{name} } ) {
            if ( $p{name} eq 'floating' ) {
                return DateTime::TimeZone::Floating->instance;
            }

            if ( $p{name} eq 'local' ) {
                return DateTime::TimeZone::Local->TimeZone();
            }

            if ( $p{name} eq 'UTC' || $p{name} eq 'Z' ) {
                return DateTime::TimeZone::UTC->instance;
            }

            return DateTime::TimeZone::OffsetOnly->new( offset => $p{name} );
        }

        if ( $p{name} =~ m{Etc/(?:GMT|UTC)(\+|-)(\d{1,2})}i ) {

            # Etc/GMT+4 is actually UTC-4. For more info, see
            # https://data.iana.org/time-zones/tzdb/etcetera
            my $sign  = $1 eq '-' ? '+' : '-';
            my $hours = $2;
            die "The timezone '$p{name}' is an invalid name.\n"
                unless $hours <= 14;
            return DateTime::TimeZone::OffsetOnly->new(
                offset => "${sign}${hours}:00" );
        }

        my $subclass = $p{name};
        $subclass =~ s{/}{::}g;
        $subclass =~ s/-(\d)/_Minus$1/;
        $subclass =~ s/\+/_Plus/;
        $subclass =~ s/-/_/g;

        my $real_class = "DateTime::TimeZone::$subclass";



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