[comp.lang.perl] What time

hakanson@ogicse.ogi.edu (Marion Hakanson) (02/05/91)

Larry & folks,

Here's an updated version of lib/ctime.pl, based on what was
distributed as of 3.044.  This new version corrects a long-standing
bug in the use of the TZ environment variable.  Used to be that if TZ
was undefined, ctime.pl would use GMT, and if it was defined but null,
local time was assumed.  These two behaviors needed to be swapped, in
order to conform with what is documented (and what actually happens)
on real (C-based) ctime(2) and localtime(2) calls.  My apologies for
not getting it right the first time -- my excuse is that I didn't have
access to modern machines/OS's back then.

There's also a really ugly (but tested correct) regex to interpret a
POSIX and/or SysV format TZ variable, in order to pull out the
standard or daylight timezone names, in most cases.  If ctime.pl
cannot pull the TZ variable apart, it prints it out in its entirety,
which what it used to do anyway.

Note that ctime.pl still cannot print out a timezone name if no TZ
variable is defined in the environment.  There is no portable way
to find this information, since Larry has steadfastly refused to
supply the real ctime(3) call to Perl users (dig, dig).  So, the
following seems to be the next best thing.  Enjoy.

=================================
;# ctime.pl is a simple Perl emulation for the well known ctime(3C) function.
;#
;# Waldemar Kebsch, Federal Republic of Germany, November 1988
;# kebsch.pad@nixpbe.UUCP
;# Modified March 1990, Feb 1991 to properly handle timezones
;#  $Id: ctime.pl,v 1.8 91/02/04 18:28:12 hakanson Exp $
;#   Marion Hakanson (hakanson@cse.ogi.edu)
;#   Oregon Graduate Institute of Science and Technology
;#
;# usage:
;#
;#     #include <ctime.pl>          # see the -P and -I option in perl.man
;#     $Date = &ctime(time);

CONFIG: {
    package ctime;

    @DoW = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
    @MoY = ('Jan','Feb','Mar','Apr','May','Jun',
	    'Jul','Aug','Sep','Oct','Nov','Dec');
}

sub ctime {
    package ctime;

    local($time) = @_;
    local($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);

    # Determine what time zone is in effect.
    # Use GMT if TZ is defined as null, local time if TZ undefined.
    # There's no portable way to find the system default timezone.

    $TZ = defined($ENV{'TZ'}) ? ( $ENV{'TZ'} ? $ENV{'TZ'} : 'GMT' ) : '';
    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
        ($TZ eq 'GMT') ? gmtime($time) : localtime($time);

    # Hack to deal with 'PST8PDT' format of TZ
    # Note that this can't deal with all the esoteric forms, but it
    # does recognize the most common: [:]STDoff[DST[off][,rule]]

    if($TZ=~/^([^:\d+\-,]{3,})([+-]?\d{1,2}(:\d{1,2}){0,2})([^\d+\-,]{3,})?/){
        $TZ = $isdst ? $4 : $1;
    }
    $TZ .= ' ' unless $TZ eq '';

    $year += ($year < 70) ? 2000 : 1900;
    sprintf("%s %s %2d %2d:%02d:%02d %s%4d\n",
      $DoW[$wday], $MoY[$mon], $mday, $hour, $min, $sec, $TZ, $year);
}
1;
=================================

-- 
Marion Hakanson         Domain: hakanson@cse.ogi.edu
                        UUCP  : {hp-pcd,tektronix}!ogicse!hakanson