File Coverage

blib/lib/Date/Julian/Simple.pm
Criterion Covered Total %
statement 61 81 75.3
branch 11 36 30.5
condition 2 15 13.3
subroutine 16 18 88.8
pod 6 10 60.0
total 96 160 60.0


line stmt bran cond sub pod time code
1             package Date::Julian::Simple;
2              
3             $Date::Julian::Simple::VERSION = '0.13';
4             $Date::Julian::Simple::AUTHORITY = 'cpan:MANWAR';
5              
6             =head1 NAME
7              
8             Date::Julian::Simple - Represents Julian date.
9              
10             =head1 VERSION
11              
12             Version 0.13
13              
14             =cut
15              
16 2     2   165106 use 5.006;
  2         15  
17 2     2   1238 use Data::Dumper;
  2         14134  
  2         128  
18 2     2   984 use POSIX qw/floor/;
  2         13016  
  2         12  
19 2     2   3900 use Time::localtime;
  2         11632  
  2         114  
20 2     2   1028 use Date::Exception::InvalidDay;
  2         154698  
  2         77  
21              
22 2     2   17 use Moo;
  2         4  
  2         10  
23 2     2   650 use namespace::autoclean;
  2         4  
  2         27  
24              
25 2     2   157 use overload q{""} => 'as_string', fallback => 1;
  2         6  
  2         10  
26              
27             =head1 DESCRIPTION
28              
29             Represents the Julian date.
30              
31             =cut
32              
33             our $JULIAN_MONTHS = [
34             undef,
35             qw(January February March April May June
36             July August September October November December)
37             ];
38              
39             our $JULIAN_DAYS = [
40             qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
41             ];
42              
43             our $JULIAN_MONTH_DAYS = [
44             qw(31 28 31 30 31 30
45             31 31 30 31 30 31)
46             ];
47              
48             has julian_epoch => (is => 'ro', default => sub { 1721423.5 });
49             has days => (is => 'ro', default => sub { $JULIAN_DAYS });
50             has months => (is => 'ro', default => sub { $JULIAN_MONTHS });
51              
52             has year => (is => 'rw', predicate => 1);
53             has month => (is => 'rw', predicate => 1);
54             has day => (is => 'rw', predicate => 1);
55              
56             with 'Date::Utils';
57              
58             sub BUILD {
59 3     3 0 18 my ($self) = @_;
60              
61 3 50 33     30 if ($self->has_year && $self->has_month && $self->has_day) {
      33        
62 3         13 $self->validate_year($self->year);
63 3         63 $self->validate_month($self->month);
64 3 50       60 if ($self->is_leap_year($self->year)) {
65 0         0 my $day = $self->day;
66 0         0 my @caller = caller(0);
67 0 0       0 @caller = caller(2) if $caller[3] eq '(eval)';
68              
69 0 0       0 return if ($self->month != 2);
70              
71 0 0 0     0 Date::Exception::InvalidDay->throw({
    0 0        
      0        
72             method => __PACKAGE__."::validate_day",
73             message => sprintf("ERROR: Invalid day [%s].", defined($day)?($day):('')),
74             filename => $caller[1],
75             line_number => $caller[2] })
76             unless (defined($day) && ($day =~ /^\d+$/) && ($day >= 1) && ($day <= 29));
77             }
78             else {
79 3         13 $self->validate_day($self->day);
80             }
81             }
82             else {
83 0         0 my $today = localtime;
84 0         0 my $year = $today->year + 1900;
85 0         0 my $month = $today->mon + 1;
86 0         0 my $day = $today->mday;
87 0         0 $self->year($year);
88 0         0 $self->month($month);
89 0         0 $self->day($day);
90             }
91             }
92              
93             =head1 SYNOPSIS
94              
95             use strict; use warnings;
96             use Date::Julian::Simple;
97              
98             # prints today's Julian date.
99             print Date::Julian::Simple->new, "\n";
100              
101             =head1 METHODS
102              
103             =head2 to_julian()
104              
105             Returns julian day equivalent of the Julian date.
106              
107             =cut
108              
109             sub to_julian {
110 3     3 1 814 my ($self, $year, $month, $day) = @_;
111              
112 3 50       14 $day = $self->day unless defined $day;
113 3 50       9 $month = $self->month unless defined $month;
114 3 50       9 $year = $self->year unless defined $year;
115              
116             # Adjust negative common era years to the zero-based notation we use.
117 3 50       7 if ($year < 1) {
118 0         0 $year++;
119             }
120              
121             # Algorithm as given in Meeus, Astronomical Algorithms, Chapter 7, page 61.
122 3 50       10 if ($month <= 2) {
123 3         6 $year--;
124 3         4 $month += 12;
125             }
126              
127 3         43 return ((floor((365.25 * ($year + 4716))) + floor((30.6001 * ($month + 1))) + $day) - 1524.5);
128             }
129              
130             =head2 from_julian($julian_day)
131              
132             Returns Julian date as an object of type L equivalent of the
133             C<$julian_day>.
134              
135             =cut
136              
137             sub from_julian {
138 2     2 1 1602 my ($self, $julian_day) = @_;
139              
140 2         4 $julian_day += 0.5;
141 2         6 my $a = floor($julian_day);
142 2         5 my $b = $a + 1524;
143 2         7 my $c = floor(($b - 122.1) / 365.25);
144 2         5 my $d = floor(365.25 * $c);
145 2         6 my $e = floor(($b - $d) / 30.6001);
146              
147 2 50       10 my $month = floor(($e < 14) ? ($e - 1) : ($e - 13));
148 2 50       9 my $year = floor(($month > 2) ? ($c - 4716) : ($c - 4715));
149 2         6 my $day = $b - $d - floor(30.6001 * $e);
150              
151             # If year is less than 1, subtract one to convert from
152             # a zero based date system to the common era system in
153             # which the year -1 (1 B.C.E) is followed by year 1 (1 C.E)
154 2 50       7 if ($year < 1) {
155 0         0 $year--;
156             }
157              
158 2         53 return Date::Julian::Simple->new({ year => $year, month => $month, day => $day });
159             }
160              
161             =head2 to_gregorian()
162              
163             Returns Gregorian date as list (yyyy,mm,dd) equivalent of the Julian date.
164              
165             =cut
166              
167             sub to_gregorian {
168 1     1 1 567 my ($self) = @_;
169              
170 1         4 return $self->julian_to_gregorian($self->to_julian);
171             }
172              
173             =head2 from_gregorian($year, $month, $day)
174              
175             Returns Julian date as an object of type L equivalent of the
176             given Gregorian date C<$year>, C<$month> and C<$day>.
177              
178             =cut
179              
180             sub from_gregorian {
181 1     1 1 630 my ($self, $year, $month, $day) = @_;
182              
183 1         5 $self->validate_date($year, $month, $day);
184 1         58 return $self->from_julian($self->gregorian_to_julian($year, $month, $day));
185             }
186              
187             =head2 day_of_week()
188              
189             Returns day of the week, starting 0 for Sunday, 1 for Monday and so on.
190              
191             +-------+-------------------------------------------------------------------+
192             | Index | English Name |
193             +-------+-------------------------------------------------------------------+
194             | 0 | Sunday |
195             | 1 | Monday |
196             | 2 | Tuesday |
197             | 3 | Wednesday |
198             | 4 | Thursday |
199             | 5 | Friday |
200             | 6 | Saturday |
201             +-------+-------------------------------------------------------------------+
202              
203             =cut
204              
205             sub day_of_week {
206 1     1 1 3 my ($self) = @_;
207              
208 1         4 return $self->jwday($self->to_julian);
209             }
210              
211             =head2 is_leap_year($year)
212              
213             Returns 0 or 1 if the given Julian year C<$year> is a leap year or not.
214              
215             =cut
216              
217             sub is_leap_year {
218 3     3 1 7 my ($self, $year) = @_;
219              
220 3 50       12 return (($year % 4) == (($year > 0) ? 0 : 3));
221             }
222              
223             sub days_in_year {
224 0     0 0 0 my ($self, $year) = @_;
225              
226 0 0       0 ($self->is_leap_year($year))
227             ?
228             (return 366)
229             :
230             (return 365);
231             }
232              
233             sub days_in_month_year {
234 0     0 0 0 my ($self, $month, $year) = @_;
235              
236 0 0       0 if ($self->is_leap_year($year)) {
237 0 0       0 return 29 if ($month == 2);
238             }
239              
240 0         0 return $JULIAN_MONTH_DAYS->[$month-1];
241             }
242              
243             sub as_string {
244 1     1 0 26 my ($self) = @_;
245              
246 1         4 return sprintf("%d, %s %d", $self->day, $self->get_month_name, $self->year);
247             }
248              
249             =head1 AUTHOR
250              
251             Mohammad S Anwar, C<< >>
252              
253             =head1 REPOSITORY
254              
255             L
256              
257             =head1 SEE ALSO
258              
259             =over 4
260              
261             =item L
262              
263             =item L
264              
265             =item L
266              
267             =item L
268              
269             =item L
270              
271             =item L
272              
273             =back
274              
275             =head1 BUGS
276              
277             Please report any bugs / feature requests to C,
278             or through the web interface at L.
279             I will be notified, and then you'll automatically be notified of progress on your
280             bug as I make changes.
281              
282             =head1 SUPPORT
283              
284             You can find documentation for this module with the perldoc command.
285              
286             perldoc Date::Julian::Simple
287              
288             You can also look for information at:
289              
290             =over 4
291              
292             =item * RT: CPAN's request tracker
293              
294             L
295              
296             =item * AnnoCPAN: Annotated CPAN documentation
297              
298             L
299              
300             =item * CPAN Ratings
301              
302             L
303              
304             =item * Search CPAN
305              
306             L
307              
308             =back
309              
310             =head1 LICENSE AND COPYRIGHT
311              
312             Copyright (C) 2017 Mohammad S Anwar.
313              
314             This program is free software; you can redistribute it and / or modify it under
315             the terms of the the Artistic License (2.0). You may obtain a copy of the full
316             license at:
317              
318             L
319              
320             Any use, modification, and distribution of the Standard or Modified Versions is
321             governed by this Artistic License.By using, modifying or distributing the Package,
322             you accept this license. Do not use, modify, or distribute the Package, if you do
323             not accept this license.
324              
325             If your Modified Version has been derived from a Modified Version made by someone
326             other than you,you are nevertheless required to ensure that your Modified Version
327             complies with the requirements of this license.
328              
329             This license does not grant you the right to use any trademark, service mark,
330             tradename, or logo of the Copyright Holder.
331              
332             This license includes the non-exclusive, worldwide, free-of-charge patent license
333             to make, have made, use, offer to sell, sell, import and otherwise transfer the
334             Package with respect to any patent claims licensable by the Copyright Holder that
335             are necessarily infringed by the Package. If you institute patent litigation
336             (including a cross-claim or counterclaim) against any party alleging that the
337             Package constitutes direct or contributory patent infringement,then this Artistic
338             License to you shall terminate on the date that such litigation is filed.
339              
340             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND
341             CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
342             WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
343             NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS
344             REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT,
345             INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
346             OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
347              
348             =cut
349              
350             1; # End of Date::Julian::Simple