home *** CD-ROM | disk | FTP | other *** search
-
- ###############################################################################
- ## ##
- ## Copyright (c) 2000 - 2002 by Steffen Beyer. ##
- ## All rights reserved. ##
- ## ##
- ## This package is free software; you can redistribute it ##
- ## and/or modify it under the same terms as Perl itself. ##
- ## ##
- ###############################################################################
-
- ###############################################################################
- ## ##
- ## Mottos of this module: ##
- ## ##
- ## 1) Small is beautiful. ##
- ## ##
- ## 2) Make frequent things easy and infrequent or hard things possible. ##
- ## ##
- ###############################################################################
-
- package Date::Calc::Object;
-
- use strict;
- use vars qw(@ISA @AUXILIARY @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
-
- use Carp::Clan qw(^Date::);
-
- BEGIN # Re-export imports from Date::Calc:
- {
- require Exporter;
- require Date::Calc;
- @ISA = qw(Exporter Date::Calc);
- @AUXILIARY = qw(shift_year shift_date shift_time shift_datetime);
- @EXPORT = @Date::Calc::EXPORT;
- @EXPORT_OK = (@Date::Calc::EXPORT_OK,@AUXILIARY);
- %EXPORT_TAGS = (all => [@Date::Calc::EXPORT_OK],
- aux => [@AUXILIARY],
- ALL => [@EXPORT_OK]);
- $VERSION = '5.3';
- Date::Calc->import(@Date::Calc::EXPORT,@Date::Calc::EXPORT_OK);
- }
-
- sub shift_year
- {
- croak("internal error - parameter is not an ARRAY ref") if (ref($_[0]) ne 'ARRAY');
-
- if (ref($_[0][0]))
- {
- if (ref($_[0][0]) eq 'ARRAY')
- {
- if (@{$_[0][0]} == 3) # otherwise anonymous array is pointless
- {
- return ${shift(@{$_[0]})}[0];
- }
- else
- {
- croak("wrong number of elements in date constant");
- }
- }
- elsif (ref($_[0][0]) =~ /[^:]::[^:]/)
- {
- return shift(@{$_[0]})->year();
- }
- else
- {
- croak("input parameter is neither ARRAY ref nor object");
- }
- }
- else
- {
- if (@{$_[0]} >= 1)
- {
- return shift(@{$_[0]});
- }
- else
- {
- croak("not enough input parameters for a year");
- }
- }
- }
-
- sub shift_date
- {
- croak("internal error - parameter is not an ARRAY ref") if (ref($_[0]) ne 'ARRAY');
-
- if (ref($_[0][0]))
- {
- if (ref($_[0][0]) eq 'ARRAY')
- {
- if (@{$_[0][0]} == 3)
- {
- return( @{shift(@{$_[0]})} );
- }
- else
- {
- croak("wrong number of elements in date constant");
- }
- }
- elsif (ref($_[0][0]) =~ /[^:]::[^:]/)
- {
- return( shift(@{$_[0]})->date() );
- }
- else
- {
- croak("input parameter is neither ARRAY ref nor object");
- }
- }
- else
- {
- if (@{$_[0]} >= 3)
- {
- return( shift(@{$_[0]}), shift(@{$_[0]}), shift(@{$_[0]}) );
- }
- else
- {
- croak("not enough input parameters for a date");
- }
- }
- }
-
- sub shift_time
- {
- croak("internal error - parameter is not an ARRAY ref") if (ref($_[0]) ne 'ARRAY');
-
- if (ref($_[0][0]))
- {
- if (ref($_[0][0]) eq 'ARRAY')
- {
- if (@{$_[0][0]} == 3)
- {
- return( @{shift(@{$_[0]})} );
- }
- else
- {
- croak("wrong number of elements in time constant");
- }
- }
- elsif (ref($_[0][0]) =~ /[^:]::[^:]/)
- {
- return( (shift(@{$_[0]})->datetime())[3,4,5] );
- }
- else
- {
- croak("input parameter is neither ARRAY ref nor object");
- }
- }
- else
- {
- if (@{$_[0]} >= 3)
- {
- return( shift(@{$_[0]}), shift(@{$_[0]}), shift(@{$_[0]}) );
- }
- else
- {
- croak("not enough input parameters for time values");
- }
- }
- }
-
- sub shift_datetime
- {
- croak("internal error - parameter is not an ARRAY ref") if (ref($_[0]) ne 'ARRAY');
-
- if (ref($_[0][0]))
- {
- if (ref($_[0][0]) eq 'ARRAY')
- {
- if (@{$_[0][0]} == 6)
- {
- return( @{shift(@{$_[0]})} );
- }
- else
- {
- croak("wrong number of elements in date-time constant");
- }
- }
- elsif (ref($_[0][0]) =~ /[^:]::[^:]/)
- {
- return( shift(@{$_[0]})->datetime() );
- }
- else
- {
- croak("input parameter is neither ARRAY ref nor object");
- }
- }
- else
- {
- if (@{$_[0]} >= 6)
- {
- return( shift(@{$_[0]}), shift(@{$_[0]}), shift(@{$_[0]}),
- shift(@{$_[0]}), shift(@{$_[0]}), shift(@{$_[0]}) );
- }
- else
- {
- croak("not enough input parameters for a date and time");
- }
- }
- }
-
- package Date::Calc;
-
- use strict;
-
- use Carp::Clan qw(^Date::);
-
- use overload
- '0+' => 'number',
- '""' => 'string',
- 'bool' => 'is_valid',
- 'neg' => '_unary_minus_',
- 'abs' => 'number',
- '<=>' => '_compare_date_',
- 'cmp' => '_compare_date_time_',
- '==' => '_equal_date_',
- '!=' => '_not_equal_date_',
- 'eq' => '_equal_date_time_',
- 'ne' => '_not_equal_date_time_',
- '+' => '_plus_',
- '-' => '_minus_',
- '+=' => '_plus_equal_',
- '-=' => '_minus_equal_',
- '++' => '_increment_',
- '--' => '_decrement_',
- 'x' => '_times_',
- 'x=' => '_times_equal_',
- '=' => 'clone',
- 'nomethod' => 'OVERLOAD', # equivalent of AUTOLOAD ;-)
- 'fallback' => undef;
-
- # Report unimplemented overloaded operators:
-
- sub OVERLOAD
- {
- croak("operator '$_[3]' is unimplemented");
- }
-
- # Prevent nearly infinite loops:
-
- sub _times_
- {
- $_[3] = 'x';
- goto &OVERLOAD;
- }
-
- sub _times_equal_
- {
- $_[3] = 'x=';
- goto &OVERLOAD;
- }
-
- my $ACCURATE_MODE = 1;
- my $NUMBER_FORMAT = 0;
- my $DELTA_FORMAT = 0;
- my $DATE_FORMAT = 0;
-
- sub accurate_mode
- {
- my($flag) = $ACCURATE_MODE;
-
- if (@_ > 1)
- {
- $ACCURATE_MODE = $_[1] || 0;
- }
- return $flag;
- }
-
- sub number_format
- {
- my($flag) = $NUMBER_FORMAT;
-
- if (@_ > 1)
- {
- $NUMBER_FORMAT = $_[1] || 0;
- }
- return $flag;
- }
-
- sub delta_format
- {
- my($self) = shift;
- my($flag);
-
- if (ref $self) # object method
- {
- $flag = defined($self->[0][1]) ? $self->[0][1] : undef;
- if (@_ > 0)
- {
- $self->[0][1] = defined($_[0]) ? $_[0] : undef;
- }
- }
- else # class method
- {
- $flag = $DELTA_FORMAT;
- if (@_ > 0)
- {
- $DELTA_FORMAT = $_[0] || 0;
- }
- }
- return $flag;
- }
-
- sub date_format
- {
- my($self) = shift;
- my($flag);
-
- if (ref $self) # object method
- {
- $flag = defined($self->[0][2]) ? $self->[0][2] : undef;
- if (@_ > 0)
- {
- $self->[0][2] = defined($_[0]) ? $_[0] : undef;
- }
- }
- else # class method
- {
- $flag = $DATE_FORMAT;
- if (@_ > 0)
- {
- $DATE_FORMAT = $_[0] || 0;
- }
- }
- return $flag;
- }
-
- sub language
- {
- my($self) = shift;
- my($lang,$temp);
-
- eval
- {
- if (ref $self) # object method
- {
- $lang = defined($self->[0][3]) ? Language_to_Text($self->[0][3]) : undef;
- if (@_ > 0)
- {
- if (defined $_[0])
- {
- $temp = $_[0];
- if ($temp !~ /^\d+$/)
- { $temp = Decode_Language($temp); }
- if ($temp > 0 and $temp <= Languages())
- { $self->[0][3] = $temp; }
- else
- { die "no such language '$_[0]'"; }
- }
- else { $self->[0][3] = undef; }
- }
- }
- else # class method
- {
- $lang = Language_to_Text(Language());
- if (@_ > 0)
- {
- $temp = $_[0];
- if ($temp !~ /^\d+$/)
- { $temp = Decode_Language($temp); }
- if ($temp > 0 and $temp <= Languages())
- { Language($temp); }
- else
- { die "no such language '$_[0]'"; }
- }
- }
- };
- if ($@)
- {
- $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
- $@ =~ s!\s+at\s+\S.*\s*$!!;
- croak($@);
- }
- return $lang;
- }
-
- sub is_delta
- {
- my($self) = @_;
- my($bool) = undef;
-
- eval
- {
- if (defined($self->[0]) and
- ref($self->[0]) eq 'ARRAY' and
- defined($self->[0][0]))
- { $bool = ($self->[0][0] ? 1 : 0); }
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- return $bool;
- }
-
- sub is_date
- {
- my($self) = @_;
- my($bool) = undef;
-
- eval
- {
- if (defined($self->[0]) and
- ref($self->[0]) eq 'ARRAY' and
- defined($self->[0][0]))
- { $bool = ($self->[0][0] ? 0 : 1); }
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- return $bool;
- }
-
- sub is_short
- {
- my($self) = @_;
- my($bool) = undef;
-
- eval
- {
- if (@{$self} == 4) { $bool = 1; }
- elsif (@{$self} == 7) { $bool = 0; }
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- return $bool;
- }
-
- sub is_long
- {
- my($self) = @_;
- my($bool) = undef;
-
- eval
- {
- if (@{$self} == 7) { $bool = 1; }
- elsif (@{$self} == 4) { $bool = 0; }
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- return $bool;
- }
-
- sub is_valid
- {
- my($self) = @_;
- my($bool);
-
- $bool = eval
- {
- if (defined($self->[0]) and
- ref($self->[0]) eq 'ARRAY' and
- @{$self->[0]} > 0 and
- defined($self->[0][0]) and
- not ref($self->[0][0]) and
- ($self->[0][0] == 0 or $self->[0][0] == 1) and
- (@{$self} == 4 or @{$self} == 7))
- {
- if ($self->[0][0]) # is_delta
- {
- return 0 unless
- (
- defined($self->[1]) and not ref($self->[1]) and
- defined($self->[2]) and not ref($self->[2]) and
- defined($self->[3]) and not ref($self->[3])
- );
- if (@{$self} > 4) # is_long
- {
- return 0 unless
- (
- defined($self->[4]) and not ref($self->[4]) and
- defined($self->[5]) and not ref($self->[5]) and
- defined($self->[6]) and not ref($self->[6])
- );
- }
- return 1;
- }
- else # is_date
- {
- return 0 unless
- (
- defined($self->[1]) and not ref($self->[1]) and
- defined($self->[2]) and not ref($self->[2]) and
- defined($self->[3]) and not ref($self->[3]) and
- check_date(@{$self}[1..3])
- );
- if (@{$self} > 4) # is_long
- {
- return 0 unless
- (
- defined($self->[4]) and not ref($self->[4]) and
- defined($self->[5]) and not ref($self->[5]) and
- defined($self->[6]) and not ref($self->[6]) and
- check_time(@{$self}[4..6])
- );
- }
- return 1;
- }
- }
- return undef;
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- return $bool;
- }
-
- sub normalize
- {
- my($self) = shift;
- my($quot);
-
- if ($self->is_valid())
- {
- if ($self->is_delta())
- {
- if ($self->is_long())
- {
- splice( @{$self}, 3, 4, Normalize_DHMS(@{$self}[3..6]) );
- }
- unless ($ACCURATE_MODE) # YMD_MODE
- {
- if ($self->[2] and ($quot = int($self->[2] / 12)))
- {
- $self->[1] += $quot;
- $self->[2] -= $quot * 12;
- }
- if
- (
- $self->[2] < 0 and
- ( $self->[3] > 0 or
- $self->[4] > 0 or
- $self->[5] > 0 or
- $self->[6] > 0 )
- )
- {
- $self->[1]--;
- $self->[2] += 12;
- }
- elsif
- (
- $self->[2] > 0 and
- ( $self->[3] < 0 or
- $self->[4] < 0 or
- $self->[5] < 0 or
- $self->[6] < 0 )
- )
- {
- $self->[1]++;
- $self->[2] -= 12;
- }
- }
- }
- else
- {
- carp("normalizing a date is a no-op") if ($^W);
- }
- }
- return $self;
- }
-
- sub new
- {
- my($class,$list,$type,$self);
-
- if (@_)
- {
- $class = shift;
- if (@_ == 1 and ref($_[0]) eq 'ARRAY') { $list = $_[0]; } else { $list = \@_; }
- }
- croak("wrong number of arguments")
- unless (defined($list) and
- (@$list == 0 or @$list == 1 or @$list == 3 or @$list == 4 or @$list == 6 or @$list == 7));
- if (@$list == 1 or @$list == 4 or @$list == 7)
- {
- $type = (shift(@$list) ? 1 : 0);
- $self = [ [$type], @$list ];
- }
- elsif (@$list == 3 or @$list == 6)
- {
- $self = [ [0], @$list ];
- }
- else
- {
- $self = [ [] ];
- }
- bless($self, ref($class) || $class || 'Date::Calc');
- return $self;
- }
-
- sub clone
- {
- my($self) = @_;
- my($this);
-
- croak("invalid date/time") unless ($self->is_valid());
- $this = $self->new();
- @{$this} = @{$self};
- $this->[0] = [];
- @{$this->[0]} = @{$self->[0]};
- return $this;
- }
-
- sub copy
- {
- my($self) = shift;
- my($this);
-
- eval
- {
- if (@_ == 1 and ref($_[0])) { $this = $_[0]; } else { $this = \@_; }
- @{$self} = @{$this};
- $self->[0] = [];
- if (defined $this->[0])
- {
- if (ref($this->[0]) eq 'ARRAY') { @{$self->[0]} = @{$this->[0]}; }
- else { $self->[0][0] = $this->[0]; }
- }
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- croak("invalid date/time") unless ($self->is_valid());
- return $self;
- }
-
- sub date
- {
- my($self,$list);
-
- if (@_)
- {
- $self = shift;
- if (@_ == 1 and ref($_[0]) eq 'ARRAY') { $list = $_[0]; } else { $list = \@_; }
- }
- croak("wrong number of arguments")
- unless (defined($list) and
- (@$list == 0 or @$list == 1 or @$list == 3 or @$list == 4 or @$list == 6 or @$list == 7));
- eval
- {
- if (@$list == 1 or @$list == 4 or @$list == 7)
- {
- $self->[0][0] = (shift(@$list) ? 1 : 0);
- }
- if (@$list == 3 or @$list == 6)
- {
- splice( @{$self}, 1, scalar(@$list), @$list );
- }
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- croak("invalid date/time") unless ($self->is_valid());
- return (@{$self}[1..3]);
- }
-
- sub time
- {
- my($self,$list);
-
- if (@_)
- {
- $self = shift;
- if (@_ == 1 and ref($_[0]) eq 'ARRAY') { $list = $_[0]; } else { $list = \@_; }
- }
- croak("wrong number of arguments")
- unless (defined($list) and
- (@$list == 0 or @$list == 1 or @$list == 3 or @$list == 4));
- eval
- {
- if (@$list == 1 or @$list == 4)
- {
- $self->[0][0] = (shift(@$list) ? 1 : 0);
- }
- if (@$list == 3)
- {
- splice( @{$self}, 4, 3, @$list );
- }
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- croak("invalid date/time") unless ($self->is_valid());
- if (@{$self} == 7) { return (@{$self}[4..6]); }
- else { return (); }
- }
-
- sub datetime
- {
- my($self,$list);
-
- if (@_)
- {
- $self = shift;
- if (@_ == 1 and ref($_[0]) eq 'ARRAY') { $list = $_[0]; } else { $list = \@_; }
- }
- croak("wrong number of arguments")
- unless (defined($list) and
- (@$list == 0 or @$list == 1 or @$list == 3 or @$list == 4 or @$list == 6 or @$list == 7));
- eval
- {
- if (@$list == 1 or @$list == 4 or @$list == 7)
- {
- $self->[0][0] = (shift(@$list) ? 1 : 0);
- }
- if (@$list == 3)
- {
- splice( @{$self}, 1, 6, @$list, 0,0,0 );
- }
- elsif (@$list == 6)
- {
- splice( @{$self}, 1, 6, @$list );
- }
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- croak("invalid date/time") unless ($self->is_valid());
- if (@{$self} == 7) { return (@{$self}[1..6]); }
- else { return (@{$self}[1..3],0,0,0); }
- }
-
- sub today
- {
- my($self) = shift;
- my($gmt) = shift || 0;
-
- if (ref $self) # object method
- {
- $self->date( 0, Today($gmt) );
- return $self;
- }
- else # class method
- {
- $self ||= 'Date::Calc';
- return $self->new( 0, Today($gmt) );
- }
- }
-
- sub now
- {
- my($self) = shift;
- my($gmt) = shift || 0;
-
- if (ref $self) # object method
- {
- $self->time( 0, Now($gmt) );
- return $self;
- }
- else # class method
- {
- $self ||= 'Date::Calc';
- return $self->new( 0, Today_and_Now($gmt) );
- }
- }
-
- sub today_and_now
- {
- my($self) = shift;
- my($gmt) = shift || 0;
-
- if (ref $self) # object method
- {
- $self->date( 0, Today_and_Now($gmt) );
- return $self;
- }
- else # class method
- {
- $self ||= 'Date::Calc';
- return $self->new( 0, Today_and_Now($gmt) );
- }
- }
-
- sub gmtime
- {
- my($self) = shift;
- my(@date);
-
- eval
- {
- @date = (Gmtime(@_))[0..5];
- };
- if ($@)
- {
- $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
- $@ =~ s!\s+at\s+\S.*\s*$!!;
- croak($@);
- }
- if (ref $self) # object method
- {
- $self->date( 0, @date );
- return $self;
- }
- else # class method
- {
- $self ||= 'Date::Calc';
- return $self->new( 0, @date );
- }
- }
-
- sub localtime
- {
- my($self) = shift;
- my(@date);
-
- eval
- {
- @date = (Localtime(@_))[0..5];
- };
- if ($@)
- {
- $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
- $@ =~ s!\s+at\s+\S.*\s*$!!;
- croak($@);
- }
- if (ref $self) # object method
- {
- $self->date( 0, @date );
- return $self;
- }
- else # class method
- {
- $self ||= 'Date::Calc';
- return $self->new( 0, @date );
- }
- }
-
- sub mktime
- {
- my($self) = @_;
- my($time);
-
- if (ref $self) # object method
- {
- croak("invalid date/time") unless ($self->is_valid());
- croak("can't mktime from a delta vector") if ($self->is_delta()); # add [1970,1,1,0,0,0] first!
- eval
- {
- $time = Mktime( $self->datetime() );
- };
- if ($@)
- {
- $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
- $@ =~ s!\s+at\s+\S.*\s*$!!;
- croak($@);
- }
- return $time;
- }
- else # class method
- {
- return CORE::time();
- }
- }
-
- sub tzoffset
- {
- my($self) = shift;
- my(@diff);
-
- eval
- {
- @diff = (Timezone(@_))[0..5];
- };
- if ($@)
- {
- $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
- $@ =~ s!\s+at\s+\S.*\s*$!!;
- croak($@);
- }
- if (ref $self) # object method
- {
- $self->date( 1, @diff );
- return $self;
- }
- else # class method
- {
- $self ||= 'Date::Calc';
- return $self->new( 1, @diff );
- }
- }
-
- sub date2time
- {
- my($self) = @_;
- my($time);
-
- if (ref $self) # object method
- {
- croak("invalid date/time") unless ($self->is_valid());
- croak("can't make time from a delta vector") if ($self->is_delta()); # add [1970,1,1,0,0,0] first!
- eval
- {
- $time = Date_to_Time( $self->datetime() );
- };
- if ($@)
- {
- $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
- $@ =~ s!\s+at\s+\S.*\s*$!!;
- croak($@);
- }
- return $time;
- }
- else # class method
- {
- return CORE::time();
- }
- }
-
- sub time2date
- {
- my($self) = shift;
- my(@date);
-
- eval
- {
- @date = Time_to_Date(@_);
- };
- if ($@)
- {
- $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
- $@ =~ s!\s+at\s+\S.*\s*$!!;
- croak($@);
- }
- if (ref $self) # object method
- {
- $self->date( 0, @date );
- return $self;
- }
- else # class method
- {
- $self ||= 'Date::Calc';
- return $self->new( 0, @date );
- }
- }
-
- sub year
- {
- my($self) = shift;
-
- if (@_ > 0)
- {
- eval { $self->[1] = $_[0] || 0; };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- }
- croak("invalid date/time") unless ($self->is_valid());
- return $self->[1];
- }
-
- sub month
- {
- my($self) = shift;
-
- if (@_ > 0)
- {
- eval { $self->[2] = $_[0] || 0; };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- }
- croak("invalid date/time") unless ($self->is_valid());
- return $self->[2];
- }
-
- sub day
- {
- my($self) = shift;
-
- if (@_ > 0)
- {
- eval { $self->[3] = $_[0] || 0; };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- }
- croak("invalid date/time") unless ($self->is_valid());
- return $self->[3];
- }
-
- sub hours
- {
- my($self) = shift;
-
- if (@_ > 0)
- {
- eval
- {
- if (@{$self} == 4)
- {
- $self->[4] = 0;
- $self->[5] = 0;
- $self->[6] = 0;
- }
- if (@{$self} == 7)
- {
- $self->[4] = $_[0] || 0;
- }
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- }
- croak("invalid date/time") unless ($self->is_valid());
- if (@{$self} == 7) { return $self->[4]; }
- else { return undef; }
- }
-
- sub minutes
- {
- my($self) = shift;
-
- if (@_ > 0)
- {
- eval
- {
- if (@{$self} == 4)
- {
- $self->[4] = 0;
- $self->[5] = 0;
- $self->[6] = 0;
- }
- if (@{$self} == 7)
- {
- $self->[5] = $_[0] || 0;
- }
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- }
- croak("invalid date/time") unless ($self->is_valid());
- if (@{$self} == 7) { return $self->[5]; }
- else { return undef; }
- }
-
- sub seconds
- {
- my($self) = shift;
-
- if (@_ > 0)
- {
- eval
- {
- if (@{$self} == 4)
- {
- $self->[4] = 0;
- $self->[5] = 0;
- $self->[6] = 0;
- }
- if (@{$self} == 7)
- {
- $self->[6] = $_[0] || 0;
- }
- };
- if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
- }
- croak("invalid date/time") unless ($self->is_valid());
- if (@{$self} == 7) { return $self->[6]; }
- else { return undef; }
- }
-
- ###############################
- ## ##
- ## Selector constants ##
- ## for formatting ##
- ## callback functions: ##
- ## ##
- ###############################
- ## ##
- ## IS_SHORT = 0x00; ##
- ## IS_LONG = 0x01; ##
- ## IS_DATE = 0x00; ##
- ## IS_DELTA = 0x02; ##
- ## TO_NUMBER = 0x00; ##
- ## TO_STRING = 0x04; ##
- ## ##
- ###############################
-
- sub number
- {
- my($self,$format) = @_;
- my($number,$sign,@temp);
-
- if ($self->is_valid())
- {
- eval
- {
- $format = $NUMBER_FORMAT unless (defined $format); # because of overloading!
- if ($self->[0][0]) # is_delta
- {
- # carp("returning a fictitious number of days for delta vector")
- # if ((($self->[1] != 0) or ($self->[2] != 0)) and $^W);
- if (@{$self} == 4) # is_short
- {
- if (ref($format) eq 'CODE')
- {
- $number = &{$format}( $self, 0x02 ); # = TO_NUMBER | IS_DELTA | IS_SHORT
- }
- else
- {
- $number = ($self->[1]*12+$self->[2])*31+$self->[3];
- }
- }
- else # is_long
- {
- if (ref($format) eq 'CODE')
- {
- $number = &{$format}( $self, 0x03 ); # = TO_NUMBER | IS_DELTA | IS_LONG
- }
- elsif ($format == 2)
- {
- $number = ($self->[1]*12+$self->[2])*31+$self->[3] +
- ((($self->[4]*60+$self->[5])*60+$self->[6])/86400);
- }
- else
- {
- local($_);
- $sign = 0;
- @temp = @{$self}[3..6];
- $temp[0] += ($self->[1] * 12 + $self->[2]) * 31;
- @temp = map( $_ < 0 ? $sign = -$_ : $_, Normalize_DHMS(@temp) );
- $number = sprintf( "%s%d.%02d%02d%02d", $sign ? '-' : '', @temp );
- }
- }
- }
- else # is_date
- {
- if (@{$self} == 4) # is_short
- {
- if (ref($format) eq 'CODE')
- {
- $number = &{$format}( $self, 0x00 ); # = TO_NUMBER | IS_DATE | IS_SHORT
- }
- elsif ($format == 2 or $format == 1)
- {
- $number = Date_to_Days( @{$self}[1..3] );
- }
- else
- {
- $number = sprintf( "%04d%02d%02d",
- @{$self}[1..3] );
- }
- }
- else # is_long
- {
- if (ref($format) eq 'CODE')
- {
- $number = &{$format}( $self, 0x01 ); # = TO_NUMBER | IS_DATE | IS_LONG
- }
- elsif ($format == 2)
- {
- $number = Date_to_Days( @{$self}[1..3] ) +
- ((($self->[4]*60+$self->[5])*60+$self->[6])/86400);
- }
- elsif ($format == 1)
- {
- $number = Date_to_Days( @{$self}[1..3] ) .
- sprintf( ".%02d%02d%02d", @{$self}[4..6] );
- }
- else
- {
- $number = sprintf( "%04d%02d%02d.%02d%02d%02d",
- @{$self}[1..6] );
- }
- }
- }
- };
- if ($@)
- {
- $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
- $@ =~ s!\s+at\s+\S.*\s*$!!;
- croak($@);
- }
- return $number;
- }
- return undef;
- }
-
- sub string
- {
- my($self,$format,$language) = @_;
- my($restore,$string);
-
- if ($self->is_valid())
- {
- eval
- {
- if (defined($language) and $language ne '') # because of overloading!
- {
- if ($language =~ /^\d+$/) { $restore = Language($language); }
- else { $restore = Language(Decode_Language($language)); }
- }
- else
- {
- if (defined $self->[0][3]) { $restore = Language($self->[0][3]); }
- else { $restore = undef; }
- }
- };
- if ($@)
- {
- $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
- $@ =~ s!\s+at\s+\S.*\s*$!!;
- croak($@);
- }
- eval
- {
- if ($self->[0][0]) # is_delta
- {
- $format = defined($self->[0][1]) ? $self->[0][1] : $DELTA_FORMAT
- unless (defined $format); # because of overloading!
- if (@{$self} == 4) # is_short
- {
- if (ref($format) eq 'CODE')
- {
- $string = &{$format}( $self, 0x06 ); # = TO_STRING | IS_DELTA | IS_SHORT
- }
- elsif ($format == 3)
- {
- $string = sprintf( "%+d Y %+d M %+d D",
- @{$self}[1..3] );
- }
- elsif ($format == 2)
- {
- $string = sprintf( "%+dY %+dM %+dD",
- @{$self}[1..3] );
- }
- elsif ($format == 1)
- {
- $string = sprintf( "%+d %+d %+d",
- @{$self}[1..3] );
- }
- else
- {
- $string = sprintf( "%+d%+d%+d",
- @{$self}[1..3] );
- }
- }
- else # is_long
- {
- if (ref($format) eq 'CODE')
- {
- $string = &{$format}( $self, 0x07 ); # = TO_STRING | IS_DELTA | IS_LONG
- }
- elsif ($format == 3)
- {
- $string = sprintf( "%+d Y %+d M %+d D %+d h %+d m %+d s",
- @{$self}[1..6] );
- }
- elsif ($format == 2)
- {
- $string = sprintf( "%+dY %+dM %+dD %+dh %+dm %+ds",
- @{$self}[1..6] );
- }
- elsif ($format == 1)
- {
- $string = sprintf( "%+d %+d %+d %+d %+d %+d",
- @{$self}[1..6] );
- }
- else
- {
- $string = sprintf( "%+d%+d%+d%+d%+d%+d",
- @{$self}[1..6] );
- }
- }
- }
- else # is_date
- {
- $format = defined($self->[0][2]) ? $self->[0][2] : $DATE_FORMAT
- unless (defined $format); # because of overloading!
- if (@{$self} == 4) # is_short
- {
- if (ref($format) eq 'CODE')
- {
- $string = &{$format}( $self, 0x04 ); # = TO_STRING | IS_DATE | IS_SHORT
- }
- elsif ($format == 3)
- {
- $string = Date_to_Text_Long( @{$self}[1..3] );
- }
- elsif ($format == 2)
- {
- $string = Date_to_Text( @{$self}[1..3] );
- }
- elsif ($format == 1)
- {
- $string = sprintf( "%02d-%.3s-%04d",
- $self->[3],
- Month_to_Text($self->[2]),
- $self->[1] );
- }
- else
- {
- $string = sprintf( "%04d%02d%02d",
- @{$self}[1..3] );
- }
- }
- else # is_long
- {
- if (ref($format) eq 'CODE')
- {
- $string = &{$format}( $self, 0x05 ); # = TO_STRING | IS_DATE | IS_LONG
- }
- elsif ($format == 3)
- {
- $string = Date_to_Text_Long( @{$self}[1..3] ) .
- sprintf( " %02d:%02d:%02d", @{$self}[4..6] );
- }
- elsif ($format == 2)
- {
- $string = Date_to_Text( @{$self}[1..3] ) .
- sprintf( " %02d:%02d:%02d", @{$self}[4..6] );
- }
- elsif ($format == 1)
- {
- $string = sprintf( "%02d-%.3s-%04d %02d:%02d:%02d",
- $self->[3],
- Month_to_Text($self->[2]),
- $self->[1],
- @{$self}[4..6] );
- }
- else
- {
- $string = sprintf( "%04d%02d%02d%02d%02d%02d",
- @{$self}[1..6] );
- }
- }
- }
- };
- Language($restore) if (defined $restore);
- if ($@)
- {
- $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
- $@ =~ s!\s+at\s+\S.*\s*$!!;
- croak($@);
- }
- return $string;
- }
- return undef;
- }
-
- sub _process_
- {
- my($self,$this,$flag,$code) = @_;
- my($result,$val1,$val2,$len1,$len2,$last,$item);
-
- croak("invalid date/time") unless ($self->is_valid());
- if ($code == 0)
- {
- croak("can't apply unary minus to a date")
- unless ($self->is_delta());
- $result = $self->new();
- $result->[0][0] = $self->[0][0];
- for ( $item = 1; $item < @{$self}; $item++ )
- {
- $result->[$item] = -$self->[$item];
- }
- return $result;
- }
- if (defined $this and ref($this) =~ /[^:]::[^:]/)
- {
- croak("invalid date/time") unless ($this->is_valid());
- }
- elsif (defined $this and ref($this) eq 'ARRAY')
- {
- if (@{$this} == 3 or @{$this} == 6)
- {
- if ($code == 6)
- {
- $this = $self->new(0,@{$this});
- }
- elsif ($code == 5)
- {
- $this = $self->new($self->is_date(),@{$this});
- }
- else
- {
- $this = $self->new($self->is_delta(),@{$this});
- }
- }
- else
- {
- $this = $self->new(@{$this});
- }
- croak("invalid date/time") unless ($this->is_valid());
- }
- elsif (defined $this and not ref($this))
- {
- $this = $self->new(1,0,0,$this || 0);
- croak("invalid date/time") unless ($this->is_valid());
- }
- else { croak("illegal operand type"); }
- $val1 = $self->is_date();
- $val2 = $this->is_date();
- if ($code == 6 or $code == 5)
- {
- if ($code == 6)
- {
- croak("can't subtract a date from a delta vector")
- if ((not $val1 and $val2 and not $flag) or
- ($val1 and not $val2 and $flag));
- }
- else
- {
- croak("can't add two dates")
- if ($val1 and $val2);
- }
- $len1 = $self->is_long();
- $len2 = $this->is_long();
- if ($len1 or $len2) { $last = 7; }
- else { $last = 4; }
- if (defined $flag) { $result = $self->new((0) x $last); }
- else { $result = $self; }
- if (not $val1 and not $val2)
- {
- $result->[0][0] = 1;
- for ( $item = 1; $item < $last; $item++ )
- {
- if ($code == 6)
- {
- if ($flag)
- {
- $result->[$item] =
- ($this->[$item] || 0) -
- ($self->[$item] || 0);
- }
- else
- {
- $result->[$item] =
- ($self->[$item] || 0) -
- ($this->[$item] || 0);
- }
- }
- else
- {
- $result->[$item] =
- ($self->[$item] || 0) +
- ($this->[$item] || 0);
- }
- }
- }
- return ($result,$this,$val1,$val2,$len1,$len2);
- }
- elsif ($code <= 4 and $code >= 1)
- {
- croak("can't compare a date and a delta vector")
- if ($val1 xor $val2);
- if ($code >= 3)
- {
- if ($code == 4) { $last = 7; }
- else { $last = 4; }
- $result = 1;
- ITEM:
- for ( $item = 1; $item < $last; $item++ )
- {
- if (($self->[$item] || 0) !=
- ($this->[$item] || 0))
- { $result = 0; last ITEM; }
- }
- return $result;
- }
- else # ($code <= 2)
- {
- # croak("can't compare two delta vectors")
- # if (not $val1 and not $val2);
- if ($code == 2)
- {
- $len1 = $self->number();
- $len2 = $this->number();
- }
- else
- {
- $len1 = int($self->number());
- $len2 = int($this->number());
- }
- if ($flag) { return $len2 <=> $len1; }
- else { return $len1 <=> $len2; }
- }
- }
- else { croak("unexpected internal error; please contact author"); }
- }
-
- sub _unary_minus_
- {
- my($self,$this,$flag) = @_;
-
- return $self->_process_($this,$flag,0);
- }
-
- sub _compare_date_
- {
- my($self,$this,$flag) = @_;
-
- return $self->_process_($this,$flag,1);
- }
-
- sub _compare_date_time_
- {
- my($self,$this,$flag) = @_;
-
- return $self->_process_($this,$flag,2);
- }
-
- sub _equal_date_
- {
- my($self,$this,$flag) = @_;
-
- return $self->_process_($this,$flag,3);
- }
-
- sub _not_equal_date_
- {
- my($self,$this,$flag) = @_;
-
- return $self->_process_($this,$flag,3) ^ 1;
- }
-
- sub _equal_date_time_
- {
- my($self,$this,$flag) = @_;
-
- return $self->_process_($this,$flag,4);
- }
-
- sub _not_equal_date_time_
- {
- my($self,$this,$flag) = @_;
-
- return $self->_process_($this,$flag,4) ^ 1;
- }
-
- sub _date_time_
- {
- my($self) = @_;
-
- if (@{$self} == 7) { return (@{$self}[1..6]); }
- else { return (@{$self}[1..3],0,0,0); }
- }
-
- sub _add_
- {
- my($result,$self,$this,$flag,$val1,$val2,$len1,$len2) = @_;
-
- if ($val1) # date + delta => date
- {
- if ($len1 or $len2)
- {
- splice( @{$result}, 1, 6,
- Add_Delta_YMDHMS( $self->_date_time_(),
- $this->_date_time_() ) );
- }
- else # short
- {
- splice( @{$result}, 1, 3,
- Add_Delta_YMD( @{$self}[1..3], @{$this}[1..3] ) );
- }
- }
- else # delta + date => date
- {
- if ($len1 or $len2)
- {
- splice( @{$result}, 1, 6,
- Add_Delta_YMDHMS( $this->_date_time_(),
- $self->_date_time_() ) );
- }
- else # short
- {
- splice( @{$result}, 1, 3,
- Add_Delta_YMD( @{$this}[1..3], @{$self}[1..3] ) );
- }
- carp("implicitly changed object type from delta vector to date")
- if (not defined $flag and $^W);
- }
- $result->[0][0] = 0;
- }
-
- sub _plus_
- {
- my($self,$this,$flag) = @_;
- my($result,$val1,$val2,$len1,$len2);
-
- ($result,$this,$val1,$val2,$len1,$len2) = $self->_process_($this,$flag,5);
- if ($val1 or $val2)
- {
- $result->_add_($self,$this,$flag,$val1,$val2,$len1,$len2);
- }
- return $result;
- }
-
- sub _minus_
- {
- my($self,$this,$flag) = @_;
- my($result,$val1,$val2,$len1,$len2,$temp,$item);
-
- ($result,$this,$val1,$val2,$len1,$len2) = $self->_process_($this,$flag,6);
- if ($val1 or $val2)
- {
- if ($val1 and $val2) # date - date => delta
- {
- if ($len1 or $len2)
- {
- if ($ACCURATE_MODE)
- {
- if ($flag)
- {
- splice( @{$result}, 1, 6, 0, 0,
- Delta_DHMS( $self->_date_time_(),
- $this->_date_time_() ) );
- }
- else
- {
- splice( @{$result}, 1, 6, 0, 0,
- Delta_DHMS( $this->_date_time_(),
- $self->_date_time_() ) );
- }
- }
- else # YMD_MODE
- {
- if ($flag)
- {
- splice( @{$result}, 1, 6,
- Delta_YMDHMS( $self->_date_time_(),
- $this->_date_time_() ) );
- }
- else
- {
- splice( @{$result}, 1, 6,
- Delta_YMDHMS( $this->_date_time_(),
- $self->_date_time_() ) );
- }
- }
- }
- else # short
- {
- if ($ACCURATE_MODE)
- {
- if ($flag)
- {
- splice( @{$result}, 1, 3, 0, 0,
- Delta_Days( @{$self}[1..3], @{$this}[1..3] ) );
- }
- else
- {
- splice( @{$result}, 1, 3, 0, 0,
- Delta_Days( @{$this}[1..3], @{$self}[1..3] ) );
- }
- }
- else # YMD_MODE
- {
- if ($flag)
- {
- splice( @{$result}, 1, 3,
- Delta_YMD( @{$self}[1..3], @{$this}[1..3] ) );
- }
- else
- {
- splice( @{$result}, 1, 3,
- Delta_YMD( @{$this}[1..3], @{$self}[1..3] ) );
- }
- }
- }
- carp("implicitly changed object type from date to delta vector")
- if (not defined $flag and $^W);
- $result->[0][0] = 1;
- }
- else # date - delta => date
- {
- if ($val1)
- {
- $temp = $this->new();
- $temp->[0][0] = $this->[0][0];
- for ( $item = 1; $item < @{$this}; $item++ )
- {
- $temp->[$item] = -$this->[$item];
- }
- $result->_add_($self,$temp,$flag,$val1,$val2,$len1,$len2);
- }
- else
- {
- $temp = $self->new();
- $temp->[0][0] = $self->[0][0];
- for ( $item = 1; $item < @{$self}; $item++ )
- {
- $temp->[$item] = -$self->[$item];
- }
- $result->_add_($temp,$this,$flag,$val1,$val2,$len1,$len2);
- }
- }
- }
- return $result;
- }
-
- sub _plus_equal_
- {
- my($self,$this) = @_;
-
- return $self->_plus_($this,undef);
- }
-
- sub _minus_equal_
- {
- my($self,$this) = @_;
-
- return $self->_minus_($this,undef);
- }
-
- sub _increment_
- {
- my($self) = @_;
-
- return $self->_plus_(1,undef);
- }
-
- sub _decrement_
- {
- my($self) = @_;
-
- return $self->_minus_(1,undef);
- }
-
- 1;
-
- __END__
-
-