merlyn@iwarp.intel.com (Randal Schwartz) (03/01/90)
In article <1176@frankland-river.aaii.oz.au>, pem@frankland-river (Paul E. Maisano) writes: | I am writing a perl program at the moment which is doing a lot of | manipulation of dates and times. | | I am maintaining a text file which contains dates such as 24/04/89 and | to manipulate these dates easily I would like to convert that to "the | number of seconds since Jan 1970". This is the reverse of what localtime() | does. [I can't keep the number of seconds in the file rather than the | date either since the file may be modified by hand.] Well, as a headstart, here's what I did for 'newslat', which had to convert a Usenet-standard date into an integer: %offset = ( 'Jan89', 0, 'Feb89', 31, 'Mar89', 59, 'Apr89', 90, 'May89', 120, 'Jun89', 151, 'Jul89', 181, 'Aug89', 212, 'Sep89', 243, 'Oct89', 273, 'Nov89', 304, 'Dec89', 334, 'Jan90', 365, 'Feb90', 396, 'Mar90', 425, 'Apr90', 456, 'May90', 486, 'Jun90', 516 ); # that'll do for a while ### lotsa code deleted here ### ### we're in a loop named ARTICLE, $article is a filename, and $_ is the ### string: "Date: 24 June 90 11:23:45 GMT" for example unless (/\s(\d\d?)\s+(\w\w\w)\w*\s+(\d\d)\s+(\d\d?):(\d\d):(\d\d)\s+GMT/) { /(.*)/; warn "$article: unknown date format: $1"; next ARTICLE; } ($day,$monthname,$year,$hour,$minute,$second) = ($1,$2,$3,$4,$5,$6); unless (defined($offset{$monthname . $year})) { warn "$article: unknown month/year: $monthname/$year"; next ARTICLE; } $when = ($offset{$monthname . $year}+$day-1)*86400 + $hour*3600 + $minute * 60 + $second + 599616000; At this point, $when has the UNIX "seconds past Jan 1 1970 midnite GMT" integer in it. This routine is reasonably fast... the key is to precompute the month/year offsets (I did it by hand :-) so that Perl has only to perform a simple table lookup. If you get a generic routine working, please forward it to me (or the net). I can also help you by email, if you need further assistance. $\="hacker,";$,="another ";print"Just ","Perl "; -- /=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\ | on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III | | merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn | \=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/
ktl@wag240.caltech.edu (Kian-Tat Lim) (03/01/90)
Here's something I put together for a perl-based backup
script. It only takes a specific date format, but it'll work until
2070 if your Unix uses an unsigned long for times. Things also get
hairy around standard/daylight changeover time; I haven't looked to
see if it works properly there.
===== CUT HERE =====
sub date2secs {
;# Convert output of "date" to seconds since Jan 1 1970 00:00:00
;# Derived from GNU tar (and others) getdate.y, though not nearly as
;# smart about differing formats
;# Call like this:
;# do "date2secs.pl";
;# chop($date = `date`);
;# $secs = &date2secs($date);
;# Days before first of each month
local(%month) = ("Jan",0,"Feb",31,"Mar",59,"Apr",90,"May",120,"Jun",151,
"Jul",181,"Aug",212,"Sep",243,"Oct",273,"Nov",304,"Dec",334);
;# Hours added to each zone to get GMT; single letters are military
local(%zone) = ("nst",3.5, "ast",4, "adt",3,
"est",5, "edt",4, "cst",6, "cdt",5,
"mst",7, "mdt",6, "pst",8, "pdt",7,
"yst",9, "ydt",8, "hst",10, "hdt",9,
"gmt",0, "bst",-1, "eet",0, "eest",-1,
"met",-1, "mest",-2, "wet",-2, "west",-3,
"jst",-9, "aest",-10, "aesst",-11,
"acst",-9.5, "acsst",-10.5, "awst",-8,
"a",1, "b",2, "c",3, "d",4, "e",5, "f",6, "g",7, "h",8,
"i",9, "k",10, "l",11, "m",12, "n",-1, "o",-2, "p",-3, "q",-4,
"r",-5, "s",-6, "t",-7, "u",-8, "v",-9, "w",-10,"x",-11,"y",-12,
"z",0
);
local($wday,$mm,$dd,$tm,$zz,$yy) = split(/ +/,$_[0]);
$zz =~ tr/A-Z/a-z/;
local($hr,$min,$sec) = split(/[:]/,$tm);
;# Note that the next line will fail in 2070 and the one after will
;# fail in 2101 -- but Unix's signed long for times fails in 2038!
;# We also fail to take into account dates before the epoch (1/1/1970).
$yy += 1900 if $yy < 100; $yy += 100 if $yy <= 69;
local($jdate) = 365 * ($yy - 1970) + int(($yy - 1970 + 1) / 4);
$jdate += $mdays{$mm} + $dd - 1;
$jdate++ if $mm ne "Jan" && $mm ne "Feb" && $yy % 4 == 0 &&
($yy % 100 != 0 || $yy % 400 == 0);
$jdate *= 86400;
$jdate += (($hr + $zone{$zz}) * 60 + $min) * 60 + $sec;
}
;# Return 1 to indicate successful 'do'
1;
===== CUT HERE =====
--
Kian-Tat Lim (ktl@wagvax.caltech.edu, KTL @ CITCHEM.BITNET, GEnie: K.LIM1)
ktl@wag240.caltech.edu (Kian-Tat Lim) (03/02/90)
[Thoroughly embarrassed...] There's a minor bug in the code I posted for local date to seconds since GMT conversion. The associative array %month should be renamed to %mdays to be consistent with its usage. Sorry! For those interested, here's a quickie test to make sure it's working: do 'date2secs.pl' || die "Couldn't load file.\n"; chop($date = `date`); print &date2secs($date)," ",time,"\n"; Of course, your `date` may not produce the same output ours does... -- Kian-Tat Lim (ktl@wagvax.caltech.edu, KTL @ CITCHEM.BITNET, GEnie: K.LIM1)