DateTime-Calendar-Hebrew
view release on metacpan or search on metacpan
package DateTime::Calendar::Hebrew;
use DateTime;
use Params::Validate qw/validate SCALAR OBJECT CODEREF/;
use vars qw($VERSION);
$VERSION = '0.05';
use 5.010_000;
use strict;
no strict 'refs';
use constant HEBREW_EPOCH => -1373429;
use overload
fallback => 1,
'<=>' => '_compare_overload',
'cmp' => '_compare_overload',
'+' => '_add_overload',
'-' => '_subtract_overload';
sub new {
my $class = shift;
my %p = validate( @_,
{ year => { type => SCALAR },
month => { type => SCALAR, default => 1,
callbacks => {
'is between 1 and 13' =>
sub { $_[0] >= 1 && $_[0] <= 13 }
}
},
day => { type => SCALAR, default => 1,
callbacks => {
'is between 1 and 30' =>
sub { $_[0] >= 1 && $_[0] <= 30 }
}
},
hour => { type => SCALAR, default => 0,
callbacks => {
'is between 0 and 23' =>
sub { $_[0] >= 0 && $_[0] <= 23 }
}
},
minute => { type => SCALAR, default => 0,
callbacks => {
'is between 0 and 59' =>
sub { $_[0] >= 0 && $_[0] <= 59 }
}
},
second => { type => SCALAR, default => 0,
callbacks => {
'is between 0 and 59' =>
sub { $_[0] >= 0 && $_[0] <= 59 }
}
},
nanosecond => { type => SCALAR, default => 0,
callbacks => {
'is between 0 and 999999999' =>
sub { $_[0] >= 0 && $_[0] <= 999999999 }
}
},
sunset => { type => OBJECT, optional => 1 },
time_zone => { type => SCALAR, optional => 1 },
} );
my $self = bless \%p, $class;
$self->{rd_days} = &_to_rd(@p{ qw(year month day) });
$self->{rd_secs} = $p{hour} * 60 * 60 + $p{minute} * 60 + $p{second};
if($self->{nanosecond}) { $self->{rd_nanosecs} = delete $self->{nanosecond}; }
if($self->{sunset} and $self->{time_zone}) {
my $DT_Event_Sunrise = $self->{sunset};
my $time_zone = $self->{time_zone};
my $DT = DateTime->from_object(object => $self);
my $sunset = $DT_Event_Sunrise->next($DT->clone->truncate(to => 'day'));
$sunset->set_time_zone($time_zone);
if($DT > $sunset) {
$self->{after_sunset} = 1;
@{$self}{qw/year month day/} = &_from_rd($self->{rd_days} + 1);
}
}
return $self;
}
sub from_object {
my ( $class ) = shift;
my %p = validate( @_, {
object => {
type => OBJECT,
can => 'utc_rd_values',
},
});
my $object = $p{object}->clone();
$object->set_time_zone('floating') if $object->can( 'set_time_zone' );
my ($rd_days, $rd_secs, $rd_nanosecs) = $object->utc_rd_values();
$rd_nanosecs ||= 0;
my %args;
@args{ qw( year month day ) } = &_from_rd($rd_days);
my($h, $m, $s);
$s = $rd_secs % 60;
$m = int($rd_secs / 60);
$h = int($m / 60);
$m %= 60;
@args{ qw(hour minute second) } = ($h, $m, $s);
$args{nanosecond} = $rd_nanosecs || 0;
my $new_object = $class->new(%args);
return $new_object;
}
sub set {
my $self = shift;
my %p = validate( @_,
{ year => { type => SCALAR, optional => 1 },
month => { type => SCALAR, optional => 1,
callbacks => {
'is between 1 and 13' =>
sub { $_[0] >= 1 && $_[0] <= 13 }
}
},
day => { type => SCALAR, optional => 1,
callbacks => {
'is between 1 and 30' =>
sub { $_[0] >= 1 && $_[0] <= 30 }
}
},
hour => { type => SCALAR, optional => 1,
callbacks => {
'is between 0 and 23' =>
sub { $_[0] >= 0 && $_[0] <= 23 }
}
},
minute => { type => SCALAR, optional => 1,
callbacks => {
'is between 0 and 59' =>
sub { $_[0] >= 0 && $_[0] <= 59 }
}
},
second => { type => SCALAR, optional => 1,
callbacks => {
'is between 0 and 59' =>
sub { $_[0] >= 0 && $_[0] <= 59 }
}
},
nanosecond => { type => SCALAR, optional => 1,
callbacks => {
'is between 0 and 999999999' =>
sub { $_[0] >= 0 && $_[0] <= 999999999 }
}
},
sunset => { type => OBJECT, optional => 1 },
time_zone => { type => SCALAR, optional => 1 },
} );
$self->{$_} = $p{$_} for keys %p;
$self->{rd_days} = &_to_rd($self->{year}, $self->{month}, $self->{day});
$self->{rd_secs} = $self->{hour} * 60 * 60 + $self->{minute} * 60 + $self->{second};
if($self->{nanosecond}) { $self->{rd_nanosecs} = delete $self->{nanosecond}; }
if($self->{sunset} and $self->{time_zone}) {
my $DT_Event_Sunrise = $self->{sunset};
my $time_zone = $self->{time_zone};
my $DT = DateTime->from_object(object => $self);
my $sunset = $DT_Event_Sunrise->next($DT->clone->truncate(to => 'day'));
$sunset->set_time_zone($time_zone);
if($DT > $sunset) {
$self->{after_sunset} = 1;
@{$self}{qw/year month day/} = &_from_rd($self->{rd_days} + 1);
}
}
return $self;
}
sub utc_rd_values {
my $self = shift;
my @res = @{$self}{ qw/rd_days rd_secs rd_nanosecs/ };
# Protect against undef
$res[2] ||= 0;
return @res;
}
sub utc_rd_as_seconds {
my $self = shift;
my ($rd_days, $rd_secs, $rd_nanosecs) = $self->utc_rd_values;
return $rd_days*24*60*60 + $rd_secs;
}
sub clone {
my $self = shift;
my $clone = {%$self};
bless $clone, ref $self;
return $clone;
}
sub _compare_overload {
return $_[2] ? - $_[0]->_compare($_[1]) : $_[0]->_compare($_[1]);
}
sub _compare {
my($a, $b) = @_;
( run in 1.606 second using v1.01-cache-2.11-cpan-39bf76dae61 )