##---------------------------------------------------------------------------##
## $Id: mhtime.pl,v 2.10 2001/09/17 16:09:35 ehood Exp $
## Earl Hood mhonarc@mhonarc.org
## Time related routines for mhonarc
##---------------------------------------------------------------------------##
## Copyright (C) 1996-1999 Earl Hood, mhonarc@mhonarc.org
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
##---------------------------------------------------------------------------##
##---------------------------------------------------------------------------##
## Date variables for date routines
'jan', 0, 'feb', 1, 'mar', 2, 'apr', 3, 'may', 4, 'jun', 5, 'jul', 6,
'aug', 7, 'sep', 8, 'oct', 9, 'nov', 10, 'dec', 11,
'january', 0, 'february', 1, 'march', 2, 'april', 3,
'may', 4, 'june', 5, 'july', 6, 'august', 7,
'september', 8, 'october', 9, 'november', 10, 'december', 11,
'sun', 0, 'mon', 1, 'tue', 2, 'wed', 3, 'thu', 4, 'fri', 5, 'sat', 6,
'sunday', 0, 'monday', 1, 'tuesday', 2, 'wednesday', 3, 'thursday', 4,
'friday', 5, 'saturday', 6,
my @wdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
my @Wdays = ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
my @mons = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
'Sep', 'Oct', 'Nov', 'Dec');
my @Mons = ('January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November',
## The following used in parse_date() regexes
my $p_weekdays = 'Mon|Tue|Wed|Thu|Fri|Sat|Sun';
my $p_Weekdays = 'Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday';
my $p_months = 'Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec';
my $p_Months = 'January|February|March|April|May|June|July|August'.
'|September|October|November|December';
my $p_hrminsec = '\d{1,2}:\d\d:\d\d';
my $p_hrmin = '\d{1,2}:\d\d';
my $p_year = '\d\d\d\d|\d\d';
##---------------------------------------------------------------------------
## Set weekday and month names. This allows localization of
my($in_wd, $in_Wd, $in_m, $in_M) = @_;
@wdays = @
$in_wd if defined($in_wd) && scalar(@
$in_wd);
@Wdays = @
$in_Wd if defined($in_Wd) && scalar(@
$in_Wd);
@mons = @
$in_m if defined($in_m) && scalar(@
$in_m);
@Mons = @
$in_M if defined($in_M) && scalar(@
$in_M);
##---------------------------------------------------------------------------
## Get date in date(1)-like format. $local flag is if local time
&time2str
('', time, $_[0]);
##---------------------------------------------------------------------------
## Convert a calander time to a string.
my($fmt, $time, $local) = @_;
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
($local ?
localtime($time) : gmtime($time));
## If format string blank, use default format
$fmt = '%a %b %d %H:%M:%S';
$fmt .= ' GMT' unless $local;
last POSIXMODCHK
unless $POSIXstrftime;
last POSIXMODCHK
if ($@
) || !defined(&POSIX
::strftime
);
return POSIX
::strftime
($fmt, $sec,$min,$hour,$mday,$mon,$year,
## Get here, we have to do it ourselves.
$yearfull = $year + 1900;
$hour12 = $hour > 12 ?
$hour-12 : $hour;
$fmt =~ s/\%c/\%a \%b \%d \%H:\%M:\%S \%Y/g;
$fmt =~ s/\%a/$wdays[$wday]/g;
$fmt =~ s/\%A/$Wdays[$wday]/g;
$fmt =~ s/\%[bh]/$mons[$mon]/g;
$fmt =~ s/\%B/$Mons[$mon]/g;
$sec = sprintf("%02d", $sec);
$min = sprintf("%02d", $min);
$hour = sprintf("%02d", $hour);
$hour12 = sprintf("%02d", $hour12);
$mday = sprintf("%02d", $mday);
$mon = sprintf("%02d", $mon+1);
$year = sprintf("%02d", $year);
$yearfull = sprintf("%04d", $yearfull);
$wday = sprintf("%02d", $wday+1);
$yday = sprintf("%03d", $yday);
$fmt =~ s/\%p/am/g if ($hour < 12);
$fmt =~ s/\%p/pm/g if ($hour >= 12);
$fmt =~ s/\%P/AM/g if ($hour < 12);
$fmt =~ s/\%P/PM/g if ($hour >= 12);
$fmt =~ s/\%Y/$yearfull/g;
##---------------------------------------------------------------------------
## parse_date takes a string date specified like the output of
## date(1) into its components. Parsing a string for a date is
## ugly since we have to watch out for differing formats.
## The following date formats are looked for:
## Wdy DD Mon YY HH:MM:SS Zone
## DD Mon YY HH:MM:SS Zone
## Wdy Mon DD HH:MM:SS Zone YYYY
## Wdy Mon DD HH:MM:SS YYYY
## The routine keys off of the day of time field "HH:MM:SS" and
## scans realtive to its location.
## If the parse fails, a null array is returned. Thus the routine
## may be used as follows:
## if ( (@x = &parse_date($date)) ) { Success }
## If success the array contents are as follows:
## (Weekday (0-6), Day of the month (1-31), Month (0-11),
## Year, Hour, Minutes, Seconds, Time Zone)
## Contributer(s): Frank J. Manion <FJ_Manion@fccc.edu>
my($wday, $mday, $mon, $yr, $time, $hr, $min, $sec, $zone);
# Try to find the date by focusing on the "\d\d:\d\d" field.
# All parsing is then done relative to this location.
$date =~ s/^\s+//; $time = ""; $rest = "";
# Don't use $p_hrmin(sec) vars in split due to bug in perl 5.003.
($start, $time, $rest) = split(/(\b\d{1,2}:\d\d:\d\d)/o, $date, 2);
($start, $time, $rest) = split(/(\b\d{1,2}:\d\d)/o, $date, 2)
if !defined($time) or $time eq "";
unless defined($time) and $time ne "";
($hr, $min, $sec) = split(/:/, $time);
$sec = 0 unless $sec; # Sometimes seconds not defined
# Strip $start of all but the last 4 tokens,
# and stuff all tokens in $rest into @array
@array = split(' ', $start);
$start = join(' ', ($#array-3 < 0) ?
@array[0..$#array] :
@array[$#array-3..$#array]);
@array = split(' ', $rest);
$rest = join(' ', ($#array >= 1) ?
@array[0..1] :
# Wdy DD Mon YY HH:MM:SS Zone
/($p_weekdays),*\s+($p_day)\s+($p_months)\s+($p_year)$/io ) {
($wday, $mday, $mon, $yr, $zone) = ($1, $2, $3, $4, $array[0]);
# DD Mon YY HH:MM:SS Zone
} elsif ( $start =~ /($p_day)\s+($p_months)\s+($p_year)$/io ) {
($mday, $mon, $yr, $zone) = ($1, $2, $3, $array[0]);
# Wdy Mon DD HH:MM:SS Zone YYYY
# Wdy Mon DD HH:MM:SS YYYY
} elsif ( $start =~ /($p_weekdays),?\s+($p_months)\s+($p_day)$/io ) {
($wday, $mon, $mday) = ($1, $2, $3);
if ( $rest =~ /^(\S+)\s+($p_year)/o ) { # Zone YYYY
} elsif ( $rest =~ /^($p_year)/o ) { # YYYY
} else { # zilch, use current year
warn "Warning: No year in date ($date), using current\n";
$yr = (localtime(time))[5];
# Weekday Month DD YYYY HH:MM Zone
/($p_Weekdays),?\s+($p_Months)\s+($p_day),?\s+($p_year)$/ ) {
($wday, $mon, $mday, $yr, $zone) = ($1, $2, $3, $4, $array[0]);
# Modify month and weekday for lookup
$mon = $Month2Num{lc $mon} if defined($mon);
$wday = $WDay2Num{lc $wday} if defined($wday);
($wday, $mday, $mon, $yr, $hr, $min, $sec, $zone);
##---------------------------------------------------------------------------
## Routine to convert time in seconds to a month, day, and year
## format. The format can be "mmddyy", "yymmdd", "ddmmyy". The
## year can be specifed as "yyyy" if a 4 digit year is needed.
my($time, $fmt) = ($_[0], $_[1]);
my($day,$mon,$year,$ylen,$tmp);
($day,$mon,$year) = (localtime($time))[3,4,5];
## Compute length for year field
substr($year, 0, 4 - $ylen) = '';
if ($fmt =~ /ddmmyy/i) { # DDMMYY
$tmp = sprintf("%02d/%02d/%0${ylen}d", $day, $mon+1, $year);
} elsif ($fmt =~ /yymmdd/i) { # YYMMDD
$tmp = sprintf("%0${ylen}d/%02d/%02d", $year, $mon+1, $day);
$tmp = sprintf("%02d/%02d/%0${ylen}d", $mon+1, $day, $year);
##---------------------------------------------------------------------------
## zone_offset_to_secs translates a [+-]HHMM zone offset to
sub zone_offset_to_secs
{
## Check if just an hour specification
$min = substr($off, -2, 2);
substr($off, -2, 2) = ""; # Just leave hour in $off
$sign * (($off * 3600) + ($min * 60));
##---------------------------------------------------------------------------##