File Coverage

blib/lib/DateTime/Calendar/Christian.pm
Criterion Covered Total %
statement 219 230 95.2
branch 75 86 87.2
condition 29 45 64.4
subroutine 47 51 92.1
pod 19 30 63.3
total 389 442 88.0


line stmt bran cond sub pod time code
1              
2             use 5.008004;
3 16     16   2033314  
  16         202  
4             use strict;
5 16     16   93 use warnings;
  16         32  
  16         380  
6 16     16   83  
  16         34  
  16         904  
7             our $VERSION = '0.13_02';
8              
9             use DateTime 0.1402;
10 16     16   11303 use DateTime::Calendar::Julian 0.04;
  16         6160589  
  16         757  
11 16     16   7852  
  16         13254  
  16         408  
12             use Carp ();
13 16     16   110  
  16         43  
  16         745  
14             # We're relying on DateTime's validation, but we want Carp to report
15             # errors against our caller, not ourselves. Ditto
16             # DateTime::Calendar::Julian
17             our @CARP_NOT = (
18             qw{ DateTime DateTime::Duration DateTime::Calendar::Julian },
19             );
20              
21             use overload ( 'fallback' => 1,
22 16         115 '<=>' => '_compare_overload',
23             'cmp' => '_compare_overload',
24             '-' => '_subtract_overload',
25             '+' => '_add_overload',
26             );
27 16     16   93  
  16         32  
28             use constant ARRAY_REF => ref [];
29 16     16   1866  
  16         36  
  16         44198  
30             {
31             my %reform_dates = (
32             italy => [ 1582, 10, 15 ], # including some other catholic
33             # countries (spain, portugal, ...)
34             france => [ 1582, 12, 20 ],
35             belgium => [ 1583, 1, 1 ],
36             holland => [ 1583, 1, 1 ], # or 1583-1-12?
37             liege => [ 1583, 2, 21 ],
38             augsburg => [ 1583, 2, 24 ],
39             treves => [ 1583, 10, 15 ],
40             bavaria => [ 1583, 10, 16 ],
41             tyrolia => [ 1583, 10, 16 ],
42             julich => [ 1583, 11, 13 ],
43             cologne => [ 1583, 11, 14 ], # or 1583-11-13?
44             wurzburg => [ 1583, 11, 15 ],
45             mainz => [ 1583, 11, 22 ],
46             strasbourg_diocese => [ 1583, 11, 27 ],
47             baden => [ 1583, 11, 27 ],
48             carynthia => [ 1583, 12, 25 ],
49             bohemia => [ 1584, 1, 17 ],
50             lucerne => [ 1584, 1, 22 ],
51             silesia => [ 1584, 1, 23 ],
52             westphalia => [ 1584, 7, 12 ],
53             paderborn => [ 1585, 6, 27 ],
54             hungary => [ 1587, 11, 1 ],
55             transylvania => [ 1590, 12, 25 ],
56             prussia => [ 1610, 9, 2 ],
57             hildesheim => [ 1631, 3, 26 ],
58             minden => [ 1668, 2, 12 ],
59             strasbourg => [ 1682, 2, 16 ],
60             denmark => [ 1700, 3, 1 ],
61             germany_protestant => [ 1700, 3, 1 ],
62             gelderland => [ 1700, 7, 12 ],
63             faeror => [ 1700, 11, 28 ], # or 1700-11-27?
64             iceland => [ 1700, 11, 28 ],
65             utrecht => [ 1700, 12, 12 ],
66             zurich => [ 1701, 1, 12 ],
67             friesland => [ 1701, 1, 12 ], # or 1701-01-13?
68             drente => [ 1701, 5, 12 ], # or 1701-01-12?
69             uk => [ 1752, 9, 14 ],
70             bulgaria => [ 1915, 11, 14 ], # or 1916-04-14?
71             russia => [ 1918, 2, 14 ],
72             latvia => [ 1918, 2, 15 ],
73             romania => [ 1919, 4, 14 ], # or 1924-10-14?
74             );
75              
76             # Dates are from http://www.polysyllabic.com/GregConv.html and
77             # http://privatewww.essex.ac.uk/~kent/calisto/guide/changes.htm
78             # Only those dates that both sites agree on are included at the moment.
79              
80             # ALL interpretation of the reform_date argument MUST go through here.
81             my ( $class, $rd ) = @_;
82             if ( my $ref = ref $rd ) {
83 278     278   536 if ( ARRAY_REF eq $ref ) {
84 278 100 66     1312 return DateTime->new(
    100          
    100          
85 111 100       283 year => $rd->[0],
86 21   50     615 month => $rd->[1] || 1,
      50        
      50        
      50        
      50        
      50        
87             day => $rd->[2] || 1,
88             hour => $rd->[3] || 0,
89             minute => $rd->[4] || 0,
90             second => $rd->[5] || 0,
91             nanosecond => $rd->[6] || 0,
92             );
93             } else {
94             return DateTime->from_object( object => $rd );
95             }
96 90         292 } elsif ( $rd ) {
97             if ( my $rda = $reform_dates{ my $rd_lc = lc $rd } ) {
98             ARRAY_REF eq ref $rda
99 22 100       132 and return ( $reform_dates{$rd_lc} =
100             $class->_process_reform_date( $rda ) );
101 21 100       133 return $rda;
102             }
103 1         7 if ( $rd =~ m/ \A [0-9] /smx
104             and my @rda = split qr{ [^0-9]+ }smx, $rd ) {
105 1 50 33     16 return $class->_process_reform_date( \@rda );
106             }
107 1         4 Carp::croak( "Unknown calendar region '$rd'" );
108             } elsif ( ref $class && ( ref $class )->can( 'reform_date' ) ) {
109 0         0 return $class->reform_date();
110             } else {
111 75         163 return $class->DefaultReformDate();
112             }
113 70         173 }
114             }
115              
116             __PACKAGE__->DefaultReformDate( 'Italy' );
117              
118             my ( $class, %args ) = @_;
119              
120             my $self = $class->_new( \%args );
121 215     215 1 79667  
122             if (defined $args{year}) {
123 215         666 $self->{date} = DateTime::Calendar::Julian->new(%args);
124             if ($self->{date} >= $self->{reform_date}) {
125 215 100       524 $self->{date} = DateTime->new(%args);
126 212         835 $self->_adjust_calendar;
127 212 100       80543 }
128 131         8860 }
129 127         30574  
130             return $self;
131             }
132              
133 211         6387 my ( $class, $arg, $method ) = @_;
134              
135             my $self = bless {
136             reform_date => $class->_process_reform_date(
137 241     241   487 delete $arg->{reform_date} ),
138             }, ref $class || $class;
139              
140             if ( $method ) {
141 241   66     668 $self->{date} = DateTime->$method( %{ $arg } );
142             $self->_adjust_calendar();
143             }
144 241 100       46616  
145 10         16 return $self;
  10         46  
