shell bypass 403
package DateTime::Calendar::Mayan;
use strict;
use vars qw( $VERSION );
$VERSION = '0.0601';
use DateTime;
use Params::Validate qw( validate SCALAR OBJECT );
use constant MAYAN_EPOCH => -1137142;
use constant MAYAN_HAAB_EPOCH => MAYAN_EPOCH - 348;
use constant MAYAN_HAAB_MONTH => qw( Pop Uo Zip Zotz Tzec Xul Yaxkin Mol Chen
Yax Zac Ceh Mac Kankin Muan Pax Kayab Cumku Uayeb );
use constant MAYAN_TZOLKIN_EPOCH => MAYAN_EPOCH - 159;
use constant MAYAN_TZOLKIN_NAME => qw( Imix Ik Akbal Kan Chicchan Cimi Manik
Lamat Muluc Oc Chuen Eb Ben Ix Men Cib Caban Etznab Cauac Ahau );
sub new {
my( $class ) = shift;
my %args = validate( @_,
{
baktun => { type => SCALAR, default => 0 },
katun => { type => SCALAR, default => 0 },
tun => { type => SCALAR, default => 0 },
uinal => { type => SCALAR, default => 0 },
kin => { type => SCALAR, default => 0 },
epoch => {
type => OBJECT,
can => 'utc_rd_values',
optional => 1,
},
}
);
$class = ref( $class ) || $class;
my $alt_epoch;
if ( exists $args{ epoch } ) {
my $object = $args{ epoch };
delete $args{ epoch };
$object = $object->clone->set_time_zone( 'floating' )
if $object->can( 'set_time_zone' );
$alt_epoch = ( $object->utc_rd_values )[ 0 ];
}
my $self = {
epoch => $alt_epoch || MAYAN_EPOCH,
rd_secs => 0,
rd_nanos => 0,
};
$self->{ rd } = _long_count2rd( $self, \%args );
return( bless( $self, $class ) );
}
sub now {
my( $class ) = shift;
$class = ref( $class ) || $class;
my $dt = DateTime->now;
my $dtcm = $class->from_object( object => $dt );
return( $dtcm );
}
sub today {
my( $class ) = shift;
$class = ref( $class ) || $class;
my $dt = DateTime->today;
my $dtcm = $class->from_object( object => $dt );
return( $dtcm );
}
# lifted from DateTime
sub clone { bless { %{ $_[0] } }, ref $_[0] }
sub _long_count2rd {
my( $self, $lc ) = @_;
my $rd = $self->{ epoch }
+ $lc->{ baktun } * 144000
+ $lc->{ katun } * 7200
+ $lc->{ tun } * 360
+ $lc->{ uinal } * 20
+ $lc->{ kin };
return( $rd );
}
sub _rd2long_count {
my( $self ) = shift;
my %lc;
my $long_count = $self->{ rd } - $self->{ epoch };
$lc{ baktun } = _floor( $long_count / 144000 );
my $day_baktun = $long_count % 144000;
$lc{ katun } = _floor( $day_baktun / 7200 );
my $day_katun = $day_baktun % 7200;
$lc{ tun } = _floor( $day_katun / 360 );
my $day_tun = $day_katun % 360;
$lc{ uinal } = _floor( $day_tun / 20 );
$lc{ kin } = _floor( $day_tun % 20 );
return( \%lc );
}
sub _rd2haab {
my( $self ) = shift;
my %haab;
my $count = ( $self->{ rd } - MAYAN_HAAB_EPOCH ) % 365;
$haab{ day } = $count % 20;
$haab{ month } = _floor( $count / 20 ) + 1;
return( \%haab );
}
sub _haab2rd {
my( $month, $day ) = @_;
return( ( $month - 1 ) * 20 + $day );
}
sub _rd2tzolkin {
my( $self ) = shift;
my %tzolkin;
my $count = $self->{ rd } - MAYAN_TZOLKIN_EPOCH + 1;
$tzolkin{ number } = _amod( $count, 13 );
$tzolkin{ name } = _amod( $count, 20 );
return( \%tzolkin );
}
sub _tzolkin2rd {
my( $number, $name ) = shift;
return( ( $number - 1 + 39 x ( $number - $name ) ) % 260 );
}
sub from_object {
my( $class ) = shift;
my %args = validate( @_,
{
object => {
type => OBJECT,
can => 'utc_rd_values',
},
},
);
$class = ref( $class ) || $class;
my $object = $args{ object };
$object = $object->clone->set_time_zone( 'floating' )
if $object->can( 'set_time_zone' );
my( $rd, $rd_secs, $rd_nanos ) = $object->utc_rd_values();
my $dtcm_epoch = $object->mayan_epoch
if $object->can( 'mayan_epoch' );
my $self = {
rd => $rd,
rd_secs => $rd_secs,
rd_nanos => $rd_nanos || 0,
epoch => $dtcm_epoch->{ rd } || MAYAN_EPOCH,
};
return( bless( $self, $class ) );
}
sub utc_rd_values {
my( $self ) = shift;
# days utc, seconds utc,
return( $self->{ rd }, $self->{ rd_secs }, $self->{ rd_nanos } || 0 );
}
sub from_epoch {
my( $class ) = shift;
my %args = validate( @_,
{
epoch => { type => SCALAR },
}
);
$class = ref( $class ) || $class;
my $dt = DateTime->from_epoch( epoch => $args{ epoch } );
my $self = $class->from_object( object => $dt );
return( $self );
}
sub epoch {
my( $self ) = shift;
my $dt = DateTime->from_object( object => $self );
return( $dt->epoch );
}
sub set_mayan_epoch {
my( $self ) = shift;
my %args = validate( @_,
{
object => {
type => OBJECT,
can => 'utc_rd_values',
},
},
);
my $object = $args{ object };
$object = $object->clone->set_time_zone( 'floating' )
if $object->can( 'set_time_zone' );
# this can not handle rd values larger then a Mayan year
# $self->{ rd } = _long_count2rd( $self, _rd2long_count( $self ) );
$self->{ epoch } = ( $object->utc_rd_values )[ 0 ];
if ( $self->{ epoch } > MAYAN_EPOCH ) {
$self->{ rd } += abs( $self->{ epoch } - MAYAN_EPOCH );
} else {
$self->{ rd } -= abs( $self->{ epoch } - MAYAN_EPOCH );
}
return( $self );
}
sub mayan_epoch {
my( $self ) = shift;
my $new_self = $self->clone();
$new_self->{ rd } = $self->{ epoch };
$new_self->{ rd_secs } = 0;
$new_self->{ epoch } = MAYAN_EPOCH;
# calling from_object causes a method loop
my $class = ref( $self );
my $dtcm = bless( $new_self, $class );
return( $dtcm );
}
sub set {
my( $self ) = shift;
my %args = validate( @_,
{
baktun => { type => SCALAR, optional => 1 },
katun => { type => SCALAR, optional => 1 },
tun => { type => SCALAR, optional => 1 },
uinal => { type => SCALAR, optional => 1 },
kin => { type => SCALAR, optional => 1 },
}
);
my $lc = _rd2long_count( $self );
$lc->{ baktun } = $args{ baktun } if defined $args{ baktun };
$lc->{ katun } = $args{ katun } if defined $args{ katun };
$lc->{ tun } = $args{ tun } if defined $args{ tun };
$lc->{ uinal } = $args{ uinal } if defined $args{ uinal };
$lc->{ kin } = $args{ kin } if defined $args{ kin };
$self->{ rd } = _long_count2rd( $self, $lc );
return( $self );
}
sub add {
my( $self ) = shift;
my %args = validate( @_,
{
baktun => { type => SCALAR, optional => 1 },
katun => { type => SCALAR, optional => 1 },
tun => { type => SCALAR, optional => 1 },
uinal => { type => SCALAR, optional => 1 },
kin => { type => SCALAR, optional => 1 },
}
);
my $lc = _rd2long_count( $self );
$lc->{ baktun } += $args{ baktun } if defined $args{ baktun };
$lc->{ katun } += $args{ katun } if defined $args{ katun };
$lc->{ tun } += $args{ tun } if defined $args{ tun };
$lc->{ uinal } += $args{ uinal } if defined $args{ uinal };
$lc->{ kin } += $args{ kin } if defined $args{ kin };
$self->{ rd } = _long_count2rd( $self, $lc );
return( $self );
}
sub subtract {
my( $self ) = shift;
my %args = validate( @_,
{
baktun => { type => SCALAR, optional => 1 },
katun => { type => SCALAR, optional => 1 },
tun => { type => SCALAR, optional => 1 },
uinal => { type => SCALAR, optional => 1 },
kin => { type => SCALAR, optional => 1 },
}
);
my $lc = _rd2long_count( $self );
$lc->{ baktun } -= $args{ baktun } if defined $args{ baktun };
$lc->{ katun } -= $args{ katun } if defined $args{ katun };
$lc->{ tun } -= $args{ tun } if defined $args{ tun };
$lc->{ uinal } -= $args{ uinal } if defined $args{ uinal };
$lc->{ kin } -= $args{ kin } if defined $args{ kin };
$self->{ rd } = _long_count2rd( $self, $lc );
return( $self );
}
sub add_duration {
my( $self, $duration ) = @_;
my $dt = DateTime->from_object( object => $self );
$dt->add_duration( $duration );
my $new_self = $self->from_object( object => $dt );
# if there is an alternate epoch defined don't touch it
$self->{ rd } = $new_self->{ rd };
$self->{ rd_secs } = $new_self->{ rd_secs };
return( $self );
}
sub subtract_duration {
my( $self, $duration ) = @_;
my $dt = DateTime->from_object( object => $self );
$dt->subtract_duration( $duration );
my $new_self = $self->from_object( object => $dt );
# if there is an alternate epoch defined don't touch it
$self->{ rd } = $new_self->{ rd };
$self->{ rd_secs } = $new_self->{ rd_secs };
return( $self );
}
sub baktun {
my( $self, $arg ) = @_;
my $lc = _rd2long_count( $self );
if ( defined $arg ) {
$lc->{ baktun } = $arg;
$self->{ rd } = _long_count2rd( $self, $lc );
return( $self );
}
# conversion from Date::Maya
# set baktun to [1-13]
$lc->{ baktun } %= 13;
$lc->{ baktun } = 13 if $lc->{ baktun } == 0;
return( $lc->{ baktun } );
}
*set_baktun = \&baktun;
sub katun {
my( $self, $arg ) = @_;
my $lc = _rd2long_count( $self );
if ( defined $arg ) {
$lc->{ katun } = $arg;
$self->{ rd } = _long_count2rd( $self, $lc );
return( $self );
}
return( $lc->{ katun } );
}
*set_katun= \&katun;
sub tun {
my( $self, $arg ) = @_;
my $lc = _rd2long_count( $self );
if ( defined $arg ) {
$lc->{ tun } = $arg;
$self->{ rd } = _long_count2rd( $self, $lc );
return( $self );
}
return( $lc->{ tun } );
}
*set_tun= \&tun;
sub uinal {
my( $self, $arg ) = @_;
my $lc = _rd2long_count( $self );
if ( defined $arg ) {
$lc->{ uinal } = $arg;
$self->{ rd } = _long_count2rd( $self, $lc );
return( $self );
}
return( $lc->{ uinal } );
}
*set_uinal= \&uinal;
sub kin {
my( $self, $arg ) = @_;
my $lc = _rd2long_count( $self );
if ( defined $arg ) {
$lc->{ kin } = $arg;
$self->{ rd } = _long_count2rd( $self, $lc );
return( $self );
}
return( $lc->{ kin } );
}
*set_kin= \&kin;
sub bktuk {
my( $self, $sep ) = @_;
$sep = '.' unless defined $sep;
my $lc = _rd2long_count( $self );
$lc->{ baktun } %= 13;
$lc->{ baktun } = 13 if $lc->{ baktun } == 0;
return(
$lc->{ baktun } . $sep .
$lc->{ katun } . $sep .
$lc->{ tun } . $sep .
$lc->{ uinal } . $sep .
$lc->{ kin }
);
}
*date = \&bktuk;
*long_count = \&bktuk;
sub haab {
my( $self, $sep ) = @_;
$sep = ' ' unless defined $sep;
my $haab = _rd2haab( $self );
return( $haab->{ day } . $sep . (MAYAN_HAAB_MONTH)[ $haab->{ month } - 1 ] );
}
sub tzolkin {
my( $self, $sep ) = @_;
$sep = ' ' unless defined $sep;
my $tzolkin = _rd2tzolkin( $self );
return( $tzolkin->{ number } . $sep . (MAYAN_TZOLKIN_NAME )[ $tzolkin->{ name } - 1 ] );
}
# lifted from DateTime::Calendar::Julian;
sub _floor {
my $x = shift;
my $ix = int $x;
if ($ix <= $x) {
return $ix;
} else {
return $ix - 1;
}
}
sub _amod {
my( $x, $y ) = @_;
return( $y + $x % ( -$y ) );
}
1;
__END__