line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package DateTime::Event::Jewish::Parshah; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
DateTime::Event::Jewish::Parshah - Calculate leyning for next |
6
|
|
|
|
|
|
|
shabbat |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 SYNOPSIS |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use DateTime::Event::Jewish::Parshah qw(parshah); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
my $parshah = parshah(DateTime->today, $israel); |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 DESCRIPTION |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
Returns either a parshah name or a yom tov name for the Shabbat |
17
|
|
|
|
|
|
|
after the date supplied. The optional I flag specifies |
18
|
|
|
|
|
|
|
whether to calculate the leyning for Israel or for the diaspora. |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=cut |
22
|
|
|
|
|
|
|
|
23
|
6
|
|
|
6
|
|
695430
|
use strict; |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
211
|
|
24
|
6
|
|
|
6
|
|
25
|
use warnings; |
|
6
|
|
|
|
|
8
|
|
|
6
|
|
|
|
|
133
|
|
25
|
6
|
|
|
6
|
|
21
|
use DateTime; |
|
6
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
110
|
|
26
|
6
|
|
|
6
|
|
27
|
use DateTime::Duration; |
|
6
|
|
|
|
|
7
|
|
|
6
|
|
|
|
|
101
|
|
27
|
6
|
|
|
6
|
|
3587
|
use DateTime::Calendar::Hebrew; |
|
6
|
|
|
|
|
22592
|
|
|
6
|
|
|
|
|
187
|
|
28
|
6
|
|
|
6
|
|
2353
|
use DateTime::Event::Jewish::Yomtov qw(@festival); |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
806
|
|
29
|
6
|
|
|
6
|
|
2032
|
use DateTime::Event::Jewish::Sedrah qw(@sedrah); |
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
615
|
|
30
|
6
|
|
|
6
|
|
29
|
use base qw(Exporter); |
|
6
|
|
|
|
|
7
|
|
|
6
|
|
|
|
|
324
|
|
31
|
6
|
|
|
6
|
|
24
|
use vars qw(@EXPORT_OK); |
|
6
|
|
|
|
|
7
|
|
|
6
|
|
|
|
|
4403
|
|
32
|
|
|
|
|
|
|
@EXPORT_OK = qw(nextShabbat parshah); |
33
|
|
|
|
|
|
|
our $VERSION = '0.01'; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
our %YomTovMap; |
36
|
|
|
|
|
|
|
our %IsraelYomTovMap; |
37
|
|
|
|
|
|
|
our %YomTovYear; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=head3 _initYomTov($year) |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
Internal function that initialises the yom tov table for the |
42
|
|
|
|
|
|
|
year in question. |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=cut |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub _initYomTov { |
47
|
1746
|
|
|
1746
|
|
2052
|
my $year = shift; |
48
|
1746
|
100
|
|
|
|
4574
|
return if $YomTovYear{$year}; |
49
|
227
|
|
|
|
|
853
|
my $f = DateTime::Calendar::Hebrew->today; |
50
|
227
|
|
|
|
|
245697
|
foreach my $yt (@festival) |
51
|
|
|
|
|
|
|
{ |
52
|
4994
|
|
|
|
|
6919
|
my ($name, $day, $month, $diaspora) = @$yt; |
53
|
4994
|
|
|
|
|
11840
|
$f->set(year=>$year, month=>$month, day=>$day); |
54
|
4994
|
|
|
|
|
589977
|
my $fDays = $f->{rd_days}; |
55
|
4994
|
|
|
|
|
10795
|
$YomTovMap{$fDays} = $name; |
56
|
4994
|
100
|
|
|
|
13378
|
$IsraelYomTovMap{$fDays} = $name unless $diaspora; |
57
|
|
|
|
|
|
|
} |
58
|
227
|
|
|
|
|
1030
|
$YomTovYear{$year} = 1; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# (C) Raphael Mankin 2009 |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# The algorithm for calculating the weekly parshah is taken |
66
|
|
|
|
|
|
|
# from http://individual.utoronto.ca/kalendis/hebrew/parshah.htm |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=head3 nextShabbat($date) |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
Returns the next Shabbat which is strictly after $date. The |
71
|
|
|
|
|
|
|
returned object is a Hewbrew date. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
$date is some sort of DateTime object; it does not matter which. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=cut |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub nextShabbat { |
78
|
1164
|
|
|
1164
|
1
|
5741
|
my $date = DateTime->from_object(object=>shift)->add(days=>1); |
79
|
1164
|
|
|
|
|
941371
|
while ($date->day_of_week != 6) { |
80
|
2329
|
|
|
|
|
630644
|
$date->add(days=>1); |
81
|
|
|
|
|
|
|
} |
82
|
1164
|
|
|
|
|
353636
|
return DateTime::Calendar::Hebrew->from_object(object=>$date); |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=head3 parshah($date ,[$israel]) |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
Returns the parshah name or a yomtov name for the Shabbat |
88
|
|
|
|
|
|
|
strictly after $date. |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
$date is some sort of DateTime object; it does not matter which. |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
$israel is an optional flag to indicate that we should use the |
93
|
|
|
|
|
|
|
logic for Israel rather than the Diaspora. |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
See http://individual.utoronto.ca/kalendis/hebrew/parshah.htm for |
96
|
|
|
|
|
|
|
the logic of this code. |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=cut |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub parshah { |
101
|
582
|
|
|
582
|
1
|
1647527
|
my $today = shift; |
102
|
582
|
|
100
|
|
|
2595
|
my $israel = shift || 0; |
103
|
|
|
|
|
|
|
|
104
|
582
|
|
|
|
|
1518
|
my $targetShabbat = nextShabbat($today); |
105
|
582
|
|
|
|
|
631335
|
my $thisYear = $targetShabbat->year(); |
106
|
582
|
|
|
|
|
3555
|
_initYomTov($thisYear-1); |
107
|
582
|
|
|
|
|
1017
|
_initYomTov($thisYear); |
108
|
582
|
|
|
|
|
1075
|
_initYomTov($thisYear+1); |
109
|
582
|
100
|
|
|
|
1518
|
if ($israel) { |
110
|
291
|
50
|
|
|
|
1099
|
if (exists $IsraelYomTovMap{$targetShabbat->{rd_days}}) { |
111
|
0
|
|
|
|
|
0
|
return $IsraelYomTovMap{$targetShabbat->{rd_days}}; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
} else { |
114
|
291
|
50
|
|
|
|
1321
|
if (exists $YomTovMap{$targetShabbat->{rd_days}}) { |
115
|
0
|
|
|
|
|
0
|
return $YomTovMap{$targetShabbat->{rd_days}}; |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
} |
118
|
582
|
|
|
|
|
1800
|
my $thisMonth = $targetShabbat->month(); |
119
|
582
|
|
|
|
|
3046
|
my $thisDay = $targetShabbat->day(); |
120
|
|
|
|
|
|
|
# Get the date of last Simchat Torah, bearing in mind that |
121
|
|
|
|
|
|
|
# the year begins in Nissan. |
122
|
582
|
50
|
33
|
|
|
4961
|
my $simchatTorah = |
123
|
|
|
|
|
|
|
DateTime::Calendar::Hebrew->new(month=>7, |
124
|
|
|
|
|
|
|
day=>23-$israel, |
125
|
|
|
|
|
|
|
year=>($thisMonth==7 && $thisDay<23-$israel )? $thisYear-1: $thisYear); |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# The next few dates only matter if we are in the right part of the year. |
128
|
|
|
|
|
|
|
# Otherwise, the dates are not used and it is of no |
129
|
|
|
|
|
|
|
# consequence which year we calculate. The calculation is |
130
|
|
|
|
|
|
|
# relative to 'workingShabbat', not relative to |
131
|
|
|
|
|
|
|
# 'targetShabbat'. |
132
|
|
|
|
|
|
|
# |
133
|
|
|
|
|
|
|
# The date of Pesach |
134
|
582
|
50
|
|
|
|
51021
|
my $pesach = DateTime::Calendar::Hebrew->new(month=>1, day=>15, |
135
|
|
|
|
|
|
|
year=>($thisMonth==7 ? $thisYear-1: $thisYear)); |
136
|
|
|
|
|
|
|
# The date of 9 Av |
137
|
582
|
50
|
|
|
|
100057
|
my $tishaBAv = DateTime::Calendar::Hebrew->new(month=>5, day=>9, |
138
|
|
|
|
|
|
|
year=>($thisMonth==7 ? $thisYear-1: $thisYear) ); |
139
|
|
|
|
|
|
|
# The date of RoshHashanah |
140
|
582
|
50
|
|
|
|
110249
|
my $RoshHashanah= DateTime::Calendar::Hebrew->new(month=>7, day=>1, |
141
|
|
|
|
|
|
|
year=>($thisMonth==7 ? $thisYear : $thisYear+1)); |
142
|
582
|
|
|
|
|
43916
|
my $workingShabbat = |
143
|
|
|
|
|
|
|
nextShabbat($simchatTorah)->subtract_duration(DateTime::Duration->new(days=>7)); |
144
|
582
|
|
|
|
|
580061
|
my $startDay = $workingShabbat->{rd_days}; |
145
|
582
|
|
|
|
|
1225
|
my $endDay = $targetShabbat->{rd_days}; |
146
|
582
|
|
|
|
|
1287
|
my $parshahNumber = int(($endDay-$startDay)/7); |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
#print "Next Shabbat: " , $targetShabbat->ymd, "\n"; |
150
|
|
|
|
|
|
|
|
151
|
582
|
50
|
|
|
|
1555
|
if ($parshahNumber < 22) { # No special Shabbattot |
152
|
0
|
|
|
|
|
0
|
return $sedrah[$parshahNumber]; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# From week 22 onwards there are special cases |
156
|
582
|
|
|
|
|
744
|
$parshahNumber = 21; |
157
|
582
|
|
|
|
|
2176
|
$workingShabbat->add_duration(DateTime::Duration->new(days=>21*7)); |
158
|
582
|
|
|
|
|
465483
|
my $leapYear = DateTime::Calendar::Hebrew::_leap_year($simchatTorah->year); |
159
|
582
|
|
|
|
|
4938
|
my $wDayPesach = $pesach->day_of_week; |
160
|
582
|
|
|
|
|
3564
|
my $combined = 0; |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
#print "leap year: $leapYear\tPesach $wDayPesach\n"; |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
LOOP: |
166
|
582
|
|
|
|
|
2614
|
while ($workingShabbat < $targetShabbat) { |
167
|
3398
|
|
|
|
|
82998
|
$workingShabbat->add_duration(DateTime::Duration->new(days=> 7)); |
168
|
|
|
|
|
|
|
# If the Shabbat in question is yom tov or chol hamoed |
169
|
|
|
|
|
|
|
# it does not count towards the parshah count. |
170
|
3398
|
100
|
100
|
|
|
2951796
|
if ($israel && exists $IsraelYomTovMap{$workingShabbat->{rd_days}}) {next;} |
|
60
|
|
|
|
|
188
|
|
171
|
3338
|
100
|
100
|
|
|
13051
|
if (!$israel && exists $YomTovMap{$workingShabbat->{rd_days}}) {next;} |
|
92
|
|
|
|
|
280
|
|
172
|
3246
|
|
|
|
|
4395
|
my $workingDays = $workingShabbat->{rd_days}; |
173
|
3246
|
100
|
|
|
|
5139
|
$parshahNumber++ if ($combined); |
174
|
3246
|
|
|
|
|
3037
|
$combined = 0; |
175
|
3246
|
|
|
|
|
2597
|
$parshahNumber++; |
176
|
3246
|
100
|
|
|
|
7755
|
if($parshahNumber==22) { #Vayakhel |
177
|
|
|
|
|
|
|
# Combine Vayakhel/Pekudei if there are fewer than 4 |
178
|
|
|
|
|
|
|
# Shabbatot *before* the first day of Pesach |
179
|
582
|
|
|
|
|
871
|
my $pesachDays = $pesach->{rd_days}; |
180
|
582
|
100
|
|
|
|
1521
|
$combined =1 if ($pesachDays - $workingDays < 22); |
181
|
582
|
|
|
|
|
2422
|
next LOOP; |
182
|
|
|
|
|
|
|
} |
183
|
2664
|
100
|
100
|
|
|
8495
|
if($parshahNumber ==27 || # Tazria |
184
|
|
|
|
|
|
|
$parshahNumber ==29) { # Acharei Mot |
185
|
240
|
100
|
|
|
|
484
|
$combined = 1 if (!$leapYear); |
186
|
240
|
|
|
|
|
806
|
next LOOP; |
187
|
|
|
|
|
|
|
} |
188
|
2424
|
100
|
|
|
|
3689
|
if($parshahNumber == 32) { # Behar |
189
|
120
|
100
|
|
|
|
304
|
if ($israel) { |
190
|
|
|
|
|
|
|
# In Israel we need to change the condition to |
191
|
|
|
|
|
|
|
# not a leap year and Pesach not on Shabbat. |
192
|
|
|
|
|
|
|
# Ths can only happen in a 354 day year that |
193
|
|
|
|
|
|
|
# started on a thursday. |
194
|
60
|
100
|
100
|
|
|
242
|
$combined = 1 if (!$leapYear && $wDayPesach != 7); |
195
|
|
|
|
|
|
|
} else { |
196
|
|
|
|
|
|
|
# if Pesach falls on Shabbat then Pesach8 is |
197
|
|
|
|
|
|
|
# also on Shabbat. This is not relevant in |
198
|
|
|
|
|
|
|
# Israel. |
199
|
60
|
100
|
|
|
|
146
|
$combined = 1 if (!$leapYear); |
200
|
|
|
|
|
|
|
} |
201
|
120
|
|
|
|
|
452
|
next LOOP; |
202
|
|
|
|
|
|
|
} |
203
|
2304
|
100
|
|
|
|
3521
|
if($parshahNumber == 39) { # Chukat |
204
|
|
|
|
|
|
|
# If Pesach falls on Thursday then Shavuot2 is Shabbat |
205
|
|
|
|
|
|
|
# In Israel never combine because Shavuot can never be Shabbat |
206
|
120
|
100
|
100
|
|
|
506
|
$combined = 1 if( $wDayPesach == 5 && !$israel); |
207
|
120
|
|
|
|
|
541
|
next LOOP; |
208
|
|
|
|
|
|
|
} |
209
|
2184
|
100
|
|
|
|
3363
|
if($parshahNumber == 42) { # Mattot |
210
|
|
|
|
|
|
|
# Devraim is always read on the Shabbat before |
211
|
|
|
|
|
|
|
# Tisha B'Av. If 9 Av falls on Shabbat, then |
212
|
|
|
|
|
|
|
# we read Devarim actually on 9 Av. |
213
|
120
|
|
|
|
|
241
|
my $avDays = $tishaBAv->{rd_days}; |
214
|
120
|
100
|
|
|
|
327
|
$combined = 1 if (($avDays - $workingDays) < 14); |
215
|
120
|
|
|
|
|
478
|
next LOOP; |
216
|
|
|
|
|
|
|
} |
217
|
2064
|
100
|
|
|
|
7510
|
if(51 == $parshahNumber ) { # Nitzavim |
218
|
|
|
|
|
|
|
# Is there a Shabbat between YC and Succot? |
219
|
60
|
|
|
|
|
122
|
my $roshDays = $RoshHashanah->{rd_days}; |
220
|
60
|
100
|
|
|
|
159
|
$combined = 1 |
221
|
|
|
|
|
|
|
if (($roshDays - $workingDays) > 3); |
222
|
60
|
|
|
|
|
278
|
next LOOP; |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
582
|
|
|
|
|
15341
|
my $parshah = $sedrah[$parshahNumber]; |
227
|
582
|
100
|
|
|
|
1217
|
$parshah .= "/" . $sedrah[$parshahNumber+1] if ($combined); |
228
|
|
|
|
|
|
|
|
229
|
582
|
|
|
|
|
6637
|
return $parshah; |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=head1 BUGS |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
DateTime::Calendar::Hebrew is not a sub-class of DateTime. It |
236
|
|
|
|
|
|
|
does not implement the all functionality of DateTime, and where it |
237
|
|
|
|
|
|
|
does implement it, it uses different names and interfaces. |
238
|
|
|
|
|
|
|
In particular, none of the arithmetic works. |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=cut |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
1; |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=head1 AUTHOR |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
Raphael Mankin, C<< >> |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=head1 BUGS |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through |
251
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll |
252
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=head1 SUPPORT |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
perldoc DateTime::Event::Jewish |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
You can also look for information at: |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=over 4 |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
L |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
L |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=item * CPAN Ratings |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
L |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=item * Search CPAN |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
L |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=back |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
Copyright 2010 Raphael Mankin. |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
295
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published |
296
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License. |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
See http://dev.perl.org/licenses/ for more information. |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
=cut |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
1; # End of DateTime::Event::Parshah |