הלוח העברי בעזרת TSQL (2)

31/03/2011

4 תגובות

לפני כשנה מאיר דודאי ציטט קוד לפונקציה שמחשבת את התאריך של פסח, וגם שאל בקריצה אם טרם יצרתי פונקציה כזו בעצמי. למען האמת יש לי סקריפט פשוט שמחשב את התאריך המדוייק של פסח מיציאת מצרים ועד לביאת המשיח:

Select 'ט"ו בניסן' [פסח];

clip_image002

וברצינות- הפונקציה הנ"ל (ניתן למצוא אותה כאן בצירוף פונקציות נוספות) מתבססת על נוסחה שפיתח גאוס – מתמטיקאי גרמני שהיה אולי גדול המתמטיקאים מאז ומעולם, ואם לא- אז בוודאי בחמישיה הפותחת; ואשר נועדה במקורה לחשב את מועדו של ה-Easter – חג הפסחא הנוצרי שמועדו מתבסס על הירח ומשמר במידת מה את מקורו היהודי וחל ביום ראשון שלאחר מילוא הירח שלאחר יום השיוויון (כלומר- גם חג האביב וגם מתייחס לאמצע החודש העברי), ובשינויים מסויימים הוא הותאם לחישוב חג הפסח היהודי.

מי שרוצה לעקוב אחר שיטת החישוב של גאוס יכול להציץ כאן, ומי שרוצה בעברית-

clip_image004מתוך "המליץ"- כתב עת ציוני עברי שיצא ברוסיה במחצית השניה של המאה ה-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

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

4 תגובות

  1. שי גולדברג01/04/2011 ב 13:04

    גרי, שלום.
    כאחד שמתעניין רבות בלוח העברי וגם ב-TSQL שמחתי לקרוא את הפוסט שלך על הלוח העברי.
    מצד שני, כבר הוכח שחישובי הלוח העברי ע"פ גאוס אינם מדוייקים ולכן לא בהכרח ניתן להסתמך עליהם.
    אם אתה מעוניין בפרטים נוספים על חישובים יותר מדוייקים אשמח לתת לך.
    אין לי מייל שלך, אז תשאיר כאן תשובה ואני אדגום את הפוסט הזה…
    בברכה,
    ש"י גולדברג.

    הגב
  2. גרי רשף01/04/2011 ב 16:12

    אפתח בכך שבפוסט הקודם שלי חישבתי את מולדי הירח ואת תאריכי ראש השנה בהתאם לחישוב המקובל בהלכה (וגם צירפתי דברי רקע והסבר מלא):
    http://gerireshef.wordpress.com/2011/03/29/%d7%94%d7%9c%d7%95%d7%97-%d7%94%d7%a2%d7%91%d7%a8%d7%99-%d7%91%d7%a2%d7%96%d7%a8%d7%aa-tsql/

    כאן עשיתי קפנדריא בזרת הפונקציה נ"ל (שאינה שלי!), וגם אני התפלאתי לגלות שהיא עובדת בלי כל הדקויות של שעת המולד המחושב.
    יש לך מקור המסביר למה ומתי היא לא תעבוד?

    אשתדל בעתיד הקרוב ליצור חישוב מדוייק שאינו תלוי לא בגאוס ולא בתאריך הלועזי, אלא עומד באופן עצמאי.

    המייל שלי: GeriReshef@GMail.com.

    הגב
  3. דני05/04/2011 ב 15:39

    תודה רבה על המאמר, אני חולה על האתר שלך!

    הגב
  4. גרי רשף08/04/2011 ב 21:17

    תודה דני- מחמם את הלב לגלות שיש מי שפוקדים אותו (חוץ ממני).

    הגב