File Coverage

blib/lib/Time/LST.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Time::LST;
2            
3 1     1   22458 use 5.008008;
  1         4  
  1         39  
4 1     1   5 use strict;
  1         2  
  1         39  
5 1     1   5 use warnings;
  1         6  
  1         29  
6 1     1   465 use Astro::Time;
  0            
  0            
7             use Carp qw(croak);
8             use vars qw($VERSION @EXPORT @EXPORT_OK);
9             $VERSION = 0.038;
10             use Exporter qw(import);
11             @EXPORT = qw(ymdhms2lst datetime2lst filestat2lst now2lst time2lst);
12             @EXPORT_OK = qw(ymdhms_2_lst datetime_2_lst filestat_2_lst now_2_lst time_2_lst);
13            
14             =head1 NAME
15            
16             Time::LST - Convert date/time representations to local sidereal time via Astro-Time and other Date/Time modules
17            
18             =head1 VERSION
19            
20             This is documentation for Version 0.038 of Time::LST (2009.09.26).
21            
22             =head1 SYNOPSIS
23            
24             use Time::LST qw(datetime2lst filestat2lst now2lst time2lst ymdhms2lst);
25            
26             $long = -3.21145; # London, in degrees
27            
28             $lst_from_string = datetime2lst('1942:8:7T17:00:00', -3.21145, 'BST'); # note approx only for pre-1970
29             $data_mod_lst = filestat2lst('mod', 'valid_path_to_a_file', $long); # or filestat2lst('create', $path, $long)
30             $now_as_lst = time2lst(time(), $long);
31             $lst_from_aref = ymdhms2lst([2006, 11, 21, 12, 15, 0], $long, 'EADT'); # optional timezone
32            
33             =head1 DESCRIPTION
34            
35             This is essentially no more than a wrapper to a number of L methods that simplifies conversion into local sidereal time of a datetime representation, such as returned by L), or seconds since the epoch, such as returned by L, or L fields).
36            
37             Manditorily, you need to know the longitude (in degrees) of the space relevant to your time.
38            
39             Give a filepath to get the LST of its last modified time, or readily see what the LST is now.
40            
41             Get an accurate representation of the relevant datetime ("now," a given time, or a file's creation or modified time) in so many "seconds since the epoch", taking TimeZone into account.
42            
43             Optionally, a timezone string in some methods can be helpful for accurately parsing (solar) clock-and-calendar times.
44            
45             =head1 METHODS
46            
47             Methods need to be explicitly imported in the C statement. None are exported by default.
48            
49             All methods expect a longitude, either in I or I - e.g. -3.21145 (London), 147.333 (Hobart, Tasmania) - or degrees+minutes - e.g., 147:19:58.8 (Hobart). See the L method in the Astro::Time module for valid representations of longitude. Note, however, the degrees, not hours, are here supported.
50            
51             LST is always returned in the format B, hours ranging from 0 (12 AM) to 23 (11 PM).
52            
53             =head2 datetime2lst
54            
55             $lst = datetime2lst('1942:12:27:16:04:07', -3.21145, 'BST')
56            
57             Returns LST on the basis of parsing a datetime string into "seconds since the epoch".
58            
59             The first two values to the function are manditory.
60            
61             Firstly, there should be passed a string in any form parseable by L, e.g., "1995:01:24T09:08:17.1823213"; "21 dec 17:05"; "16 Nov 94 22:28:20 PST". There are system limitations in handling years outside of a certain range. Years less than 1000 will not parse. Years between 1000 and 1969, inclusive, will be rendered as 1970, and those greater than 2037 will be rendered as 2037. (LST deviates by only about 3 minutes from 1970 to 2037).
62            
63             A second mandatory value to the function is the I in degrees.
64            
65             Then follow non-mandatory values.
66            
67             A timezone string can be specified as an optional third value for accurate parsing of the datetime string into "seconds since the epoch"; the local timezone is used if this is not specified. Valid representations of Timezone include the likes of "AEDT" and "EST" (parsed by L; i.e., a capital-letter string of 3-5 letters in length), or "Australia/Hobart" (parsed by L).
68            
69             =cut
70            
71             sub datetime2lst {
72             my ($str, $long, $tz) = @_;
73             croak __PACKAGE__, '::datetime2lst: Need a datetime string' if !$str;
74             require Date::Parse;
75             my @ari = Date::Parse::strptime($str);
76             croak __PACKAGE__, '::datetime2lst: Check datetime: the sent datetime did not parse' if ! scalar @ari;
77             pop @ari;
78             $ari[4] += 1;
79             $ari[5] += 1900 if $ari[5] < 1000;
80             return ymdhms2lst([reverse @ari], $long, $tz);
81             }
82             *datetime_2_lst = \&datetime2lst; # Alias
83            
84             =head2 filestat2lst
85            
86             $lst = filestat2lst('create|mod', $path, $long)
87            
88             Returns LST corresponding to the creation or modification time of a given path.
89            
90             First argument equals either 'c' or 'm' (only the first letter is looked-up, case-insensitively). This, respectively, determines access to C (element 10) and C (element 9) returned by Perl's internal L function. Note that only modification-time is truly portable across systems; see L (paras 6 and 7).
91            
92             The path must be to a "real" file, not a link to a file.
93            
94             =cut
95            
96             sub filestat2lst {
97             my ($op, $path, $long, $tz) = @_;
98             croak __PACKAGE__, '::filestat_2_lst: First argument needs to be create or mod' if $op !~ /^c|m/i;
99             croak __PACKAGE__, '::filestat_2_lst: Invalid path to file' if !$path or !-e $path;
100             return time2lst( (stat($path))[ $op =~ /^c/i ? 10 : 9 ] , $long, $tz);
101             }
102             *filestat_2_lst = \&filestat2lst; # Alias
103            
104             =head2 now2lst
105            
106             $lst = now2lst($long)
107            
108             Returns local now (as returned by perl's time()) as LST, given longitude in degrees.
109            
110             Same as going: C.
111            
112             =cut
113            
114             sub now2lst {
115             return time2lst(time(), @_);
116             }
117             *now_2_lst = \&now2lst;
118            
119             =head2 ymdhms2lst
120            
121             $lst = ymdhms2lst([2006, 8, 21, 12, 3, 0], $long, $timezone)
122            
123             Returns LST corresponding to a datetime array reference of the following elements:
124            
125             =for html

  [
   year (4-digit only),
   month-of-year (i.e., nth month (ranging 1-12, or 01-12), not month index as returned by localtime()),
   day-of-month (1-31 (or 01-31)),
   hour (0 - 23),
   minutes,
   seconds
  ]

126            
127             Range-checking of these values is performed by Astro::Time itself; digital representations such as "08" or "00" are stripped of leading zeroes for parseability to another module (so there's no need to add them as fillers). Ensure that the year is 4-digit representation.
128            
129             A value for longitude is required secondary to this datetime array.
130            
131             A final timezone string - e.g., 'EST', 'AEDT' - is optional. Sending nothing, or an erroneous timezone string, assumes present local timezone. The format is as used by L or L; UTC+I format does not parse.
132            
133             =cut
134            
135             sub ymdhms2lst {
136             my ($ymdhms, $long, $tz) = @_;
137             croak __PACKAGE__, '::ymdhms2lst: Need an array reference to calculate LST' if ! ref $ymdhms;
138             croak __PACKAGE__, '::ymdhms2lst: Need an array reference of datetime (6 values) to calculate LST' if ! ref $ymdhms eq 'ARRAY' or scalar @{$ymdhms} != 6;
139            
140             # Ensure the year is epoch-able:
141             if ($ymdhms->[0] < 1970) {
142             $ymdhms->[0] = 1970;
143             if($ymdhms->[1] == 2 && $ymdhms->[2] == 29) {
144             $ymdhms->[2] = 28;
145             }
146             }
147            
148             if ($ymdhms->[0] > 2037) {
149             $ymdhms->[0] = 2037;
150             if($ymdhms->[1] == 2 && $ymdhms->[2] == 29) {
151             $ymdhms->[2] = 28;
152             }
153             }
154            
155             # Some module doesn't like "pseudo-octals" like 08, or 00, but another will need at least a 0; SO:
156             my $i;
157             for ($i = 0; $i < 6; $i++) {
158             $ymdhms->[$i] =~ s/^0+//;
159             $ymdhms->[$i] ||= 0;
160             }
161            
162             my $epoch = _ymdhms2epochsecs($ymdhms, $tz);
163             croak __PACKAGE__, '::ymdhms2lst: Check datetime: the sent datetime did not parse' if ! defined $epoch;
164             return time2lst($epoch, $long, $tz); # knock off time, just do the LST conversion
165             #
166             }
167             *ymdhms_2_lst = \&ymdhms2lst;
168            
169             =head2 time2lst
170            
171             $lst = time2lst('1164074032', $long)
172            
173             Returns LST given seconds since the epoch. If you have a time in localtime format, see L to convert it into the format that can be used with this function.
174            
175             =cut
176            
177             sub time2lst {
178             my ($time, $long, $tz) = @_;
179             croak __PACKAGE__, '::time2lst: Need longitude and time to calculate LST' if !$long || !$time;
180             my @time_ari = gmtime($time);
181             return _convert(
182             [
183             ($time_ari[5] + 1900), # year (ISO format)
184             ($time_ari[4] + 1), # month
185             $time_ari[3], # day of month
186             @time_ari[2, 1, 0] # hours, minutes, seconds
187             ],
188             $long
189             );
190             }
191             *time_2_lst = \&time2lst; # Alias
192            
193            
194             sub _ymdhms2epochsecs {
195             my ($ymdhms, $tz) = @_;
196            
197             # Get the epoch seconds of this datetime thing:
198             my $epoch;
199             #$tz ||= 'local'; # Date::Parse handles localtime more reliably than does DateTime
200             if ($tz =~ /^([A-Z]{3,5}|local)$/) { # e.g., 'AEDT', 'BST', 'local'
201             require Date::Parse;
202             my $str = join':', (@{$ymdhms}[0 .. 5]); # all 6 els as a string
203             $epoch = Date::Parse::str2time($str, $tz);
204             }
205             elsif ($tz =~ /^[A-Z]/) {
206             require DateTime;
207             my @dkeys = (qw/year month day hour minute second/);
208             my $i = 0;
209             my $dt = DateTime->new( ( map { $dkeys[$i++] => $_ } @{$ymdhms} ), time_zone => $tz, );
210             $epoch = $dt->epoch();
211             }
212             else { # No timezone specification; use Time::Local
213             require Time::Local;
214             #$time = timelocal($sec,$min,$hour,$mday,$mon,$year);
215             $epoch = Time::Local::timelocal(reverse @{$ymdhms});
216             }
217             return $epoch;
218             }
219            
220             sub _convert {
221             my $ymdhms = shift;
222             return turn2str( # Convert Julian day into fraction of a turn
223             mjd2lst(
224             cal2mjd( # Convert calendar date & time (dayfraction) into Julian Day, via Astro-Time:
225             $ymdhms->[2], # $day
226             $ymdhms->[1], # $month
227             $ymdhms->[0], # $year
228             hms2time(# Convert hours, minutes & seconds into day fraction (ut), via Astro-Time:
229             $ymdhms->[3],
230             $ymdhms->[4],
231             $ymdhms->[5],,
232             ),
233             ),
234             str2turn(# Convert angle from string (in Degrees, not Hours) into fraction of a turn, via Astro-Time:
235             shift,
236             'D',
237             )
238             ),
239             'H', # into 'H(ours)' (not D(egrees))
240             0 # 'No. sig. digits'
241             );
242             }
243            
244             1;
245             __END__