die( "\$other (", overload::StrVal( $other// ''), ") is not a number, a DateTime, or a DateTime::Duration object!\n") if( !defined( $v) || $v!~ /^(?:$RE{num}{real}|$RE{num}{int})$/ );
my$new_dt;
if( $opeq '-')
{
if( $swap)
{
# try-catch
local$@;
my( $clone, $ts);
eval
{
$clone= $dt1->clone;
$ts= $clone->epoch;
};
if( $@ )
{
die( "Error cloning and getting epoch value for DateTime object: $@");
}
if( !defined( $HAS_LOCAL_TZ) )
{
# try-catch
local$@;
eval
{
$clone->set_time_zone( 'local');
$HAS_LOCAL_TZ= 1;
};
if( $@ )
{
$clone->set_time_zone( 'UTC');
$HAS_LOCAL_TZ= 0;
warn( "Your system is missing key timezone components. ${class} is reverting to UTC instead of local time zone.\n") if( warnings::enabled() );
# 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
Module::Generic::DateTime - A DateTime wrapper for enhanced features
=head1 SYNOPSIS
use Module::Generic::DateTime;
my $dt = DateTime->new;
my $gdt = Module::Generic::DateTime->new( $dt );
# or directly will instantiate a default DateTime value based on DateTime->now
my $gdt = Module::Generic::DateTime->new;
# Now you can do operations that are not normally possible with DateTime
# Compare a dt object with a unix timestamp
if( $gdt > time() )
{
# do something
}
elsif( $gdt < '2020-03-01 07:12:10+0900' )
{
# do something
}
# and of course, comparison with other dt works as before
elsif( $gdt >= $dt )
{
# do something
}
# Remove 10 seconds from time object
$gdt -= 10;
# Add 5 seconds and get a new object
my $dt2 = $gdt + 5;
# Get the difference as an interval between two objects
my $interval = $dt1 - $dt2;
# DateTime::Duration are represented by Module::Generic::DateTime::Interval
# and extra manipulations are possible
# Add 7 seconds
$int += 7;
# Change the days
$int->days( 5 );
# or using lvalue
$int->days = 5;
# or multiply everything (years, months, weeks, days, hours, minutes, seconds and nanoseconds) in the interval by 2
$int *= 2
# Multiply one interval by another:
my $new_interval = $int1 * $int2;
# or multiply with assignment
$int1 *= $int2;
# Then add the interval to the datetime object
$dt += $int;
=head1 VERSION
v0.5.0
=head1 DESCRIPTION
L<Module::Generic::DateTime> is a thin wrapper around L<DateTime> to provide additional features as exemplified above.
It also enables the L<DateTime> object to be thawed and frozen and converted to L<JSON> with the respective methods C<STORABLE_freeze>, C<STORABLE_thaw>, C<TO_JSON>
All other method calls not in this API are passed to L<DateTime> using C<AUTOLOAD> with the added benefit that, if a method called triggers a fatal exception, it is caught using L<Nice::Try> try-catch block and an L<error|Module::Generic/error> is set and C<return> is returned instead.
=head1 CONSTRUCTOR
=head2 new
Provided with an optional L<DateTime> object and this returns a new instance of L<Module::Generic::DateTime>.
If no L<DateTime> object was provided, this will instantiate one implicitly and set the formatter to stringify it to an iso8601 string, such as: C<2022-03-08T14:22:10+0000>. By default the instantiated L<DateTime> object use the default time zone, which is C<GMT>. You can change the time zone afterward using L<DateTime/set_time_zone>:
$dt->set_time_zone( 'Asia/Tokyo' );
=head2 from_epoch
my $d = Module::Generic::DateTime->from_epoch( epoch => $unix_timestamp );
Instantiate a new L<Module::Generic::DateTime> using the L<DateTime> method C<from_epoch>. Any parameters are passed through to L<DateTime/from_epoch>
If a L<DateTime> error occurs, it will be caught and an L<error|Module::Generic/error> will be set and C<undef> will be returned.
=head2 now
my $d = Module::Generic::DateTime->now;
Instantiate a new L<Module::Generic::DateTime> using the L<DateTime> method C<now>. Any parameters are passed through to L<DateTime/now>
If a L<DateTime> error occurs, it will be caught and an L<error|Module::Generic/error> will be set and C<undef> will be returned.
=head1 METHODS
=head2 as_string
This is an alias to L</stringify>
=head2 datetime
Sets or gets the underlying L<DateTime> object.
=head2 op
This method is called to overload the following operations:
=over 4
=item * C<""> stringification
=item * C<bool>
=item * C<>> greater than
=item * C<>=> greater or equal than
=item * C<<> lower than
=item * C<<=> lower or equal than
=item * C<==> euqal
=item * C<!=> not equal
=item * C<-> minus
=item * C<+> plus
=back
=head2 op_minus_plus
This methods handles cases of overloading for C<minus> and C<plus>
=head1 SERIALISATION
=for Pod::Coverage FREEZE
=for Pod::Coverage STORABLE_freeze
=for Pod::Coverage STORABLE_thaw
=for Pod::Coverage THAW
=for Pod::Coverage TO_JSON
Serialisation by L<CBOR|CBOR::XS>, L<Sereal> and L<Storable::Improved> (or the legacy L<Storable>) is supported by this package. To that effect, the following subroutines are implemented: C<FREEZE>, C<THAW>, C<STORABLE_freeze> and C<STORABLE_thaw>
Additionally, upon loading L<Module::Generic::DateTime>, it will ensure the following L<DateTime> modules also have a C<FREEZE> and C<THAW> subroutines if not defined already: L<DateTime>, L<DateTime::TimeZone>, L<DateTime::TimeZone::OffsetOnly>, L<DateTime::Locale::FromData>, L<DateTime::Locale::Base>