Astro-App-Satpass2

 view release on metacpan or  search on metacpan

lib/Astro/App/Satpass2/FormatTime/DateTime.pm  view on Meta::CPAN

package Astro::App::Satpass2::FormatTime::DateTime;

use 5.008;

use strict;
use warnings;

use parent qw{
    Astro::App::Satpass2::FormatTime
};

use Astro::App::Satpass2::Utils qw{
    back_end __back_end_class_name_of_record
    has_method load_package
    __parse_class_and_args
    @CARP_NOT
};
use Astro::App::Satpass2::Locale qw{ __preferred };
use DateTime;
use DateTime::TimeZone;

our $VERSION = '0.057';

sub attribute_names {
    my ( $self ) = @_;
    return ( qw{ back_end }, $self->SUPER::attribute_names() );
}

sub _dt_class_and_args {
    my ( $self ) = @_;
    if ( $self->{_back_end} ) {
	return (
	    $self->{_back_end}{class},
	    $self->{_back_end}{arg},
	);
    } else {
	return ( 'DateTime', [] );
    }
}

sub class_name_of_record {
    my ( $self ) = @_;
    return $self->__back_end_class_name_of_record(
	$self->SUPER::class_name_of_record() );
}

sub format_datetime {
    my ( $self, $tplt, $time, $gmt ) = @_;
    $time = $self->__round_time_value( $time );
    if ( has_method( $time, $self->METHOD_USED() ) ) {
	return $self->__format_datetime( $time, $tplt );
    } else {
	ref $time
	    and $self->wail( 'Unsupported time specification' );
	my ( $class, $dt_arg ) = $self->_dt_class_and_args();
	my $dt = $class->from_epoch(
	    epoch	=> $time,
	    time_zone	=> $self->_get_zone( $gmt ),
	    locale	=> scalar __preferred(),
	    @{ $dt_arg },
	);
	return $self->__format_datetime( $dt, $tplt );
    }
}

sub init {
    my ( $self, %arg ) = @_;
    exists $arg{back_end}
	or $arg{back_end} = undef;
    return $self->SUPER::init( %arg );
}

{

    my $zone_gmt;
    my $zone_local;

    sub tz {
	my ( $self, @args ) = @_;

	if ( @args ) {
	    my $zone = $args[0];
	    if ( defined $zone and $zone ne '' ) {
		if ( ! DateTime::TimeZone->is_valid_name( $zone ) ) {
		    my $zed = uc $zone;
		    DateTime::TimeZone->is_valid_name( $zed )
			or $self->wail(
			    "'$zone' is not a valid time zone name" );
		    $zone = $zed;
		}
		$self->{_tz_obj} = DateTime::TimeZone->new(
		    name => $zone );
	    } else {
		$self->{_tz_obj} = $zone_local ||=
		    DateTime::TimeZone->new( name => 'local' );
	    }
	    return $self->SUPER::tz( $zone );

	} else {
	    return $self->SUPER::tz();
	}
    }

    sub _get_zone {
	my ( $self, $gmt ) = @_;
	defined $gmt
	    or $gmt = $self->gmt();

	$gmt and return ( $zone_gmt ||= DateTime::TimeZone->new(
	    name => 'UTC' ) );

	$self->{_tz_obj} and return $self->{_tz_obj};

	my $tz = $self->tz();
	if ( defined $tz && $tz ne '' ) {
	    return ( $self->{_tz_obj} = DateTime::TimeZone->new(
		    name => $tz ) );
	} else {
	    return ( $self->{_tz_obj} = $zone_local ||=
		DateTime::TimeZone->new( name => 'local' ) );
	}

    }

}

sub __format_datetime_width_adjust_object {
    my ( $self, $obj, $name, $val, $gmt ) = @_;

    if ( $obj ) {
	$obj->set( $name => $val );
    } else {
	my ( $class, $dt_arg ) = $self->_dt_class_and_args();
	$obj = $class->new(
	    time_zone	=> $self->_get_zone( $gmt ),
	    locale	=> scalar __preferred(),
	    $name	=> $val,
	    ( 'year' eq $name ? () : ( year	=> 2020 ) ),
	    @{ $dt_arg },
	);
    }

    return $obj;
}

# my $mod_fmt = $self->__preprocess_strftime_format( $dt_obj, $fmt )
# Preprocess out all the extensions to the strftime format.
# What we're handling here is things of the form %{name:modifiers},
# where the colon and modifiers are optional.
# The modifier is a series of single-character flags followed by a field
# width. The flags are:
#  '-' - left-justify
#  '0' - zero-pad (ineffective if '-' specified)
#  't' - truncate to field width
sub __preprocess_strftime_format {
    my ( $self, $dt_obj, $fmt ) = @_;
    caller->isa( __PACKAGE__ )
	or $self->weep(
	'__preprocess_strftime_format() is private to Astro-App-Satpass2' );
    $fmt =~ s< ( % [{] ( \w+ | % ) (?: : ( [-0t]* ) ( [0-9]+ ) )? [}] ) >



( run in 1.343 second using v1.01-cache-2.11-cpan-98e64b0badf )