# Copyright (C) 1995, David Muir Sharnoff

#
#package Time::Timezone;
## This is release 95.07.10.00
#
#=head1 NAME
#
#Time::Timezone -- miscellaneous timezone manipulations routines
#
#=head1 SYNOPSIS
#
#	use Time::Timezone;
#	print tz2zone();
#	print tz2zone($ENV{'TZ'});
#	print tz2zone($ENV{'TZ'}, time());
#	print tz2zone($ENV{'TZ'}, undef, $isdst);
#	$offset = tz_local_offset();
#	$offset = tz_offset($TZ);
#
#=head1 DESCRIPTION
#
#This is a collection of miscellaneous timezone manipulation routines.
#
#C<tz2zone()> parses the TZ environment variable and returns a timezone
#string suitable for inclusion in L<date>-like output.  It opionally takes
#a timezone string, a time, and a is-dst flag.
#
#C<tz_local_offset()> determins the offset from GMT time in seconds.  It
#only does the calculation once.
#
#C<tz_offset()> determines the offset from GMT in seconds of a specified
#timezone.  It is supposed to caches results.
#
#=head1 AUTHOR
#
#David Muir Sharnoff <muir@idiom.com>
#
#=cut
#
#require 5.000;
#
#require Exporter;
#@ISA = qw(Exporter);
#@EXPORT = qw(tz2zone tz_local_offset tz_offset);
#@EXPORT_OK = qw();
#

# Parts stolen from code by Paul Foley <paul@ascent.com>
sub tz2zone
{
	local($TZ, $time, $isdst) = @_;
	$TZ = defined($ENV{'TZ'}) ? ( $ENV{'TZ'} ? $ENV{'TZ'} : 'GMT' ) : ''
	    unless $TZ;

	# 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 (! defined $isdst) {
		local ($j);
		$time = time() unless $time;
		($j, $j, $j, $j, $j, $j, $j, $j, $isdst) = localtime($time);
	}

#	if (defined $tzn{$TZ}->[$isdst]) {
#		return $tzn{$TZ}->[$isdst];
#	}
      
	if ($TZ =~ /^([^:\d+\-,]{3,})([+-]?\d{1,2}(:\d{1,2}){0,2})([^\d+\-,]{3,})?/ ){
		$TZ = $isdst ? $4 : $1;
		# $tzn_cache{$TZ} = [ $1, $4 ];
	} else {
		# $tzn_cache{$TZ} = [ $TZ, $TZ ];
	}
	return $TZ;
}

sub tz_local_offset
{
	local ($time) = @_;

	$time = time() unless $time;
	local (@l) = localtime($time);
	$isdst = @l[8];

	if (defined($Timezone'tz_local[$isdst])) {
		return $Timezone'tz_local[$isdst];
	}

	$Timezone'tz_local[$isdst] = &calc_off($time);

	return $Timezone'tz_local[$isdst];
}

#sub tz_offset
#{
#	my ($tzn, $time) = @_;
#	require POSIX;
#	my $oe = $ENV{'TZ'};
#	my $tzo;
#	$ENV{'TZ'} = $tzn;
#	&POSIX::tzset();
# 
#	$time = time() unless $time;
#	my (@l) = localtime($time);
#	$isdst = @l[8];
#
## caching removed 6/4/95 'cause it doesn't work right.  Reason
## unknown.
##	if (defined($Timezone::tz_local["$tzn,$isdst"])) {
##		return $Timezone::tz_local["$tzn,$isdst"];
##	}
##
##	$Timezone::tz_local["$tzn,$isdst"] = 
#
#	$tzo = &calc_off($time);
#
#	$ENV{'TZ'} = $oe;
#	&POSIX::tzset();
#
#	return $tzo;
#}

sub calc_off
{
	# can't use my on globs in 5.001
	local ($time) = @_;

	local (@l) = localtime($time);
	local (@g) = gmtime($time);

	local ($off);

	$off =     $l[0] - $g[0]
		+ ($l[1] - $g[1]) * 60
		+ ($l[2] - $g[2]) * 3600;

	# subscript 7 is yday.

	if ($l[7] == $g[7]) {
		# done
	} elsif ($l[7] == $g[7] + 1) {
		$off += 86400;
	} elsif ($l[7] == $g[7] - 1) {
		$off -= 86400;
	} elsif ($l[7] < $g[7]) {
		# crossed over a year boundry!
		# localtime is beginning of year, gmt is end
		# therefore local is ahead
		$off += 86400;
	} else {
		$off -= 86400;
	}

	return $off;
}


1;