line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
package Date::Convert; |
3
|
|
|
|
|
|
|
|
4
|
5
|
|
|
5
|
|
4584
|
use Carp; |
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
1632
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
$VERSION="0.16"; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
$VERSION=$VERSION; # to make -w happy. :) |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# methods that every class should have: |
12
|
|
|
|
|
|
|
# initialize, day, date, date_string |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# methods that are recommended if applicable: |
15
|
|
|
|
|
|
|
# year, month, day, is_leap |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
$BEGINNING=1721426; # 1 Jan 1 in the Gregorian calendar, although technically, |
19
|
|
|
|
|
|
|
# the Gregorian calendar didn't exist at the time. |
20
|
|
|
|
|
|
|
$VERSION_TODAY=2450522; # today in JDN, when I wrote this. |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
sub new { # straight out of the perlobj manpage: |
24
|
17
|
|
|
17
|
1
|
348
|
my $class = shift; |
25
|
17
|
|
|
|
|
36
|
my $self = {}; |
26
|
17
|
|
|
|
|
44
|
bless $self, $class; |
27
|
17
|
|
|
|
|
59
|
$self->initialize(@_); |
28
|
17
|
|
|
|
|
55
|
return $self; |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub initialize { |
33
|
2
|
|
|
2
|
1
|
3
|
my $self = shift; |
34
|
2
|
|
33
|
|
|
8
|
my $val = shift || $VERSION_TODAY; |
35
|
2
|
50
|
|
|
|
8
|
carp "Date::Convert is not reliable before Absolute $BEGINNING" |
36
|
|
|
|
|
|
|
if $val < $BEGINNING; |
37
|
2
|
|
|
|
|
14
|
$$self{absol}=$val; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub clean { |
43
|
15
|
|
|
15
|
0
|
20
|
my $self = shift; |
44
|
15
|
|
|
|
|
16
|
my $key; |
45
|
15
|
|
|
|
|
54
|
foreach $key (keys %$self) { |
46
|
62
|
100
|
|
|
|
166
|
delete $$self{$key} unless $key eq 'absol'; |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub convert { |
53
|
15
|
|
|
15
|
1
|
169
|
my $class = shift; |
54
|
15
|
|
|
|
|
18
|
my $self = shift; |
55
|
15
|
|
|
|
|
73
|
$self->clean; |
56
|
15
|
|
|
|
|
55
|
bless $self, $class; |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub absol { |
63
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
64
|
0
|
|
|
|
|
0
|
return $$self{absol}; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
package Date::Convert::Gregorian; |
72
|
|
|
|
|
|
|
|
73
|
5
|
|
|
5
|
|
26
|
use Carp; |
|
5
|
|
|
|
|
6
|
|
|
5
|
|
|
|
|
5058
|
|
74
|
|
|
|
|
|
|
@ISA = qw ( Date::Convert ); |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
$GREG_BEGINNING=1721426; # 1 Jan 1 in the Gregorian calendar, although |
77
|
|
|
|
|
|
|
# technically, the Gregorian calendar didn't exist at |
78
|
|
|
|
|
|
|
# the time. |
79
|
|
|
|
|
|
|
@MONTHS_SHORT = qw ( nil Jan Feb Mar Apr May Jun July Aug Sep Oct Nov Dec ); |
80
|
|
|
|
|
|
|
@MONTH_ENDS = qw ( 0 31 59 90 120 151 181 212 243 273 304 334 365 ); |
81
|
|
|
|
|
|
|
@LEAP_ENDS = qw ( 0 31 60 91 121 152 182 213 244 274 305 335 366 ); |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
$NORMAL_YEAR = 365; |
84
|
|
|
|
|
|
|
$LEAP_YEAR = $NORMAL_YEAR + 1; |
85
|
|
|
|
|
|
|
$FOUR_YEARS = 4 * $NORMAL_YEAR + 1; # one leap year every four years |
86
|
|
|
|
|
|
|
$CENTURY = 25 * $FOUR_YEARS - 1; # centuries aren't leap years . . . |
87
|
|
|
|
|
|
|
$FOUR_CENTURIES = 4 * $CENTURY + 1; # . . .except every four centuries. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub year { |
91
|
28
|
|
|
28
|
|
32
|
my $self = shift; |
92
|
28
|
100
|
|
|
|
101
|
return $$self{year} if exists $$self{year}; # no point recalculating. |
93
|
8
|
|
|
|
|
13
|
my $days; |
94
|
|
|
|
|
|
|
my $year; |
95
|
|
|
|
|
|
|
# note: years and days are initially days *before* today, rather than |
96
|
|
|
|
|
|
|
# today's date. This is because of fenceposts. :) |
97
|
8
|
|
|
|
|
22
|
$days = $$self{absol} - $GREG_BEGINNING; |
98
|
8
|
50
|
|
|
|
22
|
if (($days+1) % $FOUR_CENTURIES) { # normal case |
99
|
8
|
|
|
|
|
21
|
$year = int ($days / $FOUR_CENTURIES) * 400; |
100
|
8
|
|
|
|
|
10
|
$days %= $FOUR_CENTURIES; |
101
|
8
|
|
|
|
|
16
|
$year += int ($days / $CENTURY) * 100; # years. |
102
|
8
|
|
|
|
|
8
|
$days %= $CENTURY; |
103
|
8
|
|
|
|
|
14
|
$year += int ($days / $FOUR_YEARS) * 4; |
104
|
8
|
|
|
|
|
10
|
$days %= $FOUR_YEARS; |
105
|
8
|
50
|
|
|
|
16
|
if (($days+1) % $FOUR_YEARS) { |
106
|
8
|
|
|
|
|
11
|
$year += int ($days / $NORMAL_YEAR); # fence post from year 1 |
107
|
8
|
|
|
|
|
46
|
$days %= $NORMAL_YEAR; |
108
|
8
|
|
|
|
|
9
|
$days += 1; # today |
109
|
8
|
|
|
|
|
12
|
$year += 1; |
110
|
|
|
|
|
|
|
} else { |
111
|
0
|
|
|
|
|
0
|
$year += int ($days / $NORMAL_YEAR + 1) - 1; |
112
|
0
|
|
|
|
|
0
|
$days = $LEAP_YEAR; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
} else { # exact four century boundary. Uh oh. . . |
115
|
0
|
|
|
|
|
0
|
$year = int ($days / $FOUR_CENTURIES + 1) * 400; |
116
|
0
|
|
|
|
|
0
|
$days = $LEAP_YEAR; # correction for later. |
117
|
|
|
|
|
|
|
} |
118
|
8
|
|
|
|
|
11
|
$$self{year}=$year; |
119
|
8
|
|
|
|
|
13
|
$$self{days_into_year}=$days; |
120
|
8
|
|
|
|
|
14
|
return $year; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub is_leap { |
127
|
17
|
|
|
17
|
|
22
|
my $self = shift; |
128
|
17
|
|
66
|
|
|
64
|
my $year = shift || $self->year; # so is_leap can be static or method |
129
|
17
|
100
|
66
|
|
|
87
|
return 0 if (($year %4) || (($year % 400) && !($year % 100))); |
|
|
|
66
|
|
|
|
|
130
|
3
|
|
|
|
|
10
|
return 1; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub month { |
135
|
15
|
|
|
15
|
|
567
|
my $self = shift; |
136
|
15
|
100
|
|
|
|
72
|
return $$self{month} if exists $$self{month}; |
137
|
10
|
|
|
|
|
20
|
my $year = $self -> year; |
138
|
10
|
|
|
|
|
18
|
my $days = $$self{days_into_year}; |
139
|
10
|
|
|
|
|
14
|
my $MONTH_REF = \@MONTH_ENDS; |
140
|
10
|
100
|
|
|
|
24
|
$MONTH_REF = \@LEAP_ENDS if ($self->is_leap); |
141
|
10
|
|
|
|
|
19
|
my $month= 13 - (grep {$days <= $_} @$MONTH_REF); |
|
130
|
|
|
|
|
199
|
|
142
|
10
|
|
|
|
|
16
|
$$self{month} = $month; |
143
|
10
|
|
|
|
|
21
|
$$self{day} = $days-@$MONTH_REF[$month-1]; |
144
|
10
|
|
|
|
|
20
|
return $month; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
sub day { |
150
|
15
|
|
|
15
|
|
20
|
my $self = shift; |
151
|
15
|
50
|
|
|
|
62
|
return $$self{day} if exists $$self{day}; |
152
|
0
|
|
|
|
|
0
|
$self->month; # calculates day as a side-effect |
153
|
0
|
|
|
|
|
0
|
return $$self{day}; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub date { |
159
|
3
|
|
|
3
|
|
5
|
my $self = shift; |
160
|
3
|
|
|
|
|
8
|
return ($self->year, $self->month, $self->day); |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub date_string { |
166
|
12
|
|
|
12
|
|
60
|
my $self = shift; |
167
|
12
|
|
|
|
|
33
|
my $year = $self->year; |
168
|
12
|
|
|
|
|
38
|
my $month = $self->month; |
169
|
12
|
|
|
|
|
32
|
my $day = $self->day; |
170
|
12
|
|
|
|
|
65
|
return "$year $MONTHS_SHORT[$month] $day"; |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub initialize { |
177
|
6
|
|
|
6
|
|
12
|
my $self = shift; |
178
|
6
|
|
50
|
|
|
33
|
my $year = shift || return Date::Convert::initialize; |
179
|
6
|
|
33
|
|
|
28
|
my $month= shift || |
180
|
|
|
|
|
|
|
croak "Date::Convert::Gregorian::initialize needs more args"; |
181
|
6
|
|
33
|
|
|
19
|
my $day = shift || |
182
|
|
|
|
|
|
|
croak "Date::Convert::Gregorian::initialize needs more args"; |
183
|
6
|
50
|
|
|
|
24
|
warn "These routines don't work well for Gregorian before year 1" |
184
|
|
|
|
|
|
|
if $year<1; |
185
|
6
|
|
|
|
|
11
|
my $absol = $GREG_BEGINNING; |
186
|
6
|
|
|
|
|
31
|
$$self{'year'} = $year; |
187
|
6
|
|
|
|
|
48
|
$$self{'month'}= $month; |
188
|
6
|
|
|
|
|
13
|
$$self{'day'} = $day; |
189
|
6
|
|
|
|
|
25
|
my $is_leap = is_leap Date::Convert::Gregorian $year; |
190
|
6
|
|
|
|
|
8
|
$year --; #get years *before* this year. Makes math easier. :) |
191
|
|
|
|
|
|
|
# first, convert year into days. . . |
192
|
6
|
|
|
|
|
19
|
$absol += int($year/400)*$FOUR_CENTURIES; |
193
|
6
|
|
|
|
|
10
|
$year %= 400; |
194
|
6
|
|
|
|
|
12
|
$absol += int($year/100)*$CENTURY; |
195
|
6
|
|
|
|
|
9
|
$year %= 100; |
196
|
6
|
|
|
|
|
14
|
$absol += int($year/4)*$FOUR_YEARS; |
197
|
6
|
|
|
|
|
10
|
$year %= 4; |
198
|
6
|
|
|
|
|
9
|
$absol += $year*$NORMAL_YEAR; |
199
|
|
|
|
|
|
|
# now, month into days. |
200
|
6
|
50
|
33
|
|
|
41
|
croak "month number $month out of range" |
201
|
|
|
|
|
|
|
if $month < 1 || $month >12; |
202
|
6
|
|
|
|
|
14
|
my $MONTH_REF=\@MONTH_ENDS; |
203
|
6
|
100
|
|
|
|
19
|
$MONTH_REF=\@LEAP_ENDS if $is_leap; |
204
|
6
|
50
|
33
|
|
|
52
|
croak "day number $day out of range for month $month" |
205
|
|
|
|
|
|
|
if $day<1 || $day+$$MONTH_REF[$month-1]>$$MONTH_REF[$month]; |
206
|
6
|
|
|
|
|
15
|
$absol += $day+$$MONTH_REF[$month-1]-1; |
207
|
6
|
|
|
|
|
18
|
$$self{absol}=$absol; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
package Date::Convert::Hebrew; |
215
|
5
|
|
|
5
|
|
33
|
use Carp; |
|
5
|
|
|
|
|
23
|
|
|
5
|
|
|
|
|
7277
|
|
216
|
|
|
|
|
|
|
@ISA = qw ( Date::Convert ); |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
$HEBREW_BEGINNING = 347996; # 1 Tishri 1 |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# @MONTH = (29, 12, 793); |
221
|
|
|
|
|
|
|
@NORMAL_YEAR = (354, 8, 876); # &part_mult(12, @MONTH); |
222
|
|
|
|
|
|
|
@LEAP_YEAR = (383, 21, 589); # &part_mult(13, @MONTH); |
223
|
|
|
|
|
|
|
@CYCLE_YEARS = (6939, 16, 595); # &part_mult(235, @MONTH); |
224
|
|
|
|
|
|
|
@FIRST_MOLAD = ( 1, 5, 204); |
225
|
|
|
|
|
|
|
@LEAP_CYCLE = qw ( 3 6 8 11 14 17 0 ); |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
@MONTHS = ('Nissan', 'Iyyar', 'Sivan', 'Tammuz', 'Av', |
228
|
|
|
|
|
|
|
'Elul', 'Tishrei', 'Cheshvan', 'Kislev', 'Teves', |
229
|
|
|
|
|
|
|
'Shevat', 'Adar', 'Adar II' ); |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# In the Hebrew calendar, the year starts in the seventh month, there can |
232
|
|
|
|
|
|
|
# be a leap month, and there are two months with a variable number of days. |
233
|
|
|
|
|
|
|
# Rather than calculate do the actual math, let's set up lookup tables based |
234
|
|
|
|
|
|
|
# on year length. :) |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
%MONTH_START= |
237
|
|
|
|
|
|
|
('353' => [177, 207, 236, 266, 295, 325, 1, 31, 60, 89, 118, 148], |
238
|
|
|
|
|
|
|
'354' => [178, 208, 237, 267, 296, 326, 1, 31, 60, 90, 119, 149], |
239
|
|
|
|
|
|
|
'355' => [179, 209, 238, 268, 297, 327, 1, 31, 61, 91, 120, 150], |
240
|
|
|
|
|
|
|
'383' => [207, 237, 266, 296, 325, 355, 1, 31, 60, 89, 118, 148, 178], |
241
|
|
|
|
|
|
|
'384' => [208, 238, 267, 297, 326, 356, 1, 31, 60, 90, 119, 149, 179], |
242
|
|
|
|
|
|
|
'385' => [209, 239, 268, 298, 327, 357, 1, 31, 61, 91, 120, 150, 180]); |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
sub is_leap { |
245
|
972
|
|
|
972
|
|
1426
|
my $self = shift; |
246
|
972
|
|
|
|
|
948
|
my $year = shift; |
247
|
972
|
50
|
|
|
|
1472
|
$year=$self->year if ! defined $year; |
248
|
972
|
|
|
|
|
904
|
my $mod=$year % 19; |
249
|
972
|
|
|
|
|
1083
|
return scalar(grep {$_==$mod} @LEAP_CYCLE); |
|
6804
|
|
|
|
|
11195
|
|
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
sub initialize { |
254
|
6
|
|
|
6
|
|
10
|
my $self = shift; |
255
|
6
|
|
50
|
|
|
17
|
my $year = shift || return Date::Convert::initialize; |
256
|
6
|
|
33
|
|
|
17
|
my $month= shift || |
257
|
|
|
|
|
|
|
croak "Date::Convert::Hebrew::initialize needs more args"; |
258
|
6
|
|
33
|
|
|
19
|
my $day = shift || |
259
|
|
|
|
|
|
|
croak "Date::Convert::Hebrew::initialize needs more args"; |
260
|
6
|
50
|
|
|
|
20
|
warn "These routines don't work well for Hebrew before year 1" |
261
|
|
|
|
|
|
|
if $year<1; |
262
|
6
|
|
|
|
|
25
|
$$self{year}=$year; $$self{$month}=$month; $$self{day}=$day; |
|
6
|
|
|
|
|
17
|
|
|
6
|
|
|
|
|
64
|
|
263
|
6
|
|
|
|
|
19
|
my $rosh=$self->rosh; |
264
|
6
|
|
|
|
|
23
|
my $year_length=(rosh Date::Convert::Hebrew ($year+1))-$rosh; |
265
|
6
|
50
|
|
|
|
32
|
carp "Impossible year length" unless defined $MONTH_START{$year_length}; |
266
|
6
|
|
|
|
|
10
|
my $months_ref=$MONTH_START{$year_length}; |
267
|
6
|
|
|
|
|
15
|
my $days=$$months_ref[$month-1]+$day-1; |
268
|
6
|
|
|
|
|
15
|
$$self{days}=$days; |
269
|
6
|
|
|
|
|
9
|
my $absol=$rosh+$days-1; |
270
|
6
|
|
|
|
|
22
|
$$self{absol}=$absol; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
sub year { |
276
|
30
|
|
|
30
|
|
38
|
my $self = shift; |
277
|
30
|
100
|
|
|
|
177
|
return $$self{year} if exists $$self{year}; |
278
|
4
|
|
|
|
|
6
|
my $days=$$self{absol}; |
279
|
4
|
|
|
|
|
10
|
my $year=int($days/365)-3*365; # just an initial guess, but a good one. |
280
|
4
|
50
|
|
|
|
11
|
warn "Date::Convert::Hebrew isn't reliable before the beginning of\n". |
281
|
|
|
|
|
|
|
"\tthe Hebrew calendar" if $days < $HEBREW_BEGINNING; |
282
|
4
|
|
|
|
|
23
|
$year++ while rosh Date::Convert::Hebrew ($year+1)<=$days; |
283
|
4
|
|
|
|
|
19
|
$$self{year}=$year; |
284
|
4
|
|
|
|
|
19
|
$$self{days}=$days-(rosh Date::Convert::Hebrew $year)+1; |
285
|
4
|
|
|
|
|
27
|
return $year; |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
sub month { |
290
|
8
|
|
|
8
|
|
14
|
my $self = shift; |
291
|
8
|
50
|
|
|
|
42
|
return $$self{month} if exists $$self{month}; |
292
|
8
|
|
|
|
|
637
|
my $year_length= |
293
|
|
|
|
|
|
|
rosh Date::Convert::Hebrew ($self->year+1) - |
294
|
|
|
|
|
|
|
rosh Date::Convert::Hebrew $self->year; |
295
|
8
|
50
|
|
|
|
39
|
carp "Impossible year length" unless defined $MONTH_START{$year_length}; |
296
|
8
|
|
|
|
|
14
|
my $months_ref=$MONTH_START{$year_length}; |
297
|
8
|
|
|
|
|
43
|
my $days=$$self{days}; |
298
|
8
|
|
|
|
|
16
|
my ($n, $month)=(1); |
299
|
8
|
|
|
|
|
10
|
my $day=31; # 31 is too large. Good. :) |
300
|
8
|
100
|
100
|
|
|
17
|
grep {if ($days>=$_ && $days-$_<$day) |
|
101
|
|
|
|
|
302
|
|
|
9
|
|
|
|
|
16
|
|
301
|
9
|
|
|
|
|
13
|
{$day=$days-$_+1;$month=$n} |
302
|
101
|
|
|
|
|
121
|
$n++} @$months_ref; |
303
|
8
|
|
|
|
|
17
|
$$self{month}=$month; |
304
|
8
|
|
|
|
|
13
|
$$self{day}=$day; |
305
|
8
|
|
|
|
|
47
|
return $month; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
sub day { |
312
|
8
|
|
|
8
|
|
9
|
my $self = shift; |
313
|
8
|
50
|
|
|
|
77
|
return $$self{day} if exists $$self{day}; |
314
|
0
|
|
|
|
|
0
|
$self->month; # calculates day as a side-effect. |
315
|
0
|
|
|
|
|
0
|
return $$self{day}; |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub date { |
320
|
3
|
|
|
3
|
|
4
|
my $self = shift; |
321
|
3
|
|
|
|
|
9
|
return ($self->year, $self->month, $self->day); |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
sub date_string { |
326
|
5
|
|
|
5
|
|
46
|
my $self=shift; |
327
|
5
|
|
|
|
|
16
|
return $self->year." $MONTHS[$self->month-1] ".$self->day; |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
sub rosh { |
332
|
623
|
|
|
623
|
|
869
|
my $self = shift; |
333
|
623
|
|
66
|
|
|
1062
|
my $year = shift || $self->year; |
334
|
623
|
|
|
|
|
1005
|
my @molad= @FIRST_MOLAD; |
335
|
623
|
|
|
|
|
1375
|
@molad = &part_add(@molad, &part_mult(int(($year-1)/19),@CYCLE_YEARS)); |
336
|
623
|
|
|
|
|
928
|
my $offset=($year-1)%19; |
337
|
623
|
|
|
|
|
731
|
my $num_leaps=(grep {$_<=$offset} @LEAP_CYCLE) - 1; |
|
4361
|
|
|
|
|
5666
|
|
338
|
623
|
|
|
|
|
1086
|
@molad = &part_add(@molad, &part_mult($num_leaps, @LEAP_YEAR)); |
339
|
623
|
|
|
|
|
1300
|
@molad = &part_add(@molad, &part_mult($offset-$num_leaps, |
340
|
|
|
|
|
|
|
@NORMAL_YEAR)); |
341
|
623
|
|
|
|
|
813
|
my $day=shift @molad; |
342
|
623
|
|
|
|
|
639
|
my $hour=shift @molad; |
343
|
623
|
|
|
|
|
592
|
my $part= shift @molad; |
344
|
623
|
|
|
|
|
659
|
my $guess=$day%7; |
345
|
623
|
100
|
100
|
|
|
1672
|
if (($hour>=18) # molad zoken al tidrosh |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
346
|
|
|
|
|
|
|
or |
347
|
|
|
|
|
|
|
((is_leap Date::Convert::Hebrew $year) and # gatrad b'shanah |
348
|
|
|
|
|
|
|
($guess==2) and # p'shutah g'rosh |
349
|
|
|
|
|
|
|
(($hour>9)or($hour==9 && $part>=204))) |
350
|
|
|
|
|
|
|
or |
351
|
|
|
|
|
|
|
((is_leap Date::Convert::Hebrew $year-1) and # b'to takfat achar |
352
|
|
|
|
|
|
|
($guess==1) and # ha'ibur akor |
353
|
|
|
|
|
|
|
(($hour>15)or($hour==15&&$part>589)))){ # mi-lishorsh |
354
|
197
|
|
|
|
|
197
|
$guess++; |
355
|
197
|
|
|
|
|
186
|
$day++; |
356
|
|
|
|
|
|
|
} |
357
|
623
|
|
|
|
|
691
|
$guess%=7; |
358
|
623
|
100
|
|
|
|
656
|
if (scalar(grep {$guess==$_} (0, 3, 5))) { # lo ad"o rosh |
|
1869
|
|
|
|
|
2911
|
|
359
|
271
|
|
|
|
|
231
|
$guess++; |
360
|
271
|
|
|
|
|
242
|
$day++; |
361
|
|
|
|
|
|
|
} |
362
|
623
|
|
|
|
|
568
|
$guess%=7; |
363
|
623
|
|
|
|
|
2369
|
return ($day+1+$HEBREW_BEGINNING); |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
sub part_add { |
370
|
1869
|
|
|
1869
|
|
2241
|
my ($day1, $hour1, $part1)=(shift, shift, shift); |
371
|
1869
|
|
|
|
|
2130
|
my ($day2, $hour2, $part2)=(shift, shift, shift); |
372
|
1869
|
|
|
|
|
1900
|
my $part=$part1+$part2; |
373
|
1869
|
|
|
|
|
1694
|
my $hour=$hour1+$hour2; |
374
|
1869
|
|
|
|
|
1654
|
my $day =$day1 +$day2; |
375
|
1869
|
100
|
|
|
|
2977
|
if ($part>1080) { |
376
|
645
|
|
|
|
|
602
|
$part-=1080; |
377
|
645
|
|
|
|
|
614
|
$hour++; |
378
|
|
|
|
|
|
|
} |
379
|
1869
|
100
|
|
|
|
2829
|
if ($hour>24) { |
380
|
726
|
|
|
|
|
656
|
$hour-=24; |
381
|
726
|
|
|
|
|
657
|
$day++; |
382
|
|
|
|
|
|
|
} |
383
|
1869
|
|
|
|
|
4060
|
return ($day, $hour, $part); |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
sub part_mult { |
388
|
1869
|
|
|
1869
|
|
1753
|
my $scalar = shift; |
389
|
1869
|
|
|
|
|
2030
|
my $day= ((0+ shift) * $scalar); |
390
|
1869
|
|
|
|
|
1971
|
my $hour=((0+ shift) * $scalar); |
391
|
1869
|
|
|
|
|
1914
|
my $part=((0+ shift) * $scalar); |
392
|
1869
|
|
|
|
|
1672
|
my $tmp; |
393
|
1869
|
100
|
|
|
|
2987
|
if ($part>1080) { |
394
|
1617
|
|
|
|
|
1628
|
$tmp=int($part/1080); |
395
|
1617
|
|
|
|
|
1464
|
$part%=1080; |
396
|
1617
|
|
|
|
|
1642
|
$hour+=$tmp; |
397
|
|
|
|
|
|
|
} |
398
|
1869
|
100
|
|
|
|
2825
|
if ($hour>24) { |
399
|
1557
|
|
|
|
|
1533
|
$tmp=int($hour/24); |
400
|
1557
|
|
|
|
|
1411
|
$hour%=24; |
401
|
1557
|
|
|
|
|
1427
|
$day+=$tmp; |
402
|
|
|
|
|
|
|
} |
403
|
1869
|
|
|
|
|
3910
|
return($day, $hour, $part); |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
# Here's a quickie, based on the base class. |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
package Date::Convert::Absolute; |
410
|
5
|
|
|
5
|
|
59
|
use Date::Convert; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
698
|
|
411
|
|
|
|
|
|
|
@ISA = qw ( Date::Convert ); |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
sub initialize { |
414
|
2
|
|
|
2
|
|
10
|
return Date::Convert::initialize @_; |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
sub date { |
419
|
4
|
|
|
4
|
|
14
|
my $self=shift; |
420
|
4
|
|
|
|
|
32
|
return $$self{'absol'}; |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
sub date_string { |
424
|
2
|
|
|
2
|
|
15
|
my $self=shift; |
425
|
2
|
|
|
|
|
5
|
my $date=$self->date; # just a scalar |
426
|
2
|
|
|
|
|
6
|
return "$date"; |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
# Julian is kinda like Gregorian, but the leap year rule is easier. |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
package Date::Convert::Julian; |
434
|
|
|
|
|
|
|
|
435
|
5
|
|
|
5
|
|
32
|
use Carp; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
3181
|
|
436
|
|
|
|
|
|
|
@ISA = qw ( Date::Convert::Gregorian Date::Convert ); |
437
|
|
|
|
|
|
|
# we steal useful constants from Gregorian |
438
|
|
|
|
|
|
|
$JULIAN_BEGINNING=$Date::Convert::Gregorian::GREG_BEGINNING - 2; |
439
|
|
|
|
|
|
|
$NORMAL_YEAR= $Date::Convert::Gregorian::NORMAL_YEAR; |
440
|
|
|
|
|
|
|
$LEAP_YEAR= $Date::Convert::Gregorian::LEAP_YEAR; |
441
|
|
|
|
|
|
|
$FOUR_YEARS= $Date::Convert::Gregorian::FOUR_YEARS; |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
@MONTH_ENDS = @Date::Convert::Gregorian::MONTH_ENDS; |
444
|
|
|
|
|
|
|
@LEAP_ENDS = @Date::Convert::Gregorian::LEAP_ENDS; |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
sub initialize { |
447
|
3
|
|
33
|
3
|
|
16
|
my $self=shift || |
448
|
|
|
|
|
|
|
croak "Date::Convert::Julian::initialize needs more args"; |
449
|
3
|
|
50
|
|
|
7
|
my $year=shift || return Date::Convert::initialize; |
450
|
3
|
|
33
|
|
|
82
|
my $month=shift || |
451
|
|
|
|
|
|
|
croak "Date::Convert::Julian::initialize needs more args"; |
452
|
3
|
|
33
|
|
|
8
|
my $day=shift || |
453
|
|
|
|
|
|
|
croak "Date::Convert::Julian::initialize needs more args"; |
454
|
|
|
|
|
|
|
|
455
|
3
|
50
|
|
|
|
12
|
warn "These routines don't work well for Julian before year 1" |
456
|
|
|
|
|
|
|
if $year<1; |
457
|
3
|
|
|
|
|
5
|
my $absol = $JULIAN_BEGINNING; |
458
|
3
|
|
|
|
|
5
|
$$self{'year'} = $year; |
459
|
3
|
|
|
|
|
6
|
$$self{'month'}= $month; |
460
|
3
|
|
|
|
|
4
|
$$self{'day'} = $day; |
461
|
3
|
|
|
|
|
8
|
my $is_leap = is_leap Date::Convert::Gregorian $year; |
462
|
3
|
|
|
|
|
5
|
$year --; #get years *before* this year. Makes math easier. :) |
463
|
|
|
|
|
|
|
# first, convert year into days. . . |
464
|
3
|
|
|
|
|
6
|
$absol += int($year/4)*$FOUR_YEARS; |
465
|
3
|
|
|
|
|
4
|
$year %= 4; |
466
|
3
|
|
|
|
|
4
|
$absol += $year*$NORMAL_YEAR; |
467
|
|
|
|
|
|
|
# now, month into days. |
468
|
3
|
50
|
33
|
|
|
15
|
croak "month number $month out of range" |
469
|
|
|
|
|
|
|
if $month < 1 || $month >12; |
470
|
3
|
|
|
|
|
5
|
my $MONTH_REF=\@MONTH_ENDS; |
471
|
3
|
50
|
|
|
|
7
|
$MONTH_REF=\@LEAP_ENDS if $is_leap; |
472
|
3
|
50
|
33
|
|
|
18
|
croak "day number $day out of range for month $month" |
473
|
|
|
|
|
|
|
if $day<1 || $day+$$MONTH_REF[$month-1]>$$MONTH_REF[$month]; |
474
|
3
|
|
|
|
|
5
|
$absol += $day+$$MONTH_REF[$month-1]-1; |
475
|
3
|
|
|
|
|
6
|
$$self{absol}=$absol; |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
sub year { |
480
|
7
|
|
|
7
|
|
9
|
my $self = shift; |
481
|
7
|
100
|
|
|
|
31
|
return $$self{year} if exists $$self{year}; |
482
|
2
|
|
|
|
|
3
|
my ($days, $year); |
483
|
|
|
|
|
|
|
# To avoid fenceposts, year and days are initially *before* today. |
484
|
|
|
|
|
|
|
# the next code is stolen directly form the ::Gregorian code. Good thing |
485
|
|
|
|
|
|
|
# I'm the one who wrote it. . . |
486
|
2
|
|
|
|
|
15
|
$days=$$self{absol}-$JULIAN_BEGINNING; |
487
|
2
|
|
|
|
|
7
|
$year = int ($days / $FOUR_YEARS) * 4; |
488
|
2
|
|
|
|
|
4
|
$days %= $FOUR_YEARS; |
489
|
2
|
50
|
|
|
|
6
|
if (($days+1) % $FOUR_YEARS) { # Not on a four-year boundary. Good! |
490
|
2
|
|
|
|
|
4
|
$year += int ($days / $NORMAL_YEAR); # fence post from year 1 |
491
|
2
|
|
|
|
|
3
|
$days %= $NORMAL_YEAR; |
492
|
2
|
|
|
|
|
3
|
$days += 1; # today |
493
|
2
|
|
|
|
|
2
|
$year += 1; |
494
|
|
|
|
|
|
|
} else { |
495
|
0
|
|
|
|
|
0
|
$year += int ($days / $NORMAL_YEAR + 1) - 1; |
496
|
0
|
|
|
|
|
0
|
$days = $LEAP_YEAR; |
497
|
|
|
|
|
|
|
} |
498
|
2
|
|
|
|
|
4
|
$$self{year}=$year; |
499
|
2
|
|
|
|
|
4
|
$$self{days_into_year}=$days; |
500
|
2
|
|
|
|
|
9
|
return $year; |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
sub is_leap { |
506
|
2
|
|
|
2
|
|
3
|
my $self = shift; |
507
|
2
|
|
33
|
|
|
8
|
my $year = shift || $self->year; # so is_leap can be static or method |
508
|
2
|
100
|
|
|
|
7
|
return 0 if ($year %4); |
509
|
1
|
|
|
|
|
4
|
return 1; |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
# OK, we're done. Everything else just gets inherited from Gregorian. |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
1; |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
__END__ |