146 10         3641 }
147              
148             my $self = shift;
149 241         498  
150             if ($self->is_gregorian and $self->{date} < $self->{reform_date}) {
151             $self->{date} = DateTime::Calendar::Julian->from_object(
152             object => $self->{date} );
153 335     335   651 } elsif ($self->is_julian and $self->{date} >= $self->{reform_date}) {
154             $self->{date} = DateTime->from_object( object => $self->{date} );
155 335 100 100     673 }
    100 100        
156              
157 20         1700 return;
158             }
159 15         1059  
160             return $_[0]{date}->isa('DateTime::Calendar::Julian');
161             }
162 335         21655  
163             return ! $_[0]->is_julian;
164             }
165              
166 735     735 1 22345 my ( $self ) = @_;
167             return $self->is_julian() ? 'Julian' : 'Gregorian';
168             }
169              
170 352     352 1 1893 my ( $class, %args ) = @_;
171              
172             return $class->_new( \%args, 'from_epoch' );
173             }
174 40     40 1 708  
175 40 100       83
176              
177             my ( $class, %args ) = @_;
178              
179 5     5 1 1587 return $class->_new( \%args, 'from_object' );
180             }
181 5         18  
182             my ( $class, %args ) = @_;
183              
184 2     2 0 1222 my $self = $class->_new( \%args );
185              
186 0     0 1 0 my $rd = $self->reform_date();
187             my $ry = $rd->year;
188              
189 5     5 1 3700 if ( $args{year} > $ry ) {
190             $self->{date} = DateTime->from_day_of_year( %args );
191 5         22 } elsif ( $args{year} < $ry ) {
192             $self->{date} = DateTime::Calendar::Julian->from_day_of_year(
193             %args );
194             } else {
195 16     16 1 9722 my $dev = DateTime::Calendar::Christian->gregorian_deviation( $rd );
196             my $rdoy = $rd->day_of_year - $dev;
197 16         72 if ( $args{day_of_year} < $rdoy ) {
198             $self->{date} = DateTime::Calendar::Julian->from_day_of_year(
199 16         53 %args );
200 16         57 } else {
201             $args{day_of_year} += $dev;
202 16 100       126 $self->{date} = DateTime->from_day_of_year( %args );
    100          
203 4         61 }
204             }
205 4         28  
206             return $self;
207             }
208 8         42  
209 8         238 # This method assumes that both current month and next month exists.
210 8 100       56 # There can be problems when the number of missing days is larger than
211 6         37 # 27.
212             my ($class, %p) = @_;
213             # First, determine the first day of the next month.
214 2         6 $p{day} = 1;
215 2         13 $p{month}++;
216             if ($p{month} > 12) {
217             $p{month} -= 12;
218             $p{year}++;
219 16         6455 }
220             my $self = $class->new( %p );
221              
222             if ($self->month != $p{month}) {
223             # Apparently, month N+1 does not have a day 1.
224             # This means that this date is removed in the calendar reform,
225             # and the last day of month N is the last day before the reform.
226 72     72 1 2235  
227             $self = $self->from_object( object => $self->{reform_date} );
228 72         129 }
229 72         95  
230 72 100       159 # Subtract one. That should be the last day of the month.
231 66         92 $self->subtract( days => 1 );
232 66         87  
233             return $self;
234 72         185 }
235              
236 72 100       158 my $self = shift;
237              
238             my $new = {};
239             $new->{reform_date} = $self->{reform_date}->clone;
240             $new->{date} = $self->{date}->clone if exists $self->{date};
241 1         8 return bless $new, ref $self;
242             }
243              
244             my $self = shift;
245 72         487  
246             my $year = $self->year;
247 72         261 # This could go wrong if the number of missing days is more than
248             # about 300, and reform_date lies at the beginning of the next year.
249             if ($year != $self->{reform_date}->year) {
250             return $self->{date}->is_leap_year;
251 21     21 0 6103 }
252              
253 21         39 # Difficult case: $year is in the year of the calendar reform
254 21         67 # Test if Feb 29 exists
255 21 50       264 my $d = eval { $self->new( year => $year,
256 21         206 month => 2,
257             day => 29,
258             ) };
259             return defined($d) && $d->month == 2 && $d->day == 29;
260 8     8 1 29 }
261              
262 8         15 my ($dt, $dur, $reversed) = @_;
263              
264             if ($reversed) {
265 8 100       42 ($dur, $dt) = ($dt, $dur);
266 2         13 }
267              
268             my $new = $dt->clone;
269             $new->add_duration($dur);
270             return $new;
271 6         29 }
  6         12  
