package Util::Date; ############################################################################## # # DESCRIPTION: This class handles dates and times. It handles date # DESCRIPTION: formatting and conversion to and from mission time. # # HISTORY # HISTORY: $Log: Date.pm,v $ # HISTORY: Revision 1.3 2014/02/27 07:01:06 apsop # HISTORY: VERSION header now shows CVS Revision # HISTORY: # HISTORY: Revision 1.2 2006/08/01 20:35:34 apsop # HISTORY: Add in CVS history indicator. # HISTORY: # HISTORY: 1.0 -> 1.1 2000-07-18 # HISTORY: Fixed a bug where today's date was one day ahead, possibly # HISTORY: creating dates like June 31. # HISTORY: # HISTORY: 1.1 -> 1.2 2000-10-23 # HISTORY: Fixed a bug where seconds were set equal to minutes # HISTORY: # HISTORY: 1.2 -> 1.3 2003-07-10 # HISTORY Added mjd method # # VERSION: $Revision: 1.3 $ # ############################################################################## use Util::Ftool; use strict; ########################################################### # class data ########################################################### my $REFDATE=""; # reference date and time when converting to my $REFTIME=""; # seconds my $FILENAME=""; # Filename object my $LEAPFILE=""; # leapsecond table my %MONTH = ("01" => "January", "02" => "February", "03" => "March", "04" => "April", "05" => "May", "06" => "June", "07" => "July", "08" => "August", "09" => "September", "10" => "October", "11" => "November", "12" => "December" ); ########################################################################### # This constructor has three forms: # - new() initializes to the current local date and time # - new(yyyy-mm-dd, hh:mm:ss) initializes to the given date and time # - new(yyyy-mm-ddThh:mm:ss) initializes from the FITS keyword date format # - new(mission_time) initializes from the given mission time in seconds # since the reference time. ########################################################################### sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self={}; if( !@_ ) { ############################################################ # no arguments so initialize to today's local date and time ############################################################ my @time=gmtime(time); my $year =$time[5]+1900; my $month=sprintf("%02d",$time[4]+1); my $day =sprintf("%02d",$time[3] ); $self->{DATE} = "$year-$month-$day"; my $hours=sprintf("%02d",$time[2]); my $min =sprintf("%02d",$time[1]); my $sec =sprintf("%02d",$time[0]); $self->{TIME} = "$hours:$min:$sec"; } elsif( $_[0] =~ /^\d\d\d\d-\d\d-\d\d$/ ) { ################################### # first argument looks like a date ################################### $self->{DATE}=shift; $self->{TIME}=shift || "00:00:00"; } elsif($_[0] =~ /\d\d\d\d-\d\d-\d\dT/){ ###################################################### # looks like a FITS style yyyy-mm-ddThh:mm:ss format ###################################################### ($self->{DATE}, $self->{TIME}) = $_[0] =~ /^(.*)T(.*)$/; if( ! $self->{TIME} ) { $self->{TIME}="00:00:00"; } } else { ################################################################### # treat the first arg as a number of seconds since # the reference time ################################################################### if (not $LEAPFILE or not -f $LEAPFILE) { $LEAPFILE = $FILENAME->fetch_cal("leapsec"); } if($REFDATE && $REFTIME && $FILENAME) { ##################################################### # we have all the class data we need to run sec2time ##################################################### my $sec2time=Util::Ftool->new("sec2time") ->params({offset => $_[0], leapfile => $LEAPFILE, datezero => $REFDATE, timezero => $REFTIME}) ->verbose(0) ->run(); my $parfile=$sec2time->parfile(); $self->{DATE}=$parfile->read("date"); $self->{TIME}=$parfile->read("time"); ##################################### # clip off decimal seconds ##################################### $self->{TIME} =~ s/\..*$//; } else { ################################################## # the class has not been initialized, so # a message to stderr is probably the best thing ################################################## print STDERR "Date class not properly initialized:\n"; print STDERR "REFDATE=|$REFDATE|\n"; print STDERR "REFTIME=|$REFTIME|\n"; print STDERR "FILENAME=|$FILENAME|\n"; } } bless($self,$class); return $self; } # end of constructor ################### # ACCESSORS: ################### ######################################################################### # the following method initializes all the class data needed for conversions # between dates and mission time in seconds. # Refdate and reftime and the date and time at zero elapsed seconds. # Leapsec is the name of the leap second calibration file. ######################################################################### sub init_class { #(refdate, reftime, leapsec) my $self=shift; $self->refdate(shift); $self->reftime(shift); $self->filename(shift); } ######################################################################## # get or set the reference date class data for date - time conversions ######################################################################## sub refdate { my $self = shift; if (@_) { $REFDATE = shift } return $REFDATE; } ######################################################################## # get or set the reference time class data for date - time conversions ######################################################################## sub reftime { my $self = shift; if (@_) { $REFTIME = shift } return $REFTIME; } ############################################################################# # get or set the leapsecond file name class data for date - time conversions ############################################################################# sub filename { my $self = shift; if (@_) { $FILENAME = shift } return $FILENAME; } ############################################################################# # return the date in yyyy-mm-dd format ############################################################################# sub date { my $self = shift; return $self->{DATE}; } ############################################################################# # return the time in hh:mm:ss format ############################################################################# sub time { my $self = shift; return $self->{TIME}; } ################################################################# # return the number of seconds since the reference date and time ################################################################# sub seconds { my $self=shift; my $leapsec = $FILENAME->fetch_cal("leapsec"); my $time2sec=Util::Ftool->new("time2sec") ->params({"date" => $self->{DATE}, "time" => $self->{TIME}, leapfile => $leapsec, datezero => $REFDATE, timezero => $REFTIME }) ->verbose(0) ->run(); return $time2sec->parfile()->read("offset"); } # end of seconds method ################################################################# # return the Modified Julian Day corresponding to this date # This implementation is not terribly efficient, since it first # converts the date to seconds and then to MJD ################################################################# sub mjd { my $self = shift; my $leapsec = $FILENAME->fetch_cal("leapsec"); my $seconds = $self->seconds(); my $sec2time = Util::Ftool->new("sec2time") ->params({offset => $seconds, leapfile => $leapsec, datezero => $REFDATE, timezero => $REFTIME}) ->verbose(0) ->run(); return $sec2time->parfile()->read("mjd"); } # end of mjd method ################################################## # parses the date into year, month and day fields. Returns these # as an array (year, month, day). ################################################## sub year_month_day { my $self=shift; return ($self->{DATE} =~ /(\d\d\d\d)-(\d\d)-(\d\d)/ ); } #################################### # print the the date in words #################################### sub in_words { my $self=shift; my ($year,$month,$day) = $self->year_month_day(); $day =~ s/^0*//; return "$MONTH{$month} $day, $year"; } 1;