Attached is the above module. Unless there's strenuous objections I'll
CPAN it. I just wish for this and for ::Alias that we could hook in
better without messing with the internals.

While I'm thinking of it, I'd like to be able to set names and
short-names for offsets. I have a list of short names in Strptime, but
I've love to be able to get these back from TimeZone somehow. Just like
we do with Olsen (or is it Olson, one's the twins, one's the time, can't
ever remember which!).

Cheers!
Rick
package DateTime::TimeZone::LMT;

use strict;

use Carp qw( croak );
use DateTime::TimeZoneCatalog;

use vars qw( $VERSION $LONGITUDE $OFFSET );
$VERSION = 0.01;

sub import {
    my $class = shift;
    return unless @_;
    $class->set( @_ );
}

sub set {
    my $class = shift;

    my $longitude = shift;
	
	if ($longitude) {
		croak "You must supply a valid longitude. (-180 .. 180)" if ($longitude < -180 or $longitude > 180);

		# Offset in seconds:
		my $offset_seconds = ( $longitude / 180 ) * (12 * 60 * 60);

		my $sign = '+';
		if ($offset_seconds < 0) {
			$offset_seconds *= -1;
			$sign = '-';
		}

		my $hours = int($offset_seconds / (60 * 60) );
		$offset_seconds -= $hours * (60 * 60);

		my $minutes = int($offset_seconds / 60);
		$offset_seconds -= $minutes * 60;

		my $seconds = sprintf("%.0f",$offset_seconds);
		
		$OFFSET = "$sign$hours:$minutes:$seconds";
		
		$DateTime::TimeZone::LINKS{ LMT } = $OFFSET;
		
		$LONGITUDE = $longitude;
	}
	return $LONGITUDE;
}

sub offset {return $OFFSET};

1;

__END__

=pod

=head1 NAME

DateTime::TimeZone::Alias - Create aliases for DateTime timezones

=head1 SYNOPSIS

    use DateTime::TimeZone::LMT qw/145.08009/;
    # or
    use DateTime::TimeZone::LMT;
    DateTime::TimeZone::LMT->set(145.08009);
    
	DateTime::TimeZone::LMT->longitude;
	# 145.08009
	
	DateTime::TimeZone::LMT->offset;
 	# +09:40:19
	
=head1 DESCRIPTION

Creates LMT DateTime timezones.  This module violates 
the encapsulation of the DateTime internals.  User _Beware_.

=head1 BACKGROUND

Local Apparent Time

If we are to tell the time by the sun's hour angle, no two points will share
the same time unless they lie on the same meridian. The time is thus 
I<localised> to a particular meridian, and since it is also based on the
apparent (think 'appear') motion of the sun we call it Local Apparent Time.

This is the kind of time shown on most sundials, and until about a century 
ago was the kind of time used almost universally in daily life. Yet it suffers
from disadvantages which have led most people to discard it in favor of some
other kind of time.

For one thing it is inconvenient to use a system of timekeeping which is so
narrowly localised. Remember that no two points will share the same LAT unless
they lie on the same meridian. Two cities 100 miles apart will differ by about
7.5 minutes. There is even a difference of about 0.25 seconds at opposite ends
of a football field! Precisely set clocks would even show slightly different
times in different rooms of the same house!

Local Mean Time

The second disadvantage of LAT arises from the fact that when we measure days
by the sun they turn out to differ amongst themselves in length. About Christmas
time the days are about 30 seconds longer than average and in mid-September are
about 20 seconds shorter. These variations increase until in mid-February when
the sun reaches its meridian almost 14.5 minutes later than it would if all
days were of equal length. Then in early November the meridian falls back about
16.5 minutes. These variations amount to just over half-an-hour which would be
decidedly inconvenient for scientific purposes, and today we would consider it
unacceptable for even everyday affairs.

Instead, then, of reckoning time from the irregularly moving real sun, we
usually reckon it from an imaginary i<mean> sun -- a fictitious heavenly body
which moves at a constant speed, equal to the average speed at which the
real sun moves. Time measured accoring to this mean sun is known as I<Local
Mean Time>. This is the time that this module works with.

=head1 IMPORT PARAMETERS

Accepts a scalar containing a valid longitude.

=head1 METHODS

=over 4

=item * set( $longitude ) 

Sets the longitude.


=item * longitude( $longitude ) 

Sets the longitude if one is provided.

Returns the current longitude.


=item * offset() 

Returns the current longitude's UTC offset.

=back

=head1 NOTES

=head2 Import

Multiple C<use DateTime::TimeZone::LMT> statements in the same package will 
cause unexpected behaviour. If you need more than one LMT, consider using
C<DateTime::TimeZone::Alias> as detailed in the Cookbook below.


=head1 COOKBOOK

=head2 What is my LMT?

To determine the time right where you are, get your longitude. Look it up in 
an atlas or look it up online. There are online services that let you enter
your address and they return a very accurate value. Then:

	use DateTime;
	use DateTime::TimeZone::LMT $your_longitude;
	print DateTime->now( time_zone => LMT )->datetime;

=head2 Multiple LMTs

If you want to add multiple LMTs to your work, use C<DateTime::TimeZone::Alias>

	use DateTime::TimeZone::LMT 145.08009;
	use DateTime::TimeZone::Alias( 'LMT/Melbourne' => DateTime::TimeZone::LMT->offset );

	DateTime::TimeZone::LMT->set(0);
	DateTime::TimeZone::Alias->set( 'LMT/Greenwich' => DateTime::TimeZone::LMT->offset );

	DateTime::TimeZone::LMT->set(180);
	DateTime::TimeZone::Alias->set( 'LMT/IDL' => DateTime::TimeZone::LMT->offset );

So now we have three Aliases to our offsets and can use them to create DateTimes:

	$now_melbourne = DateTime->now( time_zone => 'LMT/Melbourne' );
	$now_greenwich = DateTime->now( time_zone => 'LMT/Greenwich' );
	$now_idl       = DateTime->now( time_zone => 'LMT/IDL'       );



=head1 TODO

I'm looking at extending this to also do LAT also (Local Apparent Time). This
requires lookup tables and is date-dependent so it will probably be a little
different in it's behaviour.

=head1 CREDITS

Joshua Hoblitt upon whose module (C<DateTime::TimeZone::Alias>) this module
is built.

=head1 SUPPORT
  
Support for this module is provided via the [EMAIL PROTECTED] email
list. See http://lists.perl.org/ for more details.
 
=head1 AUTHOR

Rick Measham <[EMAIL PROTECTED]>

=head1 COPYRIGHT

Copyright (c) 2003 Rick Measham.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the
same terms as Perl itself.

The full text of the license can be found in the LICENSE file included
with this module.

=head1 SEE ALSO

[EMAIL PROTECTED] mailing list

http://datetime.perl.org/

=cut

Reply via email to