272              
273             my ($date1, $date2, $reversed) = @_;
274              
275 6   100     819 if ($reversed) {
276             ($date2, $date1) = ($date1, $date2);
277             }
278              
279 2     2   847 if (UNIVERSAL::isa($date2, 'DateTime::Duration')) {
280             my $new = $date1->clone;
281 2 50       5 $new->add_duration( $date2->inverse );
282 0         0 return $new;
283             } else {
284             my $date3 = DateTime->from_object( object => $date2 );
285 2         8 return $date1->{date}->subtract_datetime($date3);
286 2         7 }
287 2         13 }
288              
289              
290              
291 5     5   3274  
292             my $self = shift;
293 5 50       15 my $dt = shift;
294 0         0  
295             return $self->{date} - $dt->{date};
296             }
297 5 100       21  
298 2         5 my ($self, $dur) = @_;
299 2         9  
300 2         12 # According to the papal bull and the English royal decree that
301             # introduced the Gregorian calendar, dates should be calculated as
302 3         10 # if the change did not happen; this makes date math very easy in
303 3         295 # most cases...
304             # But not all.
305              
306             my %deltas = $dur->deltas;
307 20     20 1 101  
308             # We take the components of DateTime::Duration in the same order
309 79     79 1 4526 # that DateTime itself does.
310              
311 79     79 0 7020 if ( my $days = delete $deltas{days} ) {
312             # Days must not be adjusted further, for sanity's sake. See RT
313             # 140734.
314 0     0 0 0 $self->{date}->add( days => $days );
315 0         0 $self->_adjust_calendar;
316             }
317 0         0  
318             if ( my $months = delete $deltas{months} ) {
319             # This must be adjusted to avoid regression.
320             # TODO there are other sane things to do here.
321 103     103 0 9588  
322             my $start_jul = $self->is_julian;
323              
324             $self->{date}->add( months => $months);
325             $self->_adjust_calendar;
326              
327             # The intent of the following code is to implement the usual
328             # conversion, by adding or subtracting the Gregorian deviation
329 103         234 # as of the reform date. An example would be that George
330             # Washington was born on February 11 1732 Julian. The reform
331             # took this to February 22 Gregorian, and that is the date
332             # usually given, even though a couple more days' difference has
333             # accumulated since then.
334 103 100       1399 #
335             # A straightforward implementation would be to do the change in
336             # two steps: addition would be in Julian to the reform date and
337 80         310 # then in Gregorian for the rest of the interval, and vice versa
338 80         68332 # for subtraction. But that would involve going back and redoing
339             # tha calculation.
340             #
341 103 100       268 # What this implementation does is to recognize that part of the
342             # calculation has been done in the wrong calendar, and correct
343             # for the number of leap year days that did (or did not) occur
344             # under the correct calendar.
345 13         25 #
346             # The original implementation nade this correction in all cases.
347 13         43 # But as Christian Carey found out, this gives incorrect (or at
348 13         11858 # least very surprising) results when adding or subtracting
349             # enough days to not only cross the reform date but cross one of
350             # the years affected by the reform. His example was that adding
351             # 43,099 days to 1583-03-01 (Julian) correctly gave 1700-03-11
352             # (Gregorian), but adding 43,100 days also gave 1700-03-11
353             # rather than 1700-03-12. This is described (sketchily) in RT
354             # 140734.
355             #
356             # The solution I have adopted is to pick apart the interval the
357             # same way DateTime does (and is documented to do) and only
358             # apply the correction to the month portion of the interval.
359             # This fixes RT 140734, but preserves the fact that if you
360             # calculate GW's Nth birthday by adding N years to his Julian
361             # birthday, the result is always either February 11 Julian or
362             # February 22 Gregorian, using the UK reform date.
363             #
364             # -- TRW
365              
366             my $dd;
367             if ($start_jul and $self->is_gregorian) {
368              
369             # The period after reform_date has been calculated in Julian
370             # instead of in Gregorian; this may have introduced extra
371             # leap days; the date should be set back.
372             $dd = $self->gregorian_deviation($self->{date}) -
373             $self->gregorian_deviation($self->{reform_date});
374             } elsif (not $start_jul and $self->is_julian) {
375              
376             # The period before reform_date has been calculated in
377             # Gregorian instead of in Julian; we may have to introduce
378             # extra leap days; the date should be set back
379             $dd = $self->gregorian_deviation($self->{reform_date}) -
380             $self->gregorian_deviation($self->{date});
381             }
382              
383             $self->{date}->subtract( days => $dd ) if $dd;
384              
385             }
386              
387             if ( keys %deltas ) {
388             $self->{date}->add( %deltas );
389 13         26 $self->_adjust_calendar;
390 13 100 66     54 }
    50 33        
