לפני כשנה מאיר דודאי ציטט קוד לפונקציה שמחשבת את התאריך של פסח, וגם שאל בקריצה אם טרם יצרתי פונקציה כזו בעצמי. למען האמת יש לי סקריפט פשוט שמחשב את התאריך המדוייק של פסח מיציאת מצרים ועד לביאת המשיח:
וברצינות- הפונקציה הנ"ל (ניתן למצוא אותה כאן בצירוף פונקציות נוספות) מתבססת על נוסחה שפיתח גאוס – מתמטיקאי גרמני שהיה אולי גדול המתמטיקאים מאז ומעולם, ואם לא- אז בוודאי בחמישיה הפותחת; ואשר נועדה במקורה לחשב את מועדו של ה-Easter – חג הפסחא הנוצרי שמועדו מתבסס על הירח ומשמר במידת מה את מקורו היהודי וחל ביום ראשון שלאחר מילוא הירח שלאחר יום השיוויון (כלומר- גם חג האביב וגם מתייחס לאמצע החודש העברי), ובשינויים מסויימים הוא הותאם לחישוב חג הפסח היהודי.
מי שרוצה לעקוב אחר שיטת החישוב של גאוס יכול להציץ כאן, ומי שרוצה בעברית-
מתוך "המליץ"- כתב עת ציוני עברי שיצא ברוסיה במחצית השניה של המאה ה-19 (מי שרוצה לעיין בהמשך המאמר- כאן בעמוד 3).
בעזרת הפונקציה הנ"ל ניתן לחשב די בקלות את הלוח העברי מבלי להסתבך עם מועדי המולד, הדחיות, העיבורים וכו': מוצאים את מועדי חג הפסח, 163 יום לאחר פסח חל ראש השנה, ולפי ההפרש בין ראש שנה אחד לזה שאחריו אפשר לראות אם השנה מעוברת או פשוטה, אם חשוון מלא או לא, ואם כסלו חסר או לא.
דבר ראשון- ניצור את הפונקציה לחישוב פסח:
CREATE function dbo.Passover(@Yr int)
returns datetime
AS
BEGIN
Declare @HYear int, @Matonic int, @LeapException int, @Leap int, @DOW int, @Century int
Declare @fDay float(20), @fFracDay float(20)
Declare @Mo int, @Day int
Set @HYear=@Yr+3760
Set @Matonic=(12*@HYear+17) % 19
Set @Leap=@HYear % 4
Set @fDay=32+4343/98496.+@Matonic+@Matonic*(272953/492480.)+@Leap/4.
Set @fDay=@fDay-@HYear*(313/98496.)
Set @fFracDay=@fDay-FLOOR(@fDay)
Set @DOW=cast (3*@HYear+5*@Leap+FLOOR(@fDay)+5 as int) % 7
IF @DOW=2 or @DOW=4 or @DOW=6
set @fDay=@fDay+1
IF @DOW=1 and @Matonic>6 and @fFracDay>=1367/2160.
set @fDay=@fDay+2
IF @DOW=0 and @Matonic>11 and @fFracDay>=23269/25920.
set @fDay=@fDay+1
Set @Century=FLOOR(@Yr/100.)
Set @LeapException=FLOOR((3*@Century-5)/4.)
IF @Yr>1582
set @fDay=@fDay+@LeapException
Set @Day=FLOOR(@fDay)
Set @Mo=3
IF @Day>153
Begin
set @Mo=8
set @Day=@Day-153
End
IF @Day>122
Begin
set @Mo=7
set @Day=@Day-122
End
IF @Day>92
Begin
set @Mo=6
set @Day=@Day-92
End
IF @Day>61
Begin
set @Mo=5
set @Day=@Day-61
End
IF @Day>31
Begin
set @Mo=4
set @Day=@Day-31
End
return cast(str(@Mo)+'/'+str(@Day)+'/'+str(@Yr) as datetime)
/* Based on mathematical algorithms first devised by the German mathematician Carl Friedrich Gauss (1777-1855). I have used the date of Passover to determine most of the other Jewish holidays.*/
END
GO
וכעת- נחשב קודם כל את השנים, את ראשי השנה של כל אחד (הקודם והבא), ואת ההפרש בינהם בימים:
Declare @MiShana Int,
@AdShana Int;
Select @MiShana=5661,
@AdShana=6000;
With Shanim As
(Select @MiShana ShanaI,
@MiShana-3761 ShanaL,
Cast(Null As DateTime) RoshHashanaHakodem,
dbo.Passover(@MiShana-3761)+163 RoshHashanaHaba,
Cast(Null As Int) Yamim
Union All
Select ShanaI,
ShanaL,
RoshHashanaHakodem,
RoshHashanaHaba,
DateDiff(Day,RoshHashanaHakodem,RoshHashanaHaba) Yamim
From (Select ShanaI+1 ShanaI,
ShanaL+1 ShanaL,
RoshHashanaHaba RoshHashanaHakodem,
dbo.Passover(ShanaI-3760)+163 RoshHashanaHaba
From Shanim
Where ShanaI<@AdShana) T)
Select ShanaI-1 ShanaI,
ShanaL-1 ShanaL,
RoshHashanaHakodem,
RoshHashanaHaba,
Yamim
From Shanim
Where Yamim Is Not Null
option (MaxRecursion 0);
Go
ולבסוף נוכל להוסיף את החודשים והימים כמו בפוסט הקודם:
Declare @MiShana Int,
@AdShana Int;
Select @MiShana=5661,
@AdShana=6000;
With Shanim As
(Select @MiShana ShanaI,
@MiShana-3761 ShanaL,
Cast(Null As DateTime) RoshHashanaHakodem,
dbo.Passover(@MiShana-3761)+163 RoshHashanaHaba,
Cast(Null As Int) Yamim
Union All
Select ShanaI,
ShanaL,
RoshHashanaHakodem,
RoshHashanaHaba,
DateDiff(Day,RoshHashanaHakodem,RoshHashanaHaba) Yamim
From (Select ShanaI+1 ShanaI,
ShanaL+1 ShanaL,
RoshHashanaHaba RoshHashanaHakodem,
dbo.Passover(ShanaI-3760)+163 RoshHashanaHaba
From Shanim
Where ShanaI<@AdShana) T),
Hodashim As
(Select 1 ID, 'תשרי' Hodesh,30 Yamim, Null Sug Union All
Select 2 ID, 'חשוון' Hodesh,29 Yamim, Null Sug Union All
Select 2 ID, 'חשוון' Hodesh,30 Yamim, 'מלא' Sug Union All
Select 3 ID, 'כסלו' Hodesh,30 Yamim, Null Sug Union All
Select 3 ID, 'כסלו' Hodesh,29 Yamim, 'חסר' Sug Union All
Select 4 ID, 'טבת' Hodesh,29 Yamim, Null Sug Union All
Select 5 ID, 'שבט' Hodesh,30 Yamim, Null Sug Union All
Select 6 ID, 'אדר' Hodesh,29 Yamim, Null Sug Union All
Select 6 ID, 'אדר א' Hodesh,30 Yamim, Null Sug Union All
Select 6 ID, 'אדר ב' Hodesh,29 Yamim, Null Sug Union All
Select 7 ID, 'ניסן' Hodesh,30 Yamim, Null Sug Union All
Select 8 ID, 'אייר' Hodesh,29 Yamim, Null Sug Union All
Select 9 ID, 'סיוון' Hodesh,30 Yamim, Null Sug Union All
Select 10 ID, 'תמוז' Hodesh,29 Yamim, Null Sug Union All
Select 11 ID, 'אב' Hodesh,30 Yamim, Null Sug Union All
Select 12 ID, 'אלול' Hodesh,29 Yamim, Null Sug),
Yamim As
(Select 1 Yom
Union All
Select Yom+1
From Yamim
Where Yom<30)
Select S.ShanaI-1 ShanaI,
H.Hodesh,
H.Sug,
Y.Yom,
DateAdd(Day,Row_Number() Over(Partition By S.ShanaI Order By H.ID,H.Hodesh,Y.Yom)-1,S.RoshHashanaHakodem) TaarihL
From Shanim S
Inner Join Hodashim H
On ((S.Yamim<=355 And H.Hodesh Not In ('אדר א','אדר ב'))
Or (S.Yamim>=383 And H.Hodesh Not In ('אדר')))
And ((S.Yamim%10=3
And (H.Hodesh<>'חשוון' Or H.Sug Is Null)
And (H.Hodesh<>'כסלו' Or H.Sug='חסר'))
Or (S.Yamim%10=4
And H.Sug Is Null)
Or (S.Yamim%10=5
And (H.Hodesh<>'חשוון' Or H.Sug='מלא')
And (H.Hodesh<>'כסלו' Or H.Sug Is Null)))
Inner Join Yamim Y
On H.Yamim>=Y.Yom
Order By S.ShanaI,
H.ID,
H.Hodesh,
Y.Yom
option (MaxRecursion 0);
Go