[comp.lang.perl] reverse of localtime

pem@frankland-river.aaii.oz.au (Paul E. Maisano) (02/28/90)

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.]

My unix manual (on SUN/OS) says there is a timelocal() function.
Is this a worthwhile addition to perl ? I can't see a simple way of
doing it in perl.

I was originally going to write the program in C for speed reasons but
I think perl would be fast enough. 

I don't really want to write it in C but... :-(

------------------
Paul E. Maisano
Australian Artificial Intelligence Institute
1 Grattan St. Carlton, Vic. 3053, Australia
Ph: +613 663-7922  Fax: +613 663-7937
Email: pem@aaii.oz.au

lisch@uunet.uu.net (Ray Lischner) (03/01/90)

Paul E. Maisano writes:
 > My unix manual (on SUN/OS) says there is a timelocal() function.
 > Is this a worthwhile addition to perl ? I can't see a simple way of
 > doing it in perl.
 > 
 > I was originally going to write the program in C for speed reasons but
 > I think perl would be fast enough. 
 > 
 > I don't really want to write it in C but... :-(

The timelocal() function is not standard UNIX or ANSI C.  My old copy
of the ANSI draft mentions mktime() to build a time_t from a struct tm*.
Regardless of name, the functionality would be nice to have in Perl.

For those (like me) without  timelocal(), mktime(), etc., there is
a C version of localtime(), timelocal(), ctime(), et al., in the
comp.sources.unix archives on UUNET.

richard@pegasus.com (Richard Foulk) (03/04/90)

>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.]
>
>My unix manual (on SUN/OS) says there is a timelocal() function.
>Is this a worthwhile addition to perl ? I can't see a simple way of
>doing it in perl.

I've been real tempted to stuff ctime(1) and getdate(1) from the
Cnews distribution into perl.  Doing things like accounting and
such they are very handy, but pretty costly to invoke from perl.

-- 
Richard Foulk		richard@pegasus.com

viktor@melon.Princeton.EDU (Viktor Dukhovni) (03/05/90)

-----------------Cut------------------
#! /usr/bin/perl

;#
;#  depending on whether localtime takes signed or unsigned args,
;# this should work for years between ~1902 and ~2038 or
;# ~1970 and ~2106

sub cmpdate {
  local($tse,$tmi,$tho,$tda,$tmo,$tyr,$foo1,$foo2,$foo3,
         $se,$mi,$ho,$da,$mo,$yr) = @_;

  if ( $tyr != $yr ) {
    return($tyr - $yr) ;
  } 
  if ( $tmo != $mo ) {
    return($tmo - $mo) ;
  } 
  if ( $tda != $da ) {
    return($tda - $da) ;
  } 
  if ( $tho != $ho ) {
    return($tho - $ho) ;
  } 
  if ( $tmi != $mi ) {
    return($tmi - $mi) ;
  } 
  if ( $tse != $se ) {
    return($tse - $se) ;
  } 
}

sub unctime {
  local(@args) = @_;
  local($bit);
  local($t) = 0x0;
  local($maxtime,$mintime) ;

  if (do cmpdate(localtime(0x80000000),localtime(0)) > 0 ) {
    $maxtime=0x80000000;
    $mintime=0x0;
    $bit=0x80000000;
  } else { 
    $maxtime=0x7fffffff;
    $mintime=0x80000000;
    $bit=0x40000000;
    $t=$mintime if(do cmpdate(localtime(0),@args) > 0);
  }
  die "Date out of range\n" if (do cmpdate(localtime($maxtime),@args) < 0);
  die "Date out of range\n" if (do cmpdate(localtime($mintime),@args) > 0);

  while ( $bit != 0 ) {
    $t|=$bit if (do cmpdate(localtime($t|$bit),@args) <= 0) ;
    $bit >>= 1;
  }
  $t;
}

printf stderr "Please enter se/mi/ho/da/mo/yr ";
chop($date = <stdin>) ;
$time=do unctime(split(/\//,$date)) ;
print "$time <- ",join("/",localtime($time)),"\n" ;
----------------Cut---------------

-- 
	Viktor Dukhovni <viktor%math@princeton.edu>	: ARPA
		<...!uunet!princeton!math!viktor>	: UUCP