Module-Generic
view release on metacpan or search on metacpan
lib/Module/Generic/DateTime.pm view on Meta::CPAN
undef( $self->{dt} ) if( defined( $self->{dt} ) );
# For non-object context, we need to call cleanup to ensure there is no leftover
my $class = ref( $self );
my $err_key = $class;
my $repo = Module::Generic::Global->new( 'local_tz' => $class, key => $err_key );
$repo->cleanup;
return( $self );
};
sub FREEZE
{
my $self = CORE::shift( @_ );
my $serialiser = CORE::shift( @_ ) // '';
my $class = CORE::ref( $self );
my $dt = $self->{dt} || return;
my $tz = $dt->time_zone->name;
my $fmt = $dt->formatter;
my $locale = $dt->locale->code;
my $hash =
{
year => $dt->year,
month => $dt->month,
day => $dt->day,
hour => $dt->hour,
minute => $dt->minute,
second => $dt->second,
nanosecond => $dt->nanosecond,
};
$hash->{time_zone} = $tz if( $tz );
$hash->{formatter} = $fmt if( $fmt );
$hash->{locale} = $locale if( $locale );
# Return an array reference rather than a list so this works with Sereal and CBOR
# On or before Sereal version 4.023, Sereal did not support multiple values returned
if( $serialiser eq 'Sereal' )
{
require Sereal::Encoder;
require version;
if( version->parse( Sereal::Encoder->VERSION ) <= version->parse( '4.023' ) )
{
CORE::return( [$class, $hash] );
}
}
# But Storable want a list with the first element being the serialised element
CORE::return( $class, $hash );
}
sub STORABLE_freeze { CORE::return( CORE::shift->FREEZE( @_ ) ); }
sub STORABLE_thaw { CORE::return( CORE::shift->THAW( @_ ) ); }
sub STORABLE_thaw_post_processing
{
my $obj = shift( @_ );
my @keys = %$obj;
my $class = ref( $obj );
my $hash = {};
@$hash{ @keys } = @$obj{ @keys };
my $self = bless( $hash => $class );
return( $self );
}
# NOTE: CBOR will call the THAW method with the stored classname as first argument, the constant string CBOR as second argument, and all values returned by FREEZE as remaining arguments.
# NOTE: Storable calls it with a blessed object it created followed with $cloning and any other arguments initially provided by STORABLE_freeze
sub THAW
{
my( $self, undef, @args ) = @_;
my $ref = ( CORE::scalar( @args ) == 1 && CORE::ref( $args[0] ) eq 'ARRAY' ) ? CORE::shift( @args ) : \@args;
my $class = ( CORE::defined( $ref ) && CORE::ref( $ref ) eq 'ARRAY' && CORE::scalar( @$ref ) > 1 ) ? CORE::shift( @$ref ) : ( CORE::ref( $self ) || $self );
my $hash = CORE::ref( $ref ) eq 'ARRAY' ? CORE::shift( @$ref ) : {};
my @keys = qw( year month day hour minute second nanosecond time_zone formatter locale );
my $opts = {};
foreach my $prop ( @keys )
{
if( exists( $hash->{ $prop } ) &&
defined( $hash->{ $prop } ) &&
length( $hash->{ $prop } ) )
{
$opts->{ $prop } = $hash->{ $prop };
}
}
local $@;
my $dt = eval
{
require DateTime::Lite;
DateTime::Lite->new( %$opts );
};
if( $@ )
{
require Module::Generic;
warn( "Error thawing the DateTime::Lite object: $@\nParameters used were: ", Module::Generic->dump( $opts ) ) if( warnings::enabled() );
}
elsif( !defined( $dt ) )
{
warn( "Error thawing the DateTime::Lite object: ", DateTime::Lite->error, "\nParameters used were: ", Module::Generic->dump( $opts ) ) if( warnings::enabled() );
}
my $new;
# Storable pattern requires to modify the object it created rather than returning a new one
if( CORE::ref( $self ) )
{
$self->{dt} = $dt;
$new = $self;
}
else
{
$new = CORE::bless( { dt => $dt } => $class );
}
CORE::return( $new );
}
sub TO_JSON
{
my $self = CORE::shift( @_ );
CORE::return( '' ) if( !$self->{dt} || !Scalar::Util::blessed( $self->{dt} ) );
CORE::return( $self->{dt}->stringify );
}
# NOTE: package Module::Generic::DateTime::Interval
package Module::Generic::DateTime::Interval;
BEGIN
{
use strict;
use warnings;
use parent qw( Module::Generic );
use overload (
'""' => 'as_string',
'bool' => sub{1},
'+' => '__add_overload',
'-' => '__subtract_overload',
'*' => '__multiply_overload',
'<=>' => '__compare_overload',
'cmp' => '__compare_overload',
fallback => 1,
);
use DateTime::Lite;
use Scalar::Util ();
use Wanted;
};
sub new
{
my $this = shift( @_ );
my $dur = shift( @_ ) || return;
return( bless( { interval => $dur->clone } => ( ref( $this ) || $this ) )->init( @_ ) );
}
# This class does not convert to an HASH
sub as_hash { return( $_[0] ); }
sub as_string
{
my $self = shift( @_ );
return( $self->{interval}->in_units( 'seconds' ) );
}
sub dump
{
my $self = shift( @_ );
my @info = $self->{interval}->in_units( qw( years months weeks days hours minutes seconds nanoseconds ) );
my $tmpl = <<EOT;
Years ... %d
Months .. %d
Weeks ... %d
Days .... %d
Hours ... %d
Minutes . %d
( run in 0.492 second using v1.01-cache-2.11-cpan-39bf76dae61 )