File Coverage

blib/lib/DateTime/Calendar/Julian.pm
Criterion Covered Total %
statement 55 55 100.0
branch 12 12 100.0
condition 3 3 100.0
subroutine 13 13 100.0
pod 5 5 100.0
total 88 88 100.0


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