#!/usr/local/bin/perl
#
#
#
#
#
# $Id: $
#

&dates::init;

$localflag = 0;
if ($ARGV[0] eq '-l' or $ARGV[0] eq '-o') {
    shift;
    $localflag = 1;
}
if ($ARGV[0] eq '-n') {
    shift;
    $localflag = 2;
}

$/ = '\777';
$str = <> or die 'file error';
sub get( $ ){
    my $t = substr($str, 0, $_[0]);
    $str = substr($str, $_[0]);
    $t;
}

get(20);

($isgmtcnt, $isstdcnt, $leapcnt, $timecnt, $typecnt, $charcnt)
  = unpack("NNNNNN", get(4 * 6));

print <<EOF
Header:
    GMT/local indicators: $isgmtcnt
standard/wall indicators: $isstdcnt
        leap second data: $leapcnt
        transition times: $timecnt
        local time types: $typecnt
  time zone string chars: $charcnt
EOF
  ;

# Transition time info.
@from = unpack("N*", get(4 * $timecnt));
@index = unpack("C*", get($timecnt));
for($i = 0; $i < $timecnt; $i++) {
    $from[$i] = sprintf("%d", $from[$i]); # signed value
}

# offset info.
for($i = 0; $i < $typecnt; $i++) {
    ($gmtoff[$i], $isdst[$i], $abbrind[$i]) = unpack("NcC", get(6));
    $gmtoff[$i] = sprintf("%d", $gmtoff[$i]);
}

# leap second info.
for($i = 0; $i < $leapcnt; $i++) {
    ($leapat[$i], $offset[$i]) = unpack("NN", get(8));
}

$tzlabelstr = get($charcnt);

# GMT/local info:
@wallflag = unpack("C*", get($isstdcnt));

# GMT/local info:
@nongmtflag = unpack("C*", get($isgmtcnt));


print "\nLeap Seconds information: ($leapcnt)\n";
for($i = 0; $i < $leapcnt; $i++) {
    print "  $i:    after $leapat[$i], offset $offset[$i] s\n";
}
$maxlen = 0;

print "\nTime offset information: ($typecnt)\n";
for($i = 0; $i < $typecnt; $i++) {
    $s = $gmtoff[$i];
    my $h = int($s / 3600);
    $s -= $h * 3600;
    if ($s < 0) { $s += 3600; $h -= 1; }
    my $m = int($s / 60);
    $s -= $m * 60;
    $abbrstr[$i] = substr($tzlabelstr, $abbrind[$i]);
    $abbrstr[$i] =~ s/\0.*$//;
    $maxlen = (length $abbrstr[$i]) if ($maxlen < length $abbrstr[$i]);
    $offsetstr[$i] = sprintf "%+3d:%02d:%02d", $h, $m, $s;
      printf "  %4d: $offsetstr[$i], dst=%3s, wall=%s, '$abbrstr[$i]' (index %d)\n", 
    $i, ($isdst[$i] ? "YES": "no "), ($wallflag[$i] ? "YES": "no "), $abbrind[$i];
}

print "\nTransition time information: ($timecnt)\n";

if ($localflag) {
    $w = 26 + $maxlen;
} else {
    $w = 29;
}

printf "     -:  from %-${w}s, %s %s%s, %-${maxlen}s (0)\n",
  "old time", $offsetstr[0], $isdst[0] ? "D": "-", $wallflag[0] ? "W": "-", $abbrstr[0];

$prevzone = 0;
for($i = 0; $i < $timecnt; $i++) {
    my $f = $from[$i];
    if ($wallflag[$prevzone]) {
	$f -= $gmtoff[$prevzone];
    }
    my $in = $index[$i];
    my $ts;
    if ($localflag == 1) {
	$ts = &strftime($f + $gmtoff[$prevzone], $abbrstr[$prevzone]);
    } elsif ($localflag == 2) {
	$ts = &strftime($f + $gmtoff[$in], $abbrstr[$in]);
    } else {
	$ts = &strftime($f);
    }
    printf "  %4d:  from %-${w}s, %s %s%s, %-${maxlen}s ($in)\n",
    $i, $ts, 
    $offsetstr[$in], 
    ($isdst[$in] ? "D": "-"), ($wallflag[$in] ? "W": "-"), $abbrstr[$in];
    $prevzone = $in;
}

print "\nGMT/local indicators: ($isgmtcnt)\n";
for($i = 0; $i < $isgmtcnt; $i++) {
    print "  $i:    flag = $nongmtflag[$i]\n";
}

print "\nTimezone String Data:\n    ";
$s = $tzlabelstr;
for($i = 0; $i < length $tzlabelstr; $i++) {
    my $c = substr($s, $i, 1);
    if ($c =~ /^[A-Za-z0-9?+---]$/) {
	print "$c ";
    } else {
	printf "[%02x] ", ord($c);
    }
}
print "\n";



      
#!/usr/local/bin/perl
#
# dates package
#
# provides:
#
# &revstrftime(String datespec);
# &strftime(Int time, optional Int fmt);
#
# $Id: dates.pl,v 1.3 1997/09/14 19:51:07 yutaka Exp $
#

# date calcs
package dates;

sub init {
    return if $inited;
    $inited = 1;

    %revmonthname = ('Jan', 1, 'Feb', 2, 'Mar', 3, 'Apr', 4,
	      'May', 5, 'Jun', 6, 'Jul', 7, 'Aug', 8,
	      'Sep', 9, 'Oct', 10, 'Nov', 11, 'Dec', 12);
    @monthname = ('', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
		  'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
    @wdayname = ('', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
    @longwdayname = ('', 'Sunday', 'Monday', 'Tuesday', 'Wednesday',
	      'Thursday', 'Friday', 'Saturday');
}

sub main'revstrftime {
    local ($str) = @_;
    local ($y, $m, $d, $h, $min, $sec, $tz, $time, $tzshift);
    local ($_) = $str;
    
    local ($ssec,$mmin,$hh,$mmday,$mm,$yy,$wday,$dd,$isdst) =
	gmtime(time);
    $mm++;

    if (m/^(\w*, +)?(\d\d?)[ -](\w\w\w)[ -](\d?\d?\d\d) (\d\d):(\d\d):(\d\d) ?(.+)?/) { 
	# rfc850 / http
	$d = $2; $m = $revmonthname{$3}; $y = $4;
	$h = $5; $min = $6; $sec = $7; $tz = $8;
    } elsif (m/^([A-Z][a-z][a-z]) ([ 12][0-9]) ([ 012][0-9]):([0-5][0-9])$/) {
	# ls "Sep  1 22:00"
	$d = $2; $m = $revmonthname{$1}; $h = $3; $min = $4; $sec = 0;
	$y = ($m > $mm)? $yy - 1: $yy; $tz = 'GMT';
    } elsif (m/^([A-Z][a-z][a-z]) ([ 12][0-9])  ([12][0-9][0-9][0-9])$/) {
	# ls "Sep  1  1997"
	$d = $2; $m = $revmonthname{$1}; $h = 0; $min = 0; $sec = 0;
	$y = $3; $tz = 'GMT';
    } elsif (m/^[A-Z][a-z][a-z] ([A-Z][a-z][a-z]) ([ 12][0-9]) (\d\d):(\d\d):(\d\d) ([12][0-9][0-9][0-9])$/) {
	# ls "Mon Sep  1 22:00:00 1997"
	$d = $2; $m = $revmonthname{$1}; $h = $3; $min = $4; $sec = $5;
	$y = $6; $tz = 'GMT';
    } elsif (m/^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)\r?\n?$/) { #ftp MDTM
	$d = $3; $m = $2; $y = $1;
	$h = $4; $min = $5; $sec = $6; $tz = 'GMT';
    } else {
	return -1;
    }
    if ($m == 0) {
	return -1;
    }
    $y += 2000 if ($y < 70);
    $y += 1900 if ($y < 100);

    if ($tz eq 'GMT') {
	$tzshift = 0;
    } elsif ($tz =~ /^([+-]\d\d)(\d\d)$/) {
	$tzshift = -($1 * 3600 + $2 * 60);
    } else {
	$tzshift = 0;
    }

    return -1 if ($y < 1970 || $y > 2038 ||
		  $m < 1 || $m > 12 ||
		  $d < 1 || $d > 31 ||
		  $h < 0 || $h > 23 ||
		  $min < 0 || $min > 59 ||
		  $sec < 0 || $sec > 59);

    $y -= 1968;
    $time = $y * 365 + int($y / 4) - 365 * 2;
    $time += (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334)[$m-1];
    $time += $d - 1;
    $time -= 1 if ($y % 4 == 0 && $m < 3);
    $time *= 86400;
    $time += $h * 3600;
    $time += $min * 60;
    $time += $sec;
    $time += $tzshift;
}

sub main'strftime {
    local ($t, $tzname) = @_;
    local ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
	gmtime($t);

    # mon, wday is 0 - origin
    $tzname ||= 'GMT';
    sprintf("%s, %02d %s %04d %02d:%02d:%02d $tzname",
	    $wdayname[$wday+1], $mday, $monthname[$mon+1],
	    1900 + $year, $hour, $min, $sec);
}

&init;
1;
package main; # end package dates

