home *** CD-ROM | disk | FTP | other *** search
- ;#
- ;# Name
- ;# date.pl - Perl emulation of (the output side of) date(1)
- ;#
- ;# Synopsis
- ;# requirelude "date.pl";
- ;# $Date = &date(time);
- ;# $Date = &date(time, $format);
- ;#
- ;# Description
- ;# This package implements the output formatting functions of date(1) in
- ;# Perl. The format options are based on those supported by Ultrix 4.0
- ;# plus a couple of additions:
- ;#
- ;# %a abbreviated weekday name - Sun to Sat
- ;# %A full weekday name - Sunday to Saturday
- ;# %b abbreviated month name - Jan to Dec
- ;# %B full month name - January to December
- ;# %c date and time in local format [+]
- ;# %d day of month - 01 to 31
- ;# %D date as mm/dd/yy
- ;# %e day of month (space padded) - ` 1' to `31'
- ;# %h abbreviated month name - Jan to Dec
- ;# %H hour - 00 to 23
- ;# %I hour - 01 to 12
- ;# %j day of the year (Julian date) - 001 to 366
- ;# %m month of year - 01 to 12
- ;# %M minute - 00 to 59
- ;# %n insert a newline character
- ;# %p AM or PM
- ;# %r time in AM/PM notation
- ;# %R time as HH:MM
- ;# %S second - 00 to 59
- ;# %t insert a tab character
- ;# %T time as HH:MM:SS
- ;# %U week number, Sunday as first day of week - 00 to 53
- ;# %w day of week - 0 (Sunday) to 6
- ;# %W week number, Monday as first day of week - 00 to 53
- ;# %x date in local format [+]
- ;# %X time in local format [+]
- ;# %y last 2 digits of year - 00 to 99
- ;# %Y all 4 digits of year ~ 1700 to 2000 odd ?
- ;# %z time zone from TZ environment variable w/ a trailing space [*]
- ;# %Z time zone from TZ environment variable
- ;# %% insert a `%' character
- ;# %+ insert a `+' character [*]
- ;#
- ;# [*]: Not supported by date(1) but I wanted 'em.
- ;# [+]: These may need adjustment to fit local conventions, see below.
- ;#
- ;# For the sake of compatibility, a leading `+' in the format
- ;# specificaiton is removed if present.
- ;#
- ;# Remarks
- ;# An extension of `ctime.pl' by Waldemar Kebsch (kebsch.pad@nixpbe.UUCP),
- ;# as modified by Marion Hakanson (hakanson@ogicse.ogi.edu).
- ;#
- ;# Unlike date(1), unknown format tags are silently replaced by "".
- ;#
- ;# defaultTZ is a blatant hack, but I wanted to be able to get date(1)
- ;# like behaviour by default and there does'nt seem to be an easy (read
- ;# portable) way to get the local TZ name back...
- ;#
- ;# For a cheap date, try...
- ;#
- ;# #!/usr/local/bin/perl
- ;# require "date.pl";
- ;# exit print (&date(time, shift @ARGV) . "\n") ? 0 : 1;
- ;#
- ;# This package is redistributable under the same terms as apply to
- ;# the Perl 3.0 release. See the COPYING file in your Perl kit for
- ;# more information.
- ;#
- ;# Please send any bug reports or comments to tmcgonigal@gvc.com
- ;#
- ;# Modification History
- ;# Nmemonic Version Date Who
- ;#
- ;# NONE none 02feb91 Terry McGonigal (tmcgonigal@gvc.com)
- ;# Created from ctime.pl
- ;#
- ;# NONE none 07feb91 tmcgonigal
- ;# Added some of Marion Hakanson (hakanson@ogicse.ogi.edu)'s ctime.pl
- ;# TZ handling changes.
- ;#
- ;# NONE none 09feb91 tmcgonigal
- ;# Corrected week number calculations.
- ;#
- ;# SccsId = "%W% %E%"
- ;#
- package date;
-
- # Months of the year
- @MoY = ('January', 'Febuary', 'March', 'April', 'May', 'June',
- 'July', 'August', 'September','October', 'November', 'December');
-
- # days of the week
- @DoW = ('Sunday', 'Monday', 'Tuesday', 'Wednesday',
- 'Thursday', 'Friday', 'Saturday');
-
- # defaults
- $defaultTZ = 'EST'; # time zone (hack!)
- $defaultFMT = '%a %h %e %T %z%Y'; # format (ala date(1))
-
- # `local' formats
- $locTF = '%T'; # time (as HH:MM:SS)
- $locDF = '%D'; # date (as mm/dd/yy)
- $locDTF = '%a %b %d %T %Y'; # date/time (as dow mon dd HH:MM:SS yyy)
-
- # Time zone info
- $TZ; # wkno needs this info too
-
- # define the known format tags as associative keys with their associated
- # replacement strings as values. Each replacement string should be
- # an eval-able expresion assigning a value to $rep. These expressions are
- # eval-ed, then the value of $rep is substituted into the supplied
- # format (if any).
- %Tags = ( '%a', '($rep = $DoW[$wday])=~ s/^(...).*/\1/',# abbr. weekday name - Sun to Sat
- '%A', '$rep = $DoW[$wday]', # full weekday name - Sunday to Saturday
- '%b', '($rep = $MoY[$mon]) =~ s/^(...).*/\1/',# abbr. month name - Jan to Dec
- '%B', '$rep = $MoY[$mon]', # full month name - January to December
- '%c', '$rep = $locDTF; 1', # date/time in local format
- '%d', '$rep = &date\'pad($mday, 2, "0")', # day of month - 01 to 31
- '%D', '$rep = \'%m/%d/%y\'', # date as mm/dd/yy
- '%e', '$rep = &date\'pad($mday, 2, " ")', # day of month (space padded) ` 1' to `31'
- '%h', '$rep = \'%b\'', # abbr. month name (same as %b)
- '%H', '$rep = &date\'pad($hour, 2, "0")', # hour - 00 to 23
- '%I', '$rep = &date\'ampmH($hour)', # hour - 01 to 12
- '%j', '$rep = &date\'pad($yday+1, 3, "0")', # Julian date 001 - 366
- '%m', '$rep = &date\'pad($mon+1, 2, "0")', # month of year - 01 to 12
- '%M', '$rep = &date\'pad($min, 2, "0")', # minute - 00 to 59
- '%n', '$rep = "\n"', # insert a newline
- '%p', '$rep = &date\'ampmD($hour)', # insert `AM' or `PM'
- '%r', '$rep = \'%I:%M:%S %p\'', # time in AM/PM notation
- '%R', '$rep = \'%H:%M\'', # time as HH:MM
- '%S', '$rep = &date\'pad($sec, 2, "0")', # second - 00 to 59
- '%t', '$rep = "\t"', # insert a tab
- '%T', '$rep = \'%H:%M:%S\'', # time as HH:MM:SS
- '%U', '$rep = &date\'wkno($yday, 0)', # week number (weeks start on Sun) - 00 to 53
- '%w', '$rep = $wday; 1', # day of week - Sunday = 0
- '%W', '$rep = &date\'wkno($yday, 1)', # week number (weeks start on Mon) - 00 to 53
- '%x', '$rep = $locDF; 1', # date in local format
- '%X', '$rep = $locTF; 1', # time in local format
- '%y', '($rep = "$year") =~ s/..(..)/\1/', # last 2 digits of year - 00 to 99
- '%Y', '$rep = "$year"', # full year ~ 1700 to 2000 odd
- '%z', '$rep = $TZ eq "" ? "" : "$TZ "', # time zone from TZ env var (w/trail. space)
- '%Z', '$rep = $TZ; 1', # time zone from TZ env. var.
- '%%', '$rep = \'%\'; $adv=1', # insert a `%'
- '%+', '$rep = \'+\'' # insert a `+'
- );
-
- sub main'date {
- local($time, $format) = @_;
- local($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
- local($pos, $tag, $rep, $adv) = (0, "", "", 0);
-
-
- # default to date/ctime format or strip leading `+'...
- if ($format eq "") {
- $format = $defaultFMT;
- } elsif ($format =~ /^\+/) {
- $format = $';
- }
-
- # Use local time if can't find a TZ in the environment
- $TZ = defined($ENV{'TZ'}) ? $ENV{'TZ'} : $defaultTZ;
- ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
- &gettime ($TZ, $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;
- }
-
- # watch out in 2070...
- $year += ($year < 70) ? 2000 : 1900;
-
- # now loop throught the supplied format looking for tags...
- while (($pos = index ($format, '%')) != -1) {
-
- # grab the format tag
- $tag = substr($format, $pos, 2);
- $adv = 0; # for `%%' processing
-
- # do we have a replacement string?
- if (defined $Tags{$tag}) {
-
- # trap dead evals...
- if (! eval $Tags{$tag}) {
- print STDERR "date.pl: internal error: eval for $tag failed.\n";
- return "";
- }
- } else {
- $rep = "";
- }
-
- # do the substitution
- substr ($format, $pos, 2) =~ s/$tag/$rep/;
- $pos++ if ($adv);
- }
-
- $format;
- }
-
- # weekno - figure out week number
- sub wkno {
- local ($yday, $firstweekday) = @_;
- local ($jan1, @jan1, $wks);
- local ($now) = time;
-
- # figure out the `time' value for January 1
- $jan1 = $now - ((&gettime ($TZ, $now))[7] * 86400); # 86400 sec/day
-
- # figure out what day of the week January 1 was
- @jan1= &gettime ($TZ, $jan1);
-
- # and calculate the week number
- $wks = (($yday + ($jan1[6] - $firstweekday)) + 1)/ 7;
- $wks += (($wks - int($wks) > 0.0) ? 1 : 0);
-
- # supply zero padding
- &pad (int($wks), 2, "0");
- }
-
- # ampmH - figure out am/pm (1 - 12) mode hour value.
- sub ampmH { local ($h) = @_; &pad($h>12 ? $h-12 : $h, 2, "0"); }
-
- # ampmD - figure out am/pm designator
- sub ampmD { shift @_ > 12 ? "PM" : "AM"; }
-
- # gettime - get the time via {local,gmt}time
- sub gettime { ((shift @_) eq 'GMT') ? gmtime(shift @_) : localtime(shift @_); }
-
- # pad - pad $in with leading $pad until lenght $len
- sub pad {
- local ($in, $len, $pad) = @_;
- local ($out) = "$in";
-
- $out = $pad . $out until (length ($out) == $len);
- return $out;
- }
-
- 1;
-