391              
392             return $self;
393             }
394              
395             my ($class, $date) = @_;
396 9         23  
397             $date ||= $class;
398              
399             $date = DateTime::Calendar::Julian->from_object( object => $date );
400             return $date->gregorian_deviation;
401             }
402              
403 4         12 my ($class, $date) = @_;
404              
405             $date ||= $class;
406 13 100       253  
407             $date = DateTime->from_object( object => $date )
408             unless 'DateTime' eq ref $date;
409              
410 103 50       3942 my $year = $date->{local_c}{year};
411 103         380 $year-- if $date->{local_c}{month} <= 2;
412 103         20429  
413             return DateTime::Calendar::Julian::_floor($year/100)-DateTime::Calendar::Julian::_floor($year/400)-2;
414             }
415 103         297  
416              
417             # Almost the same as DateTime::week
418             {
419 60     60 1 364 my $self = shift;
420              
421 60   66     221 unless ( defined $self->{date}{local_c}{week_year} )
422             {
423 60         280 my $doy = $self->day_of_year;
424 60         20061 my $dow = $self->day_of_week;
425              
426             # Convert to closest Thursday:
427             $doy += 4-$dow;
428 2     2 1 10  
429             $self->{date}{local_c}{week_number} =
430 2   33     12 int(($doy + 6) / 7);
431              
432 2 50       10 if ( $self->{date}{local_c}{week_number} == 0 )
433             {
434             $self->{date}{local_c}{week_year} = $self->year - 1;
435 2         186 $self->{date}{local_c}{week_number} =
436 2 100       7 $self->_weeks_in_year( $self->{date}{local_c}{week_year} );
437             }
438 2         7 elsif ( $self->{date}{local_c}{week_number} >
439             $self->_weeks_in_year( $self->year ) )
440             {
441 255     255 1 2091 $self->{date}{local_c}{week_number} = 1;
442             $self->{date}{local_c}{week_year} = $self->year + 1;
443             }
444             else
445             {
446 42     42 0 139 $self->{date}{local_c}{week_year} = $self->year;
447             }
448 42 50       100 }
449              
450 42         78 return @{ $self->{date}{local_c} }{ 'week_year', 'week_number' }
451 42         83 }
452              
453             # This routine assumes that the month December actually exists.
454 42         137 # There can be problems if the number of missing days is larger than 30.
455             {
456             my $self = shift;
457 42         110 my $year = shift;
458              
459 42 100       118 my $dec_31 = $self->last_day_of_month( year => $year, month => 12 );
    100          
460              
461 4         12 my $days_in_yr = $dec_31->day_of_year;
462             my $dow = $dec_31->day_of_week;
463 4         23  
464             return int(($days_in_yr +
465             ($dow >= 4 ? 7 - $dow : - $dow)) / 7
466             + 0.5);
467             }
468 6         12  
469 6         11 my ( $self, %p ) = @_;
470              
471             Carp::croak( 'Cannot change reform_date with set()' )
472             if exists $p{reform_date};
473 32         63 Carp::carp( 'You passed a locale to the set() method.',
474             ' You should use set_locale() instead, as using set() may ',
475             'alter the local time near a DST boundary.' )
476             if $p{locale};
477 42         181  
  42         142  
