DateTime-Format-Epoch

 view release on metacpan or  search on metacpan

lib/DateTime/Format/Epoch.pm  view on Meta::CPAN

package DateTime::Format::Epoch;

use 5.00503; #qr
use strict;

use vars qw($VERSION);

$VERSION = '0.16';

use DateTime 0.22;
use DateTime::LeapSecond;

use Math::BigInt 'lib' => 'GMP,Pari,FastCalc';
use Params::Validate qw/validate BOOLEAN OBJECT/;

sub _floor {
    my $x  = shift;
    my $ix = int $x;
    if ($ix <= $x) {
        return $ix;
    } else {
        return $ix - 1;
    }
}

my %units_per_second = (
        seconds     => 1,
        milliseconds => 1000,
        microseconds => 1e6,
        nanoseconds => 1e9,
   );

sub new {
	my $class = shift;
    my %p = validate( @_,
                      { epoch => {type  => OBJECT, 
                                  can   => 'utc_rd_values'},
                        unit  => {callbacks =>
                                     {'valid unit' =>
                                      sub { exists $units_per_second{$_[0]}
                                            or $_[0] > 0 }},
                                  default => 'seconds'},
                        type  => {regex => qr/^(?:int|float|bigint)$/,
                                  default => 0},
                        local_epoch => {type => BOOLEAN,
                                        default => 0},
                        dhms  => {type => BOOLEAN,
                                  default => 0},
                        skip_leap_seconds => {type => BOOLEAN,
                                              default => 1},
                        start_at => {default => 0},
                      } );

    $p{epoch} = $p{epoch}->clone if $p{epoch}->can('clone');

    $p{unit} = $units_per_second{$p{unit}} || $p{unit};
    $p{unit} = 1 if $p{dhms};

    if (!$p{type}) {
        $p{type} = ($p{unit} > 1e6 ? 'bigint' : 'int');
    }

    ($p{epoch_rd_days}, $p{epoch_rd_secs}) = $p{epoch}->utc_rd_values;
    $p{epoch_class} = ref $p{epoch};

    if (!$p{skip_leap_seconds}) {
        $p{leap_secs} =
            DateTime::LeapSecond::leap_seconds( $p{epoch_rd_days} );
    }

    my $self = bless \%p, $class;
	return $self;
}

sub format_datetime {
    my ($self, $dt) = @_;

    unless (ref $self) {
        $self = $self->new;
    }

    $dt = $dt->clone->set_time_zone('floating')
        if  $self->{local_epoch} &&
            $self->{epoch}->can('time_zone') &&
            $self->{epoch}->time_zone->is_floating &&
            $dt->can('time_zone') &&
            !$dt->time_zone->is_floating;

    my ($rd_days, $rd_secs) = $dt->utc_rd_values;
    my $delta_days = $rd_days - $self->{epoch_rd_days};
    my $delta_secs = $rd_secs - $self->{epoch_rd_secs};

    my $secs = $delta_days * 86_400 + $delta_secs;

    if (!$self->{skip_leap_seconds}) {
        $secs += DateTime::LeapSecond::leap_seconds( $rd_days )
                 - $self->{leap_secs};
    }



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