ANEW --CALENCAL-- DECIMAL \ Wil Baden 2001-01-15
\ Calendrical Calculations - Arithmetical
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
\ * *
\ * Gregorian, Julian, ISO, Islamic, and Hebrew Calendars *
\ * *
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
\ Forth versions of several calendrical functions.
\
\ Calendrical Calculations,
\ Dershowitz and Reingold
\ Environmental dependency on 32 bit arithmetic.
\
\ GLOSSARY
\ nth-Weekday */_ */_MOD /_ /_MOD Advent BCE
\ Birkath-Ha-Hama CALENDAR CE Christmas
\ Day-Number Day-of-Week-from-Fixed
\ Daylight-Savings-End Daylight-Savings-Start
\ Days-Remaining Days-in-Hebrew-Year Easter
\ Eastern-Orthodox-Christmas Election-Day Epiphany
\ FIRST Fixed-from-Gregorian Fixed-from-Hebrew
\ Fixed-from-ISO Fixed-from-Islamic Fixed-from-JD
\ Fixed-from-Julian Gregorian-Date-Difference
\ Gregorian-Epoch Gregorian-Leap-Year?
\ Gregorian-Year-from-Fixed Gregorian-from-Fixed
\ Hebrew-Birthday Hebrew-Calendar-Elapsed-Days
\ Hebrew-Epoch Hebrew-Leap-Year?
\ Hebrew-New-Year-Delay Hebrew-from-Fixed
\ ISO-from-Fixed Independence-Day Islamic-Epoch
\ Islamic-from-Fixed JD-Start JD-from-Moment
\ Julian-Epoch Julian-Leap-Year? Julian-from-Fixed
\ Julian-in-Gregorian LAST Labor-Day
\ Last-Day-of-Hebrew-Month Last-Month-of-Hebrew-Year
\ Long-Heshvan? Memorial-Day Moment-from-JD
\ Nicaean-Rule-Easter Omer Passover Pentecost
\ Purim Sh-Ela Short-Kislev? Ta-Anith-Esther
\ Thanksgiving Tisha-B-Av Weekday-After
\ Weekday-Before Weekday-Nearest Weekday-on-or-After
\ Weekday-on-or-Before Yahrzeit Yom-Ha-Zikaron
\ Yom-Kippur _MOD
\ /GLOSSARY
\
\ Needed from Tool Belt
\ NEEDS
\ THIRD FOURTH ANDIF
\ /NEEDS
\ *******************************************************************
\ * Operators for Floored Arithmetic *
\ *******************************************************************
\ From Forth Standard Annex, A.6.1.1561.
\ /_MOD ( dividend divisor -- remainder quotient )
\ `/MOD` with floored arithmetic.
\ /_ ( dividend divisor -- quotient )
\ `/` with floored arithmetic.
\ _MOD ( dividend divisor -- remainder )
\ `MOD` with floored arithmetic.
\ */_MOD ( amount multiplier divisor -- remainder quotient )
\ `*/MOD` with floored arithmetic.
\ */_ ( amount multiplier divisor -- quotient )
\ `*/` with floored arithmetic.
: /_MOD ( dividend divisor -- remainder quotient )
>R S>D R> FM/MOD ;
: /_ ( dividend divisor -- quotient ) /_MOD NIP ;
: _MOD ( dividend divisor -- remainder ) /_MOD DROP ;
: */_MOD ( amount multiplier divisor -- remainder quotient )
>R M* R> FM/MOD ;
: */_ ( amount multiplier divisor -- quotient ) */_MOD NIP ;
\ *******************************************************************
\ * Julian/Gregorian Months and Weekdays *
\ *******************************************************************
\ `SUN MON TUE WED THU FRI SAT`
\ IDs for day of week. {0...6}
\ `JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC`
\ IDs for months of Julian/Gregorian calendar. {1...12}
\ Day-of-Week-from-Fixed ( fixed-date -- day-of-week )
\ The ID of the day of the week of date {0...6}
0 DUP CONSTANT SUN
1+ DUP CONSTANT MON
1+ DUP CONSTANT TUE
1+ DUP CONSTANT WED
1+ DUP CONSTANT THU
1+ DUP CONSTANT FRI
1+ DUP CONSTANT SAT
DROP
1 DUP CONSTANT JAN
1+ DUP CONSTANT FEB
1+ DUP CONSTANT MAR
1+ DUP CONSTANT APR
1+ DUP CONSTANT MAY
1+ DUP CONSTANT JUN
1+ DUP CONSTANT JUL
1+ DUP CONSTANT AUG
1+ DUP CONSTANT SEP
1+ DUP CONSTANT OCT
1+ DUP CONSTANT NOV
1+ DUP CONSTANT DEC
DROP
\ *******************************************************************
\ * Julian Day Numbers *
\ *******************************************************************
: Day-of-Week-from-Fixed ( fixed-date -- day-of-week )
7 _MOD ;
\ JD-Start ( F: -- x )
\ Fixed time _x_ of start of julian day numbers.
\ Moment-from-JD ( F: julian-day-number -- moment )
\ Fixed time _moment_ of astronomical _julian-day-number_.
\ Fixed-from-JD ( F: julian-day-number -- )( -- fixed-date )
\ _fixed-date_ of astronomical _julian-day-number_.
\ JD-from-Moment ( F: moment -- julian-day-number )
\ Astronomical _julian-day-number_ of fixed moment _moment_.
-1721424.5E0 FCONSTANT JD-Start
: Moment-from-JD ( F: julian-day-number -- moment )
JD-Start F+ ;
: Fixed-from-JD ( F: julian-day-number -- )( -- fixed-date )
Moment-from-JD FLOOR F>D D>S ;
: JD-from-Moment ( F: moment -- julian-day-number )
JD-START F- ;
\ *******************************************************************
\ * Gregorian Calendar *
\ *******************************************************************
\ Gregorian-Epoch ( -- fixed-date )
\ _fixed-date_ at start of the (proleptic) Gregorian calendar.
\ Gregorian-Leap-Year? ( gregorian-year -- flag )
\ True if _gregorian-year_ is a leap year in the Gregorian
\ calendar
\ Day-Number ( month day year -- +n )
\ Day number in year of Gregorian date.
\ Fixed-from-Gregorian ( month day year -- fixed-date )
\ _fixed-date_ equivalent to the Gregorian date.
\ Gregorian-Year-from-Fixed ( fixed-date -- gregorian-year )
\ The _gregorian-year_ corresponding to the _fixed-date_.
\ Gregorian-from-Fixed ( fixed-date -- gregorian-date . . )
\ Gregorian month day year corresponding to _fixed-date_.
\ CALENDAR ( fixed-date -- )
\ Display month calendar from fixed-date. The fixed date
\ will be flagged. (Added by Wil Baden.)
1 CONSTANT Gregorian-Epoch
: Gregorian-Leap-Year? ( gregorian-year -- flag )
DUP 4 _MOD 0= ( gregorian-year flag)
OVER 100 _MOD 0= NOT AND
SWAP 400 _MOD 0= OR ( flag)
;
: Day-Number ( month day year -- day-of-year )
>R SWAP ( day month)( R: year)
DUP >R ( R: year month)
367 * 362 - 12 / + ( day-of-year)
R> 2 > IF \ Adjust for MAR..DEC. ( R: year)
R@ Gregorian-Leap-Year? IF 1- ELSE 2 - THEN
THEN
R> DROP ;
: Fixed-from-Gregorian ( month day year -- fixed-date )
DUP 1- >R ( R: previous-year)
Day-Number ( day-of-year)
R@ 4 /_ +
R@ 100 /_ -
R@ 400 /_ +
R> 365 * + ;
: Gregorian-Year-from-Fixed ( fixed-date -- gregorian-year )
Gregorian-Epoch - ( d0)
146097 /_MOD ( d1 n400)
400 * SWAP ( year d1)
36524 /_MOD ( year d2 n100)
DUP >R ( year d2 n100)( R: n100)
100 * ROT + SWAP ( year d2)
1461 /_MOD ( year d3 n4)
4 * ROT + SWAP ( year d3)
365 /_ ( year n1)
DUP >R ( year n1)( R: n100 n1)
+ ( year)
R> 4 = R> 4 = OR NOT IF 1+ THEN ;
: Gregorian-from-Fixed ( fixed-date -- month day year )
DUP Gregorian-Year-from-Fixed >R ( R: year)
DUP JAN 1 R@ Fixed-from-Gregorian - ( date prior-days)
OVER MAR 1 R@ Fixed-from-Gregorian < NOT IF
R@ Gregorian-Leap-Year? IF 1+ ELSE 2 + THEN
THEN
12 * 373 + 367 / >R ( date)( R: year month)
2R@ 1 ROT Fixed-from-Gregorian - 1+ ( day)
R> SWAP R> ( month day year) ;
: CALENDAR ( fixed -- )
DUP Gregorian-from-Fixed NIP ( fixed month year)
CR 8 SPACES OVER 1- 3 * CHARS
S" JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC" DROP + 3 TYPE
SPACE DUP . CR
2DUP >R 1+ 1 R> Fixed-from-Gregorian >R
1 SWAP Fixed-from-Gregorian ( fixed first-of-month)
DUP Day-of-Week-from-Fixed 4 * SPACES
R> OVER - 1+ 1 DO
I 2 .R
2DUP = IF ." * " ELSE 2 SPACES THEN
1+ DUP Day-of-Week-from-Fixed 0= IF CR THEN
LOOP
Day-of-Week-from-Fixed IF CR THEN
DROP ;
: CAL ( month day year -- ) Fixed-from-Gregorian Calendar ;
\ Gregorian-Date-Difference ( greg-date-1 . . greg-date-2 . . -- n )
\ Number of days from Gregorian date _greg-date-1_ until _greg-date-1_.
\ Days-Remaining ( gregorian-date . . -- +n )
\ Days remaining in year after Gregorian date _gregorian-date_.
: Gregorian-Date-Difference ( g-date-1 . . g-date-2 . . -- n )
Fixed-from-Gregorian >R Fixed-from-Gregorian R> SWAP - ;
: Days-Remaining ( month day year -- n )
DUP DEC 31 ROT Gregorian-Date-Difference ;
\ `Kday` has been changed to `Weekday`.
\ `Nth-Kday` has been changed to `nth-Weekday`.
\ Weekday-on-or-Before ( fixed-date-1 weekday -- fixed-date-2 )
\ _fixed-date-2_ of the _weekday_ on or before
\ _fixed-date-1_. _weekday_=0 means Sunday, _weekday_=1
\ means Monday, and so on.
\ Weekday-on-or-After ( fixed-date-1 weekday -- fixed-date-2 )
\ _fixed-date_ of the _weekday_ on or after _fixed-date_.
\ _weekday_=0 means Sunday, _weekday_=1 means Monday, and
\ so on.
\ Weekday-Nearest ( fixed-date-1 weekday -- fixed-date-2 )
\ _fixed-date_ of the _weekday_ nearest _fixed-date_.
\ _weekday_=0 means Sunday, _weekday_=1 means Monday, and
\ so on.
\ Weekday-After ( fixed-date-1 weekday -- fixed-date-2 )
\ _fixed-date_ of the _weekday_ after _fixed-date_.
\ _weekday_=0 means Sunday, _weekday_=1 means Monday, and
\ so on.
\ Weekday-Before ( fixed-date-1 weekday -- fixed-date-2 )
\ _fixed-date_ of the _weekday_ before _fixed-date_.
\ _weekday_=0 means Sunday, _weekday_=1 means Monday, and
\ so on.
\ nth-Weekday ( n weekday month day year -- fixed-date )
\ _fixed-date_ of _n_nth _weekday_ after _month day year_.
\ If _n_>0, return the _n_nth _weekday_ on or after the date. If
\ _n_<0, return the _n_nth _weekday_ on or before the date. A
\ _weekday_ of 0 means Sunday, 1 means Monday, and so on.
\ FIRST ( -- n )
\ Index for selecting a _weekday_.
\ LAST ( -- n )
\ Index for selecting a _weekday_.
: Weekday-on-or-Before ( date k -- date' )
OVER SWAP - Day-of-Week-from-Fixed - ;
: Weekday-on-or-After ( date k -- date' )
SWAP 6 + SWAP Weekday-on-or-Before ;
: Weekday-Nearest ( date k -- date' )
SWAP 3 + SWAP Weekday-on-or-Before ;
: Weekday-After ( date k -- date' )
SWAP 7 + SWAP Weekday-on-or-Before ;
: Weekday-Before ( date k -- date' )
SWAP 1- SWAP Weekday-on-or-Before ;
: nth-Weekday ( n k month day year -- date )
Fixed-from-Gregorian ( n k date)
SWAP ROT >R ( date k)( R: n)
R@ 0< IF Weekday-After ELSE Weekday-Before THEN ( date)
R> 7 * + ;
1 CONSTANT FIRST
-1 CONSTANT LAST
\ *******************************************************************
\ * "Holidays" *
\ *******************************************************************
\ Independence-Day ( gregorian-year -- fixed-date )
\ _fixed-date_ of American Independence Day in _gregorian-year_.
\ Labor-Day ( gregorian-year -- fixed-date )
\ _fixed-date_ of American Labor Day in _gregorian-year_--the
\ first Monday in September.
\ Memorial-Day ( gregorian-year -- fixed-date )
\ _fixed-date_ of American Memorial Day in Gregorian
\ year--the last Monday in May.
\ Election-Day ( gregorian-year -- fixed-date )
\ _fixed-date_ of American Election Day in Gregorian
\ year--the Tuesday after the first Monday in November.
\ Daylight-Savings-Start ( gregorian-year -- fixed-date )
\ _fixed-date_ of the start of American daylight savings time
\ in _gregorian-year_--the first Sunday in April.
\ Daylight-Savings-End ( gregorian-year -- fixed-date )
\ _fixed-date_ of the end of American daylight savings time
\ in _gregorian-year_--the last Sunday in October.
\ Thanksgiving ( gregorian-year -- fixed-date )
\ _fixed-date_ of Thanksgiving in _gregorian-year_.
\ Christmas ( gregorian-year -- fixed-date )
\ _fixed-date_ of Christmas in _gregorian-year_.
\ Advent ( gregorian-year -- fixed-date )
\ _fixed-date_ of Advent in _gregorian-year_.
\ Epiphany ( gregorian-year -- fixed-date )
\ _fixed-date_ of Epiphany in _gregorian-year_.
: Independence-Day ( greg-year -- fixed-date )
JUL 4 ROT Fixed-from-Gregorian ;
: Labor-Day ( year -- fixed-date )
>R FIRST MON SEP 1 R> nth-Weekday ;
: Memorial-Day ( year -- fixed-date )
>R LAST MON MAY 31 R> nth-Weekday ;
: Election-Day ( year -- fixed-date )
>R FIRST TUE NOV 2 R> nth-Weekday ;
: Daylight-Savings-Start ( year -- fixed-date )
>R FIRST SUN APR 1 R> nth-Weekday ;
: Daylight-Savings-End ( year -- fixed-date )
>R LAST SUN OCT 31 R> nth-Weekday ;
: Thanksgiving ( year -- fixed-date )
>R 4 THU NOV 1 R> nth-Weekday ;
: Christmas ( year -- fixed-date )
DEC 25 ROT Fixed-from-Gregorian ;
: Advent ( year -- fixed-date )
NOV 30 ROT Fixed-from-Gregorian SUN Weekday-Nearest ;
: Epiphany ( year -- fixed-date )
1- Christmas 12 + ;
\ *******************************************************************
\ * ISO Calendar *
\ *******************************************************************
\ Fixed-from-ISO ( week day year -- fixed-date )
\ _fixed-date_ equivalent to ISO (week day year).
\ ISO-from-Fixed ( fixed-date -- week day year )
\ ISO (week day year) corresponding to the _fixed-date_.
: Fixed-from-ISO ( week day year -- fixed-date )
>R ( week day)( R: year)
SWAP SUN DEC 28 R> 1- ( day week sun month day year)
nth-Weekday + ;
: ISO-from-Fixed ( fixed-date -- week day year )
DUP >R ( R: date )
3 - Gregorian-Year-from-Fixed ( approx)
1 1 THIRD 1+ Fixed-from-ISO R@ > NOT - ( year)
1 1 THIRD Fixed-from-ISO R@ SWAP - 7 /_ 1+ ( year week)
R> 1- 7 _MOD 1+ ( year week day)
ROT ( week day year) ;
\ *******************************************************************
\ * Julian Calendar *
\ *******************************************************************
\ Julian-Epoch ( fixed-date )
\ _fixed-date_ of start of the Julian calendar.
\ BCE ( standard-year -- julian-year )
\ Negative value to indicate a BCE Julian year.
\ CE ( standard-year -- julian-year )
\ Positive value to indicate a CE Julian year.
\ Julian-Leap-Year? ( julian-year -- flag )
\ True if year is a leap year on the Julian calendar.
\ Fixed-from-Julian ( julian-date -- fixed-date )
\ _fixed-date_ equivalent to the Julian date.
\ Julian-from-Fixed ( fixed-date -- julian-date )
\ Julian (month day year) corresponding to _fixed-date_.
DEC 30 0 Fixed-from-Gregorian CONSTANT Julian-Epoch
: Julian-Leap-Year? ( j-year -- flag )
DUP >R 4 _MOD R> 0> IF 0 ELSE 3 THEN = ;
: Fixed-from-Julian ( month day year -- fixed-date )
>R SWAP ( day month)( R: year)
DUP >R 367 * 362 - 12 / + ( day)( R: year month)
R> 2 > IF ( day)( R: year)
R@ Julian-Leap-Year? IF 1- ELSE 2 - THEN
THEN
Julian-Epoch + 1-
R> DUP 0< - 1- DUP >R 365 * + R> 4 /_ + ;
: Julian-from-Fixed ( fixed-date -- month day year )
DUP Julian-Epoch - 4 * 1464 + 1461 /_ ( date approx)
DUP 0> NOT + >R ( date)( R: year)
DUP JAN 1 R@ Fixed-from-Julian - ( date prior-days)
OVER MAR 1 R@ Fixed-from-Julian < NOT IF
R@ Julian-Leap-Year? IF 1+ ELSE 2 + THEN
THEN
12 * 373 + 367 /_ ( date month)
SWAP OVER 1 R@ Fixed-from-Julian - 1+ ( month day)
R> ( month day year) ;
\ *******************************************************************
\ * Ecclesiastical Calendars *
\ *******************************************************************
\ Nicaean-Rule-Easter ( julian-year -- fixed-date )
\ _fixed-date_ of Easter in positive Julian year, according
\ to the rule of the Council of Nicaea.
\ Easter ( gregorian-year -- fixed-date )
\ _fixed-date_ of Easter in _gregorian-year_.
\ Pentecost ( gregorian-year -- fixed-date )
\ _fixed-date_ of Pentecost in _gregorian-year_.
\ Julian-in-Gregorian ( j-month j-day greg-year -- list-of-fixed-dates )
\ The list of the _fixed-dates_ of Julian month, day that occur
\ in _gregorian-year_.
\ Eastern-Orthodox-Christmas ( gregorian-year -- list-of-fixed-dates )
\ List of zero or one _fixed-dates_ of Eastern Orthodox
\ Christmas in _gregorian-year_.
: Nicaean-Rule-Easter ( j-year -- date )
DUP >R ( R: j-year)
19 MOD 11 * 14 + 30 MOD ( shifted-epact)
APR 19 R> Fixed-from-Julian SWAP - ( paschal-moon)
SUN Weekday-After ;
: Easter ( greg-year -- date )
DUP >R ( R: greg-year)
100 / 1+ ( century)
R@ 19 MOD 11 * 14 + ( century shifted-epact)
OVER 3 * 4 / -
SWAP 8 * 5 + 25 / + ( shifted-epact)
30 MOD
DUP 0= IF 1+
ELSE DUP 1 = 10 R@ 19 MOD < AND IF 1+
THEN THEN ( adjusted-epact)
APR 19 R> Fixed-from-Gregorian SWAP - ( paschal-moon)
SUN Weekday-After ;
: Pentecost ( greg-year -- date )
Easter 49 + ;
: Ash-Wednesday ( greg-year -- date )
Easter 46 - ;
\ *******************************************************************
\ * Islamic Calendar *
\ *******************************************************************
\ Islamic-Epoch ( -- fixed-date )
\ _fixed-date_ of start of the Islamic calendar.
\ Fixed-from-Islamic ( islamic-date -- fixed-date )
\ _fixed-date_ equivalent to Islamic date.
\ Islamic-from-Fixed ( fixed-date -- islamic-date )
\ Islamic date (month day year)
\ corresponding to _fixed-date_.
JUL 16 622 Fixed-from-Julian CONSTANT Islamic-Epoch
: Fixed-from-Islamic ( month day year -- fixed )
>R SWAP ( day month)( R: year)
1- 295 * 5 + 10 /_ +
R@ 1- 354 * +
R> 11 * 3 + 30 /_ +
Islamic-Epoch + 1- ;
: Islamic-from-Fixed ( fixed -- month day year )
DUP Islamic-Epoch - 30 * 10646 + 10631 /_ >R ( R: year)
DUP 29 - 1 1 R@ Fixed-from-Islamic - 2* 59 /_MOD SWAP IF 1+ THEN
1+ 12 MIN ( date month)
SWAP OVER 1 R@ Fixed-from-Islamic - 1+ ( month day)
R> ( month day year) ;
\ *******************************************************************
\ * Hebrew Calendar *
\ *******************************************************************
\ Hebrew-Epoch ( -- fixed-date )
\ _fixed-date_ of start of the Hebrew calendar, that is,
\ Tishri 1, 1 AM.
\ Hebrew-Leap-Year? ( hebrew-year -- flag )
\ True if year is a leap year on Hebrew calendar.
\ Last-Month-of-Hebrew-Year ( hebrew-year -- hebrew-month )
\ Last month of Hebrew year.
\ Long-Heshvan? ( hebrew-year -- flag )
\ True if Heshvan is long in Hebrew year.
\ Short-Kislev? ( hebrew-year -- flag )
\ True if Kislev is short in Hebrew year.
\ Last-Day-of-Hebrew-Month ( hebrew-month hebrew-year -- hebrew-day )
\ Last day of month in Hebrew year.
\ Hebrew-Calendar-Elapsed-Days ( hebrew-year -- n )
\ Number of days elapsed from the (Sunday) noon prior to
\ the epoch of the Hebrew calendar to the mean conjunction
\ (molad) of Tishri of Hebrew year h-year, or one day
\ later.
\ Hebrew-New-Year-Delay ( hebrew-year -- [0,1,2] )
\ Delays to start of Hebrew year to keep ordinary year in
\ range 353-356 and leap year in range 383-386.
\ Days-in-Hebrew-Year ( hebrew-year -- [353,354,355,383,384,385] )
\ Number of days in Hebrew year. Calls Fixed-from-Hebrew
\ for value that does not in turn require
\ Days-in-Hebrew-Year.
OCT 7 -3761 Fixed-from-Julian CONSTANT Hebrew-Epoch
: Hebrew-Leap-Year?
7 * 1+ 19 _MOD 7 < ;
: Last-Month-of-Hebrew-Year
Hebrew-Leap-Year? IF 13 ELSE 12 THEN ;
: Hebrew-Calendar-Elapsed-Days ( h-year -- day )
235 * 234 - 19 /_ ( months-elapsed)
DUP 13753 * 12084 + ( month-elapsed parts-elapsed)
25920 /_ SWAP 29 * + ( day)
DUP 1+ 3 * 7 _MOD 3 < - ;
: Hebrew-New-Year-Delay ( h-year -- n )
DUP 1- Hebrew-Calendar-Elapsed-Days ( year ny0)
OVER Hebrew-Calendar-Elapsed-Days ( year ny0 ny1)
ROT 1+ Hebrew-Calendar-Elapsed-Days ( ny0 ny1 ny2)
OVER - 356 = IF 2DROP 2
ELSE SWAP - 382 = IF 1
ELSE 0
THEN THEN ;
DEFER Fixed-from-Hebrew ( month day year -- date )
: Days-in-Hebrew-Year ( h-year -- days )
>R 7 1 R@ 1+ Fixed-from-Hebrew
7 1 R> Fixed-from-Hebrew - ;
: Long-Heshvan? ( h-year -- flag )
Days-in-Hebrew-Year 10 MOD 5 = ;
: Short-Kislev? ( h-year -- flag )
Days-in-Hebrew-Year 10 MOD 3 = ;
: Last-Day-of-Hebrew-Month ( month year -- day )
\ Bits 2 4 6 10 13
OVER 1 SWAP LSHIFT
[ 2 BASE ! ] 10010001010100 [ DECIMAL ]
AND
IF 2DROP 29 EXIT THEN
OVER 12 = IF
DUP Hebrew-Leap-Year? NOT IF 2DROP 29 EXIT THEN
THEN
OVER 8 = IF
DUP Long-Heshvan? NOT IF 2DROP 29 EXIT THEN
THEN
OVER 9 = IF
DUP Short-Kislev? IF 2DROP 29 EXIT THEN
THEN
2DROP 30 ;
\ Fixed-from-Hebrew ( hebrew-date -- fixed-date )
\ _fixed-date_ from Hebrew date. This function is designed so
\ that it works for Hebrew dates month, day, year even if
\ the month has fewer than day days--in that case the
\ function returns the (day-1)st day after month 1, year.
\ This property is required by the functions
\ hebrew-birthday and yahrzeit.
\ Hebrew-from-Fixed ( fixed-date -- hebrew-date )
\ Hebrew (month day year) corresponding to _fixed-date_. The
\ fraction can be approximated by 365.25.
: (Fixed-from-Hebrew) ( month day year -- date )
Hebrew-Epoch ( month day year date)
OVER Hebrew-Calendar-Elapsed-Days +
OVER Hebrew-New-Year-Delay + THIRD + 1 -
FOURTH 7 < IF
OVER Last-Month-of-Hebrew-Year 1+ 7 DO
OVER I SWAP Last-Day-of-Hebrew-Month +
LOOP
FOURTH 1 ?DO
OVER I SWAP Last-Day-of-Hebrew-Month +
LOOP
ELSE
FOURTH 7 ?DO
OVER I SWAP Last-Day-of-Hebrew-Month +
LOOP
THEN
NIP NIP NIP ;
' (Fixed-from-Hebrew) IS Fixed-from-Hebrew
: Hebrew-from-Fixed ( date -- month day year )
DUP >R ( R: date)
Hebrew-Epoch - 98496 35975351 */_ ( approx)
BEGIN 7 1 THIRD Fixed-from-Hebrew R@ > NOT WHILE
1+
REPEAT 1- >R ( )( R: date year)
2R@ 1 1 ROT Fixed-from-Hebrew < IF 7 ELSE 1 THEN
( start)
BEGIN DUP DUP R@ Last-Day-of-Hebrew-Month
R@ Fixed-from-Hebrew 2R@ DROP <
WHILE 1+ REPEAT ( month)
DUP 1 R@ Fixed-from-Hebrew 2R@ DROP SWAP - 1+
( month day)
R> ( month day year) R> DROP ;
\ *******************************************************************
\ * Hebrew Holidays and Fast Days *
\ *******************************************************************
\ Yom-Kippur ( gregorian-year -- fixed-date )
\ _fixed-date_ of Yom Kippur occurring in
\ _gregorian-year_.
\ Passover ( gregorian-year -- fixed-date )
\ _fixed-date_ of Passover occurring in _gregorian-year_.
\ Omer ( fixed-date -- omer-count )
\ Number of elapsed weeks and days in the omer at date.
\ Returns bogus if that date does not fall during the
\ omer.
\ Purim ( gregorian-year -- fixed-date )
\ _fixed-date_ of Purim occurring in _gregorian-year_.
\ Ta-Anith-Esther ( gregorian-year -- fixed-date )
\ _fixed-date_ of Ta'anith Esther occurring in
\ _gregorian-year_.
\ Tisha-B-Av ( gregorian-year -- fixed-date )
\ _fixed-date_ of Tisha B'Av occurring in Gregorianyear.
\ Birkath-Ha-Hama ( gregorian-year -- list-of-fixed-dates )
\ List of _fixed-date_ of Birkath HaHama occurring in
\ _gregorian-year_, if it occurs.
\ Sh-Ela ( gregorian-year -- fixed-date )
\ _fixed-date_ of Sh'ela occurring in _gregorian-year_.
\ Yom-Ha-Zikaron ( gregorian-year -- fixed-date )
\ _fixed-date_ of Yom HaZikaron occurring in _gregorian-year_.
: Yom-Kippur ( gregorian-year -- fixed-date )
7 10 ROT Hebrew-Epoch Gregorian-Year-from-Fixed - 1+
Fixed-from-Hebrew ( date) ;
: Rosh-Hashanah ( gregorian-year -- fixed-date )
7 1 ROT Hebrew-Epoch Gregorian-Year-from-Fixed - 1+
Fixed-from-Hebrew ;
: Passover ( gregorian-year -- fixed-date )
1 15 ROT Hebrew-Epoch Gregorian-Year-from-Fixed -
Fixed-from-Hebrew ;
: Purim ( gregorian-year -- fixed-date )
Hebrew-Epoch Gregorian-Year-from-Fixed - ( h-year)
DUP Last-Month-of-Hebrew-Year ( h-year month)
14 ROT ( month day year)
Fixed-from-Hebrew ( date) ;
: Esther ( gregorian-year -- fixed-date )
Purim DUP Day-of-Week-from-Fixed SUN =
IF 3 - ELSE 1- THEN
;
: Yom-Hashoah ( gregorian-year -- fixed-date )
1 27 ROT Hebrew-Epoch Gregorian-Year-from-Fixed -
Fixed-from-Hebrew ( date) ;
: Hanukkah ( gregorian-year -- fixed-date )
9 25 ROT Hebrew-Epoch Gregorian-Year-from-Fixed - 1+
Fixed-from-Hebrew ( date) ;
\ *******************************************************************
\ * Days of Personal Interest *
\ *******************************************************************
\ Hebrew-Birthday ( hebrew-birthdate . . hebrew-year -- fixed-date )
\ _fixed-date_ of the anniversary of _hebrew-birthdate_
\ occurring in _hebrew-year_. This function assumes that the
\ function `Fixed-from-Hebrew` works for Hebrew _month
\ day year_ even if the month has fewer than _day_ days--in
\ that case the function returns the (_day_-1)st day after
\ _month_ 1 _year_.
\ Yahrzeit ( hebrew-deathdate . . hebrew-year -- fixed-date )
\ _fixed-date_ of the anniversary of _hebrew-deathdate_
\ occurring in _hebrew-year_. This function assumes that the
\ function `Fixed-from-Hebrew` works for Hebrew _month
\ day year_ even if the month has fewer than _day_ days--in
\ that case the function returns the (_day_-1)st day after
\ _month_ 1 _year_.
: Hebrew-Birthday ( b-month b-day b-year h-year -- date )
>R ( b-month b-day b-year)( R: h-year)
THIRD SWAP Last-Month-of-Hebrew-Year = IF ( month day)
R@ Last-Month-of-Hebrew-Year OVER R>
ELSE
2DUP R>
THEN
Fixed-from-Hebrew NIP NIP ;
: Yahrzeit ( death-month death-day death-year h-year -- date )
>R ( death-month death-day death-year)( R: h-year)
THIRD 8 =
ANDIF OVER 30 =
ANDIF DUP 1- Long-Heshvan? NOT
THEN THEN
IF 3DROP 9 1 R> Fixed-from-Hebrew 1- EXIT THEN
THIRD 9 =
ANDIF OVER 30 =
ANDIF DUP 1+ Short-Kislev?
THEN THEN
IF 3DROP 10 1 R> Fixed-from-Hebrew 1- EXIT THEN
THIRD 13 = IF
DROP NIP R@ Last-Month-of-Hebrew-Year SWAP R>
Fixed-from-Hebrew EXIT THEN
THIRD 12 =
ANDIF OVER 30 =
ANDIF R@ Hebrew-Leap-Year? NOT
THEN THEN
IF 3DROP 11 30 R> Fixed-from-Hebrew EXIT THEN
DROP R> Fixed-from-Hebrew ;
\\ End of Calendrical Calculations