478             my %old_p =
479             ( reform_date => $self->{reform_date},
480             map { $_ => $self->$_() }
481             qw( year month day hour minute second nanosecond
482             locale time_zone )
483             );
484 42     42   160  
485 42         53 my $new_dt = (ref $self)->new( %old_p, %p );
486              
487 42         80 %$self = %$new_dt;
488              
489 42         97 return $self;
490 42         79 }
491              
492 42 100       347 my ( $self, @arg ) = @_;
493             $self->{date}->set_time_zone( @arg );
494             $self->_adjust_calendar;
495             return $self;
496             }
497              
498 3     3 0 14 # This code assumes there is a month of December of the previous year.
499             my $self = shift;
500              
501 3 50       9 my $doy = $self->{date}->doy;
502             if ($self->year == $self->reform_date->year &&
503             $self >= $self->reform_date ) {
504             $doy -= $self->gregorian_deviation;
505 3 50       7 my $end_of_year = $self->last_day_of_month( year => $self->year - 1,
506             month => 12 );
507             $doy = ($self->utc_rd_values)[0] - ($end_of_year->utc_rd_values)[0];
508             }
509 3         8 return $doy;
  27         133  
510             }
511              
512             return shift->day_of_year - 1;
513             }
514 3         34  
515             my ( $self, @fmts ) = @_;
516 3         21 foreach ( @fmts ) {
517             s/ %\{ ( calendar_name ) \} / $self->_strftime_helper( "$1" ) /smxge;
518 3         15 }
519             return $self->{date}->strftime( @fmts );
520             }
521              
522 2     2 0 1420 my ( $self, $method ) = @_;
523 2         23 my $rslt = $self->$method();
524 2         640 $rslt =~ s/ % /%%/smxg;
525 2         5 return $rslt;
526             }
527              
528             my ( $self ) = @_;
529             return (
530 104     104 1 193 $self->reform_date,
531             $self->{date} ? $self->{date} : (),
532 104         322 );
533 104 100 100     409 }
534              
535 24         1372 my ( $self, undef, $reform, $date ) = @_;
536 24         504 $self->{reform_date} = $reform;
537             defined $date
538 24         61 and $self->{date} = $date;
539             return $self;
540 104         1602 }
541              
542              
543             # Delegate to $self->{date}
544 10     10 1 54 for my $sub (
545             # The following by Eugene van der Pijll
546             qw/year ce_year month month_0 month_name month_abbr
547             day_of_month day_of_month_0 day_of_week day_of_week_0
548 2     2 1 11 day_name day_abbr ymd mdy dmy hour minute second hms
549 2         4 nanosecond millisecond microsecond
550 2         12 iso8601 datetime week_year week_number
  2         7  
551             time_zone offset is_dst time_zone_short_name locale
552 2         10 utc_rd_values utc_rd_as_seconds local_rd_as_seconds jd
553             mjd epoch utc_year compare /,
554             # these should be replaced with a corrected version -- EvdP
555             qw/truncate/,
556 2     2   4 # The following by Thomas R. Wyant, III
557 2         5 qw/
558 2         6 am_or_pm compare_ignore_floating
559 2         19 christian_era secular_era era era_abbr era_name
560             delta_days delta_md delta_ms duration_class format_cldr
561             formatter fractional_second hires_epoch
562             hour_1 hour_12 hour_12_0 is_finite is_infinite
563 11     11 0 279 leap_seconds local_day_of_week local_rd_values
564             quarter quarter_0 quarter_name quarter_abbr
565             set_locale set_formatter subtract_datetime_absolute
566 11 100       31 time_zone_long_name
567             year_with_christian_era year_with_era
568             year_with_secular_era
569             /,
570             # Because Eugene accepted week_number and week_year even
571 11     11 0 9283 # though they might span the reform date, I will accept
572 11         29 # the following -- TRW
573             qw/
574 11 100       31 week_of_month
575 11         58 weekday_of_month
576             /,
577             # Missed in the above somehow --TRW
578             qw/
579             day_of_quarter
580             day_of_quarter_0
581             is_between
582             is_last_day_of_month
583             is_last_day_of_quarter
584             is_last_day_of_year
585             month_length
586             quarter_length
587             rfc3339
588             stringify
589             year_length
590             /,
591             ) {
592             no strict 'refs';
593             *$sub = sub {
594             my $self = shift;
595             Carp::croak( "Empty date object in call to $sub" )
596             unless exists $self->{date};
597             $self->{date}->$sub(@_)
598             };
599             }
600              
601             my ( $self, $other ) = @_;
602             $self->{date}
603             or return -1;
604             return $self->{date}->_compare_overload( $other );
605             }
606              
607             # Delegate to set();
608              
609             for my $name ( qw/ year month day hour minute second nanosecond / ) {
610             my $sub = "set_$name";
611             no strict 'refs';
612             *$sub = sub {
613             my ( $self, $value ) = @_;
614             return $self->set( $name => $value );
615             };
616             }
617              
618             {
619             no warnings 'once';
620              
621             *mon = \&month;
622             *mon_0 = \&month_0;
623             *day = \&day_of_month;
624             *mday = \&day_of_month;
625             *day_0 = \&day_of_month_0;
626             *mday_0 = \&day_of_month_0;
627             *wday = \&day_of_week;
628 16     16   179 *dow = \&day_of_week;
  16         51  
  16         2618  
629             *wday_0 = \&day_of_week_0;
630 731     731   41920 *dow_0 = \&day_of_week_0;
631             *doq = \&day_of_quarter;
632 731 50       1421 *doq_0 = \&day_of_quarter_0;
633 731         2096 *doy = \&day_of_year;
634             *doy_0 = \&day_of_year_0;
635             *date = \&ymd;
636             *min = \&minute;
637             *sec = \&second;
638 55     55   3361 *DateTime::Calendar::Christian::time = \&hms;
639             }
640 55 100       192  
641 53         315 shift;
642             return DateTime->DefaultLocale( @_ );
643             }
644              
645             {
646             my $DefaultReformDate;
647              
648 16     16   118 my ( $class, $rd ) = @_;
  16         52  
  16         1168  
649             $rd
650 0     0   0 and $DefaultReformDate = $class->_process_reform_date( $rd );
651 0         0 return $DefaultReformDate;
652             }
653             }
654              
655             1;
656 16     16   147  
  16         55  
  16         5025  
657             =head1 NAME
658              
659             DateTime::Calendar::Christian - Dates in the Christian calendar
660              
661             =head1 SYNOPSIS
662              
663             use DateTime::Calendar::Christian;
664              
665             $dt = DateTime::Calendar::Christian->new( year => 1752,
666             month => 10,
667             day => 4,
668             reform_date => $datetime );
669              
670             =head1 DESCRIPTION
671              
672             DateTime::Calendar::Christian is the implementation of the combined
673             Julian and Gregorian calendar.
674              
675             See L<DateTime> for information about most of the methods.
676              
677             =head1 BACKGROUND
678              
679 0     0 0 0 The Julian calendar, introduced in Roman times, had an average year
680 0         0 length of 365.25 days, about 0.03 days more than the correct number. When
681             this difference had accumulated to about ten days, the calendar was
682             reformed by pope Gregory XIII, who introduced a new leap year rule. To
683             correct for the error that had built up over the centuries, ten days
684             were skipped in October 1582. In most countries, the change date was
685             later than that; England went Gregorian in 1752, and Russia didn't
686             change over until 1918.
687 86     86 1 187  
688 86 100       259 =head1 METHODS
689              
690 86         6985 This manpage only describes those methods that differ from those of
691             DateTime. See L<DateTime|DateTime> for all other methods. A spirited
692             attempt has been made to implement the B<entire> L<DateTime|DateTime>
693             interface.
694              
695             Methods not documented below may behave in unexpected ways when they
696             involve dates both before and after the reform date. For example,
697             C<week_number()>, when called on a date in the reform year but after the
698             reform, returns the week number in the Gregorian year, not the actual
699             year.
700              
701             B<Caveat programmer.>
702              
703             =over
704              
705             =item * new( ... )
706              
707             Besides the usual parameters ("year", "month", "day", "hour", "minute",
708             "second", "nanosecond", "locale", "formatter" and "time_zone"),
709             this class method takes the additional "reform_date" parameter. See
710             L<SPECIFYING REFORM DATE|/SPECIFYING REFORM DATE> below for how to
711             specify this.
712              
713             If this method is used as an instance method and no "reform_date" is
714             given, the "reform_date" of the returned object is the same as the one
715             of the object used to call this constructor. This means you can make
716             "date generators", that implement a calendar with a fixed reform date:
717              
718             $english_calendar = DateTime::Calendar::Christian(
719             reform_date => DateTime->new( year => 1752,
720             month => 9,
721             day => 14 )
722             );
723              
724             or equivalently:
725              
726             $english_calendar = DateTime::Calendar::Christian(
727             reform_date => 'UK' );
728              
729             You can use this generator to create dates with the given reform_date:
730              
731             $born = $english_calendar->new( year => 1732, month => 2, day => 22 );
732             $died = $english_calendar->new( year => 1799, month => 12, day => 14 );
733              
734             When a date is given that was skipped during a calendar reform, it is
735             assumed that it is a Gregorian date, which is then converted to the
736             corresponding Julian date. This behaviour may change in future
737             versions. If a date is given that can be both Julian and Gregorian, it
738             will be considered Julian. This is a bug.
739              
740             =item * from_epoch, from_object, from_day_of_year, last_day_of_month
741              
742             These methods accept an additional "reform_date" argument. Note that the
743             epoch is defined for most (all?) systems as a date in the Gregorian
744             calendar. B<But> this module will still represent it as a Julian date if
745             the epoch gives a date before the reform date.
746              
747             =item * reform_date
748              
749             Returns the date of the calendar reform, as a DateTime object.
750              
751             =item * is_julian, is_gregorian
752              
753             Return true or false indicating whether the datetime object is in a
754             specific calendar.
755              
756             =item * calendar_name
757              
758             Return C<'Julian'> or C<'Gregorian'>, depending on the value returned by
759             C<is_julian()>.
760              
761             =item * is_leap_year
762              
763             This method returns a true or false indicating whether or not the
764             datetime object is in a leap year. If the object is in the year of the
765             date reform, this method indicates whether there is a leap day in that
766             year, irrespective of whether the datetime object is in the same
767             calendar as the possible leap day.
768              
769             =item * days_in_year
770              
771             Returns the number of days in the year. Is equal to 365 or 366, except
772             for the year(s) of the calendar reform.
773              
774             =item * day_of_year, day_of_year_0
775              
776             Returns the day of the year, either one-based or zero-based depending on
777             the actual method called. In the reform year this is the actual number
778             of days from January 1 (Julian) to the current date, whether Julian or
779             Gregorian.
780              
781             =item * add, subtract
782              
783             These are done in terms of duration, so that, for example, subtracting a
784             day from the reform date (Gregorian) gets you the day before the reform
785             date (Julian).
786              
787             When months and/or years are involved, the result is modified from a
788             straight I<rata die> calculation to add or subtract the number of days
789             skipped by the reform. Without this modification, George Washington's
790             birthday of February 11 Julian would drift forward in the Gregorian
791             calendar as the difference between the two calendars increased. With
792             this modification, it is February 22 Gregorian regardless of the actual
793             days difference between the two calendars.
794              
795             B<Note> that in versions C<0.12> and earlier this modification was
796             applied to B<all> durations. This produced anomalous (i.e. wrong)
797             results when adding or subtracting large numbers of days.
798              
799             Beginning with version C<0.12_01> the modification is only applied to
800             months (and years, since years are folded into months when a
801             L<DateTime::Duration|DateTime::Duration> object is created.) The actual
802             order of operation is that specified by L<DateTime|DateTime>: the
803             C<days> component of the duration is applied first, then C<months> (with
804             the above modification), then C<minutes>, C<seconds>, and
805             C<nanoseconds>. This can give rise to commutation/round-trip failures,
806             and these may be more common under this change, but this appears to be
807             the price of fixing the bug described in the previous paragraph.
808              
809             The L<DateTime|DateTime> documentation notes that this can happen in
810             that module even in simple cases, such as adding a month to (say)
811             January 31. It also notes that if order of operation is an issue, you
812             can force it by doing something like
813              
814             $dt->add( months => 3 )->add( days => 5 );
815              
816             to force months to be done first.
817              
818             =item * strftime
819              
820             This override allows selected methods of this class (i.e. not inherited
821             from DateTime) to be used in the C<'%{method_name}'> construction in
822             templates. The only method allowed at the moment is C<calendar_name>.
823              
824             =item * gregorian_deviation( [$datetime] )
825              
826             This method returns the difference in days between the Gregorian and the
827             Julian calendar. If the parameter $datetime is given, it will be used to
828             calculate the result; in this case this method can be used as a class
829             method.
830              
831             This deviation increments on March 1 (Julian) of any year which is a
832             leap year in the Julian calendar but not the Gregorian calendar.
833              
834             =item * julian_deviation( [$datetime] )
835              
836             This method was added in version 0.13.
837              
838             This method returns the difference in days between the Gregorian and the
839             Julian calendar. If the parameter $datetime is given, it will be used to
840             calculate the result; in this case this method can be used as a class
841             method.
842              
843             This deviation increments on March 1 (Gregorian) of any year which is a
844             leap year in the Julian calendar but not the Gregorian calendar.
845              
846             =item * DefaultReformDate
847              
848             This static method returns a L<DateTime|DateTime> object representing
849             the default reform date. If called with an argument, the argument
850             becomes the new reform date, which is returned. The argument is either a
851             L<DateTime|DateTime> object (or something that can be converted into
852             one) or a reform date location name. See
853             L<SPECIFYING REFORM DATE|/SPECIFYING REFORM DATE> below for what kind of
854             arguments can be specified.
855              
856             =back
857              
858             =head1 INTERFACES
859              
860             This module implements the following interfaces:
861              
862             =over
863              
864             =item * Storable
865              
866             This module implements the Storable interface. All the donkey work is
867             done by L<DateTIme|DateTime>.
868              
869             =item * Overloading
870              
871             Addition, subtraction, and both string and numeric comparison are
872             overloaded. Objects with no date (that is, objects initialized as "date
873             generators") collate before objects with a date.
874              
875             =back
876              
877             =head1 SPECIFYING REFORM DATE
878              
879             The reform date represents the first date the Gregorian calendar came
880             into use. It can be specified a number of different ways:
881              
882             =over
883              
884             =item * A DateTime object, or an object that can be converted into one.
885              
886             =item * A location name (case-insensitive) from the following list:
887              
888             Italy -------------- 1582-10-15 # and some other Catholic countries
889             France ------------- 1582-12-20
890             Belgium ------------ 1583-1-1
891             Holland ------------ 1583-1-1 # or 1583-1-12?
892             Liege -------------- 1583-2-21
893             Augsburg ----------- 1583-2-24
894             Treves ------------- 1583-10-15
895             Bavaria ------------ 1583-10-16
896             Tyrolia ------------ 1583-10-16
897             Julich ------------- 1583-11-13
898             Cologne ------------ 1583-11-14 # or 1583-11-13?
899             Wurzburg ----------- 1583-11-15
900             Mainz -------------- 1583-11-22
901             Strasbourg_Diocese - 1583-11-27
902             Baden -------------- 1583-11-27
903             Carynthia ---------- 1583-12-25
904             Bohemia ------------ 1584-1-17
905             Lucerne ------------ 1584-1-22
906             Silesia ------------ 1584-1-23
907             Westphalia --------- 1584-7-12
908             Paderborn ---------- 1585-6-27
909             Hungary ------------ 1587-11-1
910             Transylvania ------- 1590-12-25
911             Prussia ------------ 1610-9-2
912             Hildesheim --------- 1631-3-26
913             Minden ------------- 1668-2-12
914             Strasbourg --------- 1682-2-16
915             Denmark ------------ 1700-3-1
916             Germany_Protestant - 1700-3-1
917             Gelderland --------- 1700-7-12
918             Faeror ------------- 1700-11-28 # or 1700-11-27?
919             Iceland ------------ 1700-11-28
920             Utrecht ------------ 1700-12-12
921             Zurich ------------- 1701-1-12
922             Friesland ---------- 1701-1-12 # or 1701-01-13?
923             Drente ------------- 1701-5-12 # or 1701-01-12?
924             UK ----------------- 1752-9-14
925             Bulgaria ----------- 1915-11-14 # or 1916-04-14?
926             Russia ------------- 1918-2-14
927             Latvia ------------- 1918-2-15
928             Romania ------------ 1919-4-14 # or 1924-10-14?
929              
930             =item * An array reference.
931              
932             The first seven elements of the array are year, month, day, hour,
933             minute, second and nanosecond. Element C<[0]> is the only one that is
934             required. Elements C<[1]> and C<[2]> default to C<1>, and the rest to
935             C<0>.
936              
937             =item * An ISO-8601-ish string.
938              
939             The string is split on non-numerics, and the reform date initialized
940             from a reference to the resultant array, as described in the previous
941             item. The string B<must> be the punctuated form; that is, C<'1752-9-14'>
942             will work, but C<'17520914'> will not. There must not be a zone
943             specification, and the year must not be signed.
944              
945             =back
946              
947             =head1 BUGS
948              
949             =over
950              
951             =item * There are problems with calendars switch to Gregorian before 200 AD or after about 4000 AD. Before 200 AD, this switch leads to duplication of dates. After about 4000 AD, there could be entire missing months. (The module can handle dates before 200 AD or after 4000 AD just fine; it's just the calendar reform dates that should be inside these limits.)
952              
953             =item * There may be functions that give the wrong results for the year of the calendar reform. The function C<truncate()> is a known problem, and C<today()> may be a problem. If you find any more problems, please let me know.
954              
955             =back
956              
957             =head1 SUPPORT
958              
959             Support for this module is provided via the F<datetime@perl.org> email
960             list. See L<https://lists.perl.org/> for more details.
961              
962             Please report bugs to
963             L<https://rt.cpan.org/Public/Dist/Display.html?Name=DateTime-Calendar-Christian>,
964             L<https://github.com/trwyant/perl-DateTime-Calendar-Christian/issues>, or
965             in electronic mail to F<wyant@cpan.org>.
966              
967             =head1 AUTHOR
968              
969             Eugene van der Pijll <pijll@gmx.net>
970              
971             Thomas R. Wyant, III F<wyant at cpan dot org>
972              
973             =head1 COPYRIGHT
974              
975             Copyright (c) 2003 Eugene van der Pijll. All rights reserved.
976              
977             Copyright (C) 2016-2022 Thomas R. Wyant, III
978              
979             This program is free software; you can redistribute it and/or modify it
980             under the same terms as Perl itself; either the GNU General Public
981             License version 1 (or, at your option, any later version) or the
982             Artistic License. For more details, see the full text of the licenses in
983             the directory LICENSES.
984              
985             This program is distributed in the hope that it will be useful, but
986             without any warranty; without even the implied warranty of
987             merchantability or fitness for a particular purpose.
988              
989             =head1 SEE ALSO
990              
991             L<DateTime>, L<DateTime::Calendar::Julian>
992              
993             datetime@perl.org mailing list
994              
995             =cut
996              
997             # ex: set textwidth=72 :