File Coverage

blib/lib/DateTime/Calendar/Julian.pm
Criterion Covered Total %
statement 54 54 100.0
branch 12 12 100.0
condition 3 3 100.0
subroutine 12 12 100.0
pod 4 4 100.0
total 85 85 100.0


line stmt bran cond sub pod time code
1             package DateTime::Calendar::Julian;
2              
3 4     4   341267 use strict;
  4         34  
  4         142  
4 4     4   23 use warnings;
  4         7  
  4         145  
5              
6 4     4   23 use vars qw($VERSION @ISA);
  4         9  
  4         356  
7              
8             $VERSION = '0.106_03';
9              
10 4     4   3986 use DateTime 0.08;
  4         2199091  
  4         2867  
11             @ISA = 'DateTime';
12              
13             sub _floor {
14 282     282   448 my $x = shift;
15 282         529 my $ix = int $x;
16 282 100       571 if ($ix <= $x) {
17 231         466 return $ix;
18             } else {
19 51         114 return $ix - 1;
20             }
21             }
22              
23             my @start_of_month = (0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337);
24              
25             # Julian dates are formatted in exactly the same way as Gregorian dates,
26             # so we use most of the DateTime methods.
27              
28             # This is the difference between Julian and Gregorian calendar:
29             sub _is_leap_year {
30 166     166   33347 my (undef, $year) = @_; # Invocant unused
31              
32 166         587 return ($year % 4 == 0);
33             }
34              
35             # Algorithms from http://home.capecod.net/~pbaum/date/date0.htm
36             sub _ymd2rd { ## no critic (ProhibitUnusedPrivateSubroutines)
37 64     64   41052 my (undef, $y, $m, $d) = @_; # Invocant unused
38              
39 64         240 my $adj = _floor( ($m-3)/12 );
40 64         139 $m -= 12 * $adj;
41 64         131 $y += $adj;
42              
43 64         185 my $rd = $d + $start_of_month[$m-3] + 365*$y + _floor($y/4) - 308;
44 64         178 return $rd;
45             }
46              
47             {
48             my @QuarterStart = my @LeapYearQuarterStart = ( 0, 90, 181, 273 );
49             $LeapYearQuarterStart[$_] += 1 for 1 .. 3;
50              
51             sub _rd2ymd { ## no critic (ProhibitUnusedPrivateSubroutines)
52 71     71   17238 my ($class, $rd, $extra) = @_;
53              
54 71         150 my $z = $rd + 308;
55 71         190 my $y = _floor(($z*100-25)/36525);
56 71         188 my $c = $z - _floor(365.25*$y);
57 71         182 my $m = int((5*$c + 456)/153);
58 71         141 my $d = $c - $start_of_month[$m-3];
59 71 100       208 if ($m > 12) {
60 34         61 $m -= 12;
61 34         64 $y++;
62             }
63              
64 71 100       161 if ($extra) {
65             # day_of_week, day_of_year
66 62   100     191 my $doy = ($c + 31 + 28 - 1)%365 + 1 +
67             ($class->_is_leap_year($y) && $m > 2);
68 62         145 my $dow = (($rd + 6)%7) + 1;
69              
70             # quarter -- see DateTime::PP->rd2ymd()
71 62         140 my $quarter = int( ( 1 / 3.1 ) * $m ) + 1;
72              
73 62 100       128 my $doq = $doy - ( $class->_is_leap_year( $y ) ?
74             $LeapYearQuarterStart[ $quarter - 1 ] :
75             $QuarterStart[ $quarter - 1 ] );
76              
77 62         221 return $y, $m, $d, $dow, $doy, $quarter, $doq;
78             }
79 9         36 return $y, $m, $d;
80             }
81             }
82              
83             sub epoch {
84 1     1 1 42 my $self = shift;
85              
86 1         5 my $greg = DateTime->from_object( object => $self );
87 1         420 return $greg->epoch;
88             }
89              
90             sub from_epoch {
91 1     1 1 699 my $class = shift;
92              
93 1         6 my $greg = DateTime->from_epoch( @_ );
94 1         294 return $class->from_object( object => $greg );
95             }
96              
97             sub gregorian_deviation {
98 6     6 1 4775 my $self = shift;
99              
100 6         16 my $year = $self->{local_c}{year};
101 6 100       18 $year-- if $self->{local_c}{month} <= 2;
102              
103 6         20 return _floor($year/100)-_floor($year/400)-2;
104             }
105              
106             # NOTE: Do NOT just default the separator to 'J' and delegate to SUPER.
107             # This will not work before DateTime 1.43 because before that the
108             # datetime() method did not have an argument.
109             sub datetime {
110 12     12 1 4204 my ( $self, $sep ) = @_;
111 12 100       35 $sep = 'J' unless defined $sep;
112 12         45 return join $sep, $self->ymd( '-' ), $self->hms( ':' );
113             }
114              
115             1;
116              
117             __END__
118              
119             =head1 NAME
120              
121             DateTime::Calendar::Julian - Dates in the Julian calendar
122              
123             =head1 SYNOPSIS
124              
125             use DateTime::Calendar::Julian;
126              
127             $dt = DateTime::Calendar::Julian->new( year => 964,
128             month => 10,
129             day => 16,
130             );
131              
132             # convert Julian->Gregorian...
133              
134             $dtgreg = DateTime->from_object( object => $dt );
135             print $dtgreg->datetime; # prints '0964-10-21T00:00:00'
136              
137             # ... and back again
138              
139             $dtjul = DateTime::Calendar::Julian->from_object( object => $dtgreg );
140             print $dtjul->datetime; # prints '0964-10-16J00:00:00'
141              
142             =head1 DESCRIPTION
143              
144             DateTime::Calendar::Julian implements the Julian Calendar. This module
145             implements all methods of DateTime; see the DateTime(3) manpage for all
146             methods.
147              
148             =head1 METHODS
149              
150             This module implements one additional method besides the ones from
151             DateTime, and changes the output of one other method.
152              
153             =over 4
154              
155             =item * gregorian_deviation
156              
157             Returns the difference in days between the Gregorian and the Julian
158             calendar.
159              
160             =item * datetime
161              
162             print $dt->datetime( $sep ), "\n";
163              
164             This method is equivalent to
165              
166             join $sep, $dt->ymd( '-' ), $dt->hms( ':' );
167              
168             The C<$sep> argument defaults to C<'J'>.
169              
170             B<Caveat:> the optional argument was added to this method in version
171             1.02, to belatedly track a change made in L<DateTime|DateTime> version
172             1.43 released 2017-05-29. Fixing this restores the original
173             stringification behavior of this class, which was to return an ISO-8601
174             string unless a formatter was set. Before this change, the
175             stringification separated date and time with either a C<'T'> or a
176             C<'J'>, depending on which version of L<DateTime|DateTime> was
177             installed.
178              
179             =back
180              
181             B<Note> that as of version C<0.106_01>, methods related to quarters
182             should work.
183              
184             =head1 BACKGROUND
185              
186             The Julian calendar was introduced by Julius Caesar in 46BC. It
187             featured a twelve-month year of 365 days, with a leap year in February
188             every fourth year. This calendar was adopted by the Christian church in
189             325AD. Around 532AD, Dionysius Exiguus moved the starting point of the
190             Julian calendar to the calculated moment of birth of Jesus Christ. Apart
191             from differing opinions about the start of the year (often January 1st,
192             but also Christmas, Easter, March 25th and other dates), this calendar
193             remained unchanged until the calendar reform of pope Gregory XIII in
194             1582. Some backward countries, however, used the Julian calendar until
195             the 18th century or later.
196              
197             This module uses the proleptic Julian calendar for years before 532AD,
198             or even 46BC. This means that dates are calculated as if this calendar
199             had existed unchanged from the beginning of time. The assumption is
200             made that January 1st is the first day of the year.
201              
202             Note that BC years are given as negative numbers, with 0 denoting the
203             year 1BC (there was no year 0AD!), -1 the year 2BC, etc.
204              
205             =head1 SUPPORT
206              
207             Support for this module is provided via the F<datetime@perl.org> email
208             list. See L<https://lists.perl.org/> for more details.
209              
210             Please report bugs to
211             L<https://rt.cpan.org/Public/Dist/Display.html?Name=DateTime-Calendar-Julian>,
212             L<https://github.com/trwyant/perl-DateTime-Calendar-Julian/issues>, or
213             in electronic mail to F<wyant@cpan.org>.
214              
215             =head1 AUTHOR
216              
217             Eugene van der Pijll <pijll@gmx.net>
218              
219             Thomas R. Wyant, III F<wyant at cpan dot org>
220              
221             =head1 COPYRIGHT AND LICENSE
222              
223             Copyright (c) 2003 Eugene van der Pijll. All rights reserved.
224              
225             Copyright (C) 2018-2022 Thomas R. Wyant, III
226              
227             This program is free software; you can redistribute it and/or modify it
228             under the same terms as Perl itself.
229              
230             This program is distributed in the hope that it will be useful, but
231             without any warranty; without even the implied warranty of
232             merchantability or fitness for a particular purpose.
233              
234             =head1 SEE ALSO
235              
236             L<DateTime|DateTime>
237              
238             L<DateTime::Calendar::Christian|DateTime::Calendar::Christian>
239              
240             datetime@perl.org mailing list
241              
242             L<http://datetime.perl.org/>
243              
244             =cut
245              
246             # ex: set textwidth=72 :