BSON
view release on metacpan or search on metacpan
lib/BSON/Time.pm view on Meta::CPAN
use 5.010001;
use strict;
use warnings;
package BSON::Time;
# ABSTRACT: BSON type wrapper for date and time
use version;
our $VERSION = 'v1.12.2';
use Carp qw/croak/;
use Config;
use Time::HiRes qw/time/;
use Scalar::Util qw/looks_like_number/;
use if !$Config{use64bitint}, 'Math::BigInt';
use if !$Config{use64bitint}, 'Math::BigFloat';
use Moo;
#pod =attr value
#pod
#pod A integer representing milliseconds since the Unix epoch. The default
#pod is 0.
#pod
#pod =cut
has 'value' => (
is => 'ro'
);
use namespace::clean -except => 'meta';
sub BUILDARGS {
my $class = shift;
my $n = scalar(@_);
my %args;
if ( $n == 0 ) {
if ( $Config{use64bitint} ) {
$args{value} = time() * 1000;
}
else {
$args{value} = Math::BigFloat->new(time());
$args{value}->bmul(1000);
$args{value} = $args{value}->as_number('zero');
}
}
elsif ( $n == 1 ) {
croak "argument to BSON::Time::new must be epoch seconds, not '$_[0]'"
unless looks_like_number( $_[0] );
if ( !$Config{use64bitint} && ref($args{value}) ne 'Math::BigInt' ) {
$args{value} = Math::BigFloat->new(shift);
$args{value}->bmul(1000);
$args{value} = $args{value}->as_number('zero');
}
else {
$args{value} = 1000 * shift;
}
}
elsif ( $n % 2 == 0 ) {
%args = @_;
if ( defined $args{value} ) {
croak "argument to BSON::Time::new must be epoch seconds, not '$args{value}'"
unless looks_like_number( $args{value} ) || overload::Overloaded($args{value});
if ( !$Config{use64bitint} && ref($args{value}) ne 'Math::BigInt' ) {
$args{value} = Math::BigInt->new($args{value});
}
}
else {
if ( !$Config{use64bitint} && ref($args{value}) ne 'Math::BigInt' ) {
$args{value} = Math::BigFloat->new(shift);
$args{value}->bmul(1000);
$args{value} = $args{value}->as_number('zero');
}
else {
$args{value} = 1000 * shift;
}
}
}
else {
croak("Invalid number of arguments ($n) to BSON::Time::new");
}
# normalize all to integer ms
$args{value} = int( $args{value} );
return \%args;
}
#pod =method epoch
#pod
#pod Returns the number of seconds since the epoch (i.e. a floating-point value).
#pod
#pod =cut
sub epoch {
my $self = shift;
if ( $Config{use64bitint} ) {
return $self->value / 1000;
}
else {
require Math::BigFloat;
my $upgrade = Math::BigFloat->new($self->value->bstr);
return 0 + $upgrade->bdiv(1000)->bstr;
}
}
#pod =method as_iso8601
#pod
#pod Returns the C<value> as an ISO-8601 formatted string of the form
#pod C<YYYY-MM-DDThh:mm:ss.sssZ>. The fractional seconds will be omitted if
#pod they are zero.
#pod
#pod =cut
sub as_iso8601 {
my $self = shift;
my ($s, $m, $h, $D, $M, $Y) = gmtime($self->epoch);
$M++;
$Y+=1900;
my $f = $self->{value} % 1000;
return $f
? sprintf( "%4d-%02d-%02dT%02d:%02d:%02d.%03dZ", $Y, $M, $D, $h, $m, $s, $f )
( run in 0.388 second using v1.01-cache-2.11-cpan-d7f47b0818f )