# TimeFormat convert UTC dates to seconds (date2sec) and # seconds to UTC dates (sec2date) in a defined format. # Accepted input dates for &date2sec() are # 2005-03-28 12:00:00.001 # 2005-03-28 # 2005-102 12:00:00 # 2005-102 # 2005102 12:00:00 # 2005102 # 2005,100,12:10:00 # 2005,100 12:10:00.001 package TimeFormat ; use strict ; use Time::Local qw(timegm_nocheck); use POSIX 'strftime'; # convert seconds to a formatted date require Exporter ; #our $SECONDS ; # set when date2sec is called our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $Verbose, $FORMAT) ; @ISA = qw(Exporter); @EXPORT = (); @EXPORT_OK = qw( sec2date date2sec current2sec last_julian_day remove_time format ) ; %EXPORT_TAGS = ( Default => [qw(&date2sec)], Both => [qw(&date2sec &sec2date)], All => [qw(&date2sec &sec2date ¤t2sec &last_julian_day &remove_time &format)]); $VERSION = 1.0 ; $Verbose = 0 ; # This variable is used for the conversion between dates $FORMAT = "%Y-%m-%d %H:%M:%S.%q" ; # should be set via format() # %Y - year including century or %y - year within century (00-99) # %m - month (1-12) # %d - day of month (1-31) # %j - julian day (000-366) # %H - hour (00-23) or %I - hour (01-12) # %M - minute (00-59) # %S - second (00-59) # %q - milli second (000-999) (not in the documentation) # %s - epoch time (xxxxxxxxxxx.xxx) sub remove_time { my $sec = shift ; &date2sec( sec2date($sec,"%Y%j") ) ; } sub last_julian_day { my $year = shift ; &sec2date(date2sec("$year-12-31"),"%j") ; } sub current2sec { return &date2sec( localtime() ) ; } # This function accepts epoch-seconds and returns a formatted date. sub sec2date { my ($sec, $fmt) = @_; $fmt = $FORMAT if ! $fmt ; # check input format if ( $sec !~ /^\d+(?:\.\d+)?$/ ) { $sec = &date2sec($sec) ; } # is input format correct ? return $sec if ($sec !~ /^\d+(?:\.\d+)?$/) ; ## fractional part of $sec, rounded to 3 digits my $milli = sprintf "%03.0f", 1000 * ($sec - int $sec); # add mili-seconds (%q) $fmt =~ s/%q/$milli/g; # change output-format for milli-seconds strftime $fmt, gmtime(int $sec); #strftime $fmt, localtime(int $sec); } # converts a date to epoch seconds sub date2sec { my $time = undef ; if ( @_ > 1 ) { $time = sprintf ("%d-%.3d %.2d:%.2d:%.2d",(1900 + $_[5]),($_[7]+1),$_[2],$_[1],$_[0]) ; } else { $time = shift ; } return undef if ! defined $time ; my $seconds ; # decl. of vars. my ( $year, $month, $day, $julian, $hour, $minute, $second, $mili) ; # convert year-only-date $time .= "-001" if ( length($time) == 4) ; # date is already in seconds if ( length($time) != 7 && $time =~ /^ \d+ # seconds (?: \.\d+ # milli-seconds )? $/xg ) { $seconds = $time ; } # split date ( with a julian day) # elsif ( $time =~ /\d{4}(?:[-,])?(\d{3})[\s{0,},](\d\d:\d\d:\d\d)?/ ) { elsif ( $time =~ /\d{4}(?:[-,])?(\d{3})\b/ ) { ( $year, $julian, $hour, $minute, $second, $mili ) = ( $time =~ m/ (\d{4}) # year (?: # group the day - time portions (?: [-,] # year and julian day sep. with a , or - )? (\d{1,3}) # julian day (?: # group the time portions [\s+,] # date and time sep. by whitespaces or , (\d\d) # hour : (\d\d) # minute : (\d\d) # second + fractions (?: (\.\d+) )? )? # time is optional )? # day - time is optional /xg ); $seconds = &timegm_nocheck($second,$minute,$hour,$julian,0,$year-1900) + $mili ; } # (date contains month and day) elsif ( $time =~ /\d{4}-\d{2}-\d{2}\s{0,}?(\d\d:\d\d:\d\d)?(?:\.\d+)?/ ) { ( $year, $month, $day, $hour, $minute, $second, $mili ) = ( $time =~ m/ (\d{4}) # year - # (\d{2}) # month - # (\d{2}) # day (?: # group the time portions \s+ # one or more whitespace (\d\d) # hour : (\d\d) # minute : (\d\d) # second (?: (\.\d+) )? )? # time is optional /xg ); print STDERR __PACKAGE__." Error: Month out of range: $month\n" if $month > 12; return undef unless $month < 13 && defined $year ; # only check month $seconds = &timegm_nocheck($second,$minute,$hour,$day,$month-1,$year-1900) + $mili ; } else { return undef ; } # input date could not be parsed return $seconds ; } # predefine the output format sub format { $FORMAT = shift ; return 1 ; # OK } 1; __END__