Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Holiday Processing 2

Status
Not open for further replies.

Glenn9999

Programmer
Jun 19, 2004
2,311
0
36
US
I was in another forum and saw someone talk about manually entering holidays into their system, and thought it might be interesting to try to code up something that comes up with holidays, so I came up with this proof-of-concept that something along those lines could be done. Hopefully it helps out someone.

About the only thing that's missing is adjusting for workdays if a holiday comes up on a Saturday or a Sunday, but that can be easily handled by calling 2000-Zeller and then adjusting the day forward or backward.

Code:
 IDENTIFICATION DIVISION.
 PROGRAM-ID. HOLIDAY.
* This program lists all holidays for the year given in input.
* RULES FOR HOLIDAYS.
*
* WRITTEN AND COPYRIGHTED FOR GENERAL DISTRIBUTION BY
* "GLENN9999 AT tek-tips.COM".  ANY USE OF THIS CODE MUST
* INCLUDE THESE THREE LINES WITHIN THEM.
*
* 1) New Year's Day is every January 1.
* 2) Martin Luther King Day is the third Monday in January.
* 3) President's Day is the third Monday in February.
* 4) Easter is ...
* 5) Memorial Day is the last Monday in May.
* 6) Independence Day is every July 4.
* 7) Labor Day is the first monday in September.
* 8) Columbus Day is the second Monday in October.
* 9) Veteran's Day is November 11.
* 10) Thanksgiving is the fourth Thursday in November.
* 11) Christmas is December 25.

 DATA DIVISION.
 WORKING-STORAGE SECTION.

 01  PROCESSING-VARIABLES.
     04  YEAR-INPUT            PIC S9(4) COMP-5.
     04  ZIN-MONTH             PIC S9(4) COMP-5.
     04  ZIN-YEAR              PIC S9(4) COMP-5.
     04  ZIN-CENTURY           PIC S9(4) COMP-5.
     04  ZIN-DOW               PIC S9(4) COMP-5.
     04  ZIN-DAY               PIC S9(4) COMP-5.
     04  ZIN-TEMP              PIC S9(4) COMP-5.
     04  EST-N                 PIC S9(4) COMP-5.
     04  EST-D                 PIC S9(4) COMP-5.
     04  EST-K                 PIC S9(4) COMP-5.
     04  EST-I                 PIC S9(4) COMP-5.
     04  EST-J                 PIC S9(4) COMP-5.
     04  EST-L                 PIC S9(4) COMP-5.

 01  OUTPUT-VARIABLES.
     04  OUTPUT-DATA.
         08                    PIC X(32) VALUE "NEW YEAR'S DAY".
         08                    PIC X(10) VALUE "  /  /    ".

         08                    PIC X(32)
            VALUE "MARTIN LUTHER KING DAY".
         08                    PIC X(10) VALUE "  /  /    ".

         08                    PIC X(32) VALUE "PRESIDENT'S DAY".
         08                    PIC X(10) VALUE "  /  /    ".

         08                    PIC X(32) VALUE "EASTER".
         08                    PIC X(10) VALUE "  /  /    ".

         08                    PIC X(32) VALUE "MEMORIAL DAY".
         08                    PIC X(10) VALUE "  /  /    ".

         08                    PIC X(32) VALUE "INDEPENDENCE DAY".
         08                    PIC X(10) VALUE "  /  /    ".

         08                    PIC X(32) VALUE "LABOR DAY".
         08                    PIC X(10) VALUE "  /  /    ".

         08                    PIC X(32) VALUE "COLUMBUS DAY".
         08                    PIC X(10) VALUE "  /  /    ".

         08                    PIC X(32) VALUE "VETERAN'S DAY".
         08                    PIC X(10) VALUE "  /  /    ".

         08                    PIC X(32) VALUE "THANKSGIVING".
         08                    PIC X(10) VALUE "  /  /    ".

         08                    PIC X(32) VALUE "CHRISTMAS".
         08                    PIC X(10) VALUE "  /  /    ".


     04  OUTPUT-TABLE REDEFINES OUTPUT-DATA
                      OCCURS 11 TIMES
                      INDEXED BY OUT-NDX.
         08  FILLER            PIC X(32).
         08  OUT-MONTH         PIC 99.
         08  FILLER            PIC X.
         08  OUT-DAY           PIC 99.
         08  FILLER            PIC X.
         08  OUT-YEAR          PIC 9999.

 PROCEDURE DIVISION.
 0000-MAIN SECTION.
     MOVE 1 TO ZIN-DAY.
     DISPLAY "ENTER A YEAR."
     ACCEPT YEAR-INPUT.
     PERFORM 1000-PROCESS-DATA.
     PERFORM VARYING OUT-NDX FROM 1 BY 1
             UNTIL OUT-NDX > 11
        DISPLAY OUTPUT-TABLE (OUT-NDX)
     END-PERFORM.
     GOBACK.

 1000-PROCESS-DATA SECTION.
     PERFORM 1001-NEW-YEARS-DAY.
     PERFORM 1002-MLKDAY.
     PERFORM 1003-PRES-DAY.
     PERFORM 1004-EASTER.
     PERFORM 1005-MEM-DAY.
     PERFORM 1006-INDEP-DAY.
     PERFORM 1007-LABORDAY.
     PERFORM 1008-COLUMBUSDAY.
     PERFORM 1009-VETERANSDAY.
     PERFORM 1010-THANKSGIVING.
     PERFORM 1011-CHRISTMAS.

 1001-NEW-YEARS-DAY SECTION.
* NEW YEAR'S DAY
     SET OUT-NDX TO 1.
     MOVE YEAR-INPUT TO OUT-YEAR (OUT-NDX).
     MOVE 1 TO OUT-MONTH (OUT-NDX).
     MOVE 1 TO OUT-DAY (OUT-NDX).

 1002-MLKDAY SECTION.
     SET OUT-NDX TO 2.
* MARTIN LUTHER KING DAY
     MOVE 1 TO OUT-MONTH (OUT-NDX) ZIN-MONTH.
     MOVE YEAR-INPUT TO ZIN-YEAR.
     PERFORM 2000-ZELLER.
* ADJUST TO THE FIRST MONDAY  (1)
     IF ZIN-DOW < 1
        COMPUTE ZIN-TEMP = 1 - ZIN-DOW
     ELSE
        COMPUTE ZIN-TEMP = 7 - ZIN-DOW + 1
     END-IF.
* ADJUST TO THE THIRD MONDAY
     COMPUTE OUT-DAY (OUT-NDX) = ZIN-DAY + ZIN-TEMP + (2 * 7).
     MOVE YEAR-INPUT TO OUT-YEAR (OUT-NDX).

 1003-PRES-DAY SECTION.
     SET OUT-NDX TO 3.
* PRESIDENTS DAY
     MOVE 2 TO OUT-MONTH (OUT-NDX) ZIN-MONTH.
     MOVE YEAR-INPUT TO ZIN-YEAR.
     PERFORM 2000-ZELLER.
* ADJUST TO THE FIRST MONDAY  (1)
     IF ZIN-DOW < 1
        COMPUTE ZIN-TEMP = 1 - ZIN-DOW
     ELSE
        COMPUTE ZIN-TEMP = 7 - ZIN-DOW + 1
     END-IF.
* ADJUST TO THE THIRD MONDAY
     COMPUTE OUT-DAY (OUT-NDX) = ZIN-DAY + ZIN-TEMP + (2 * 7).
     MOVE YEAR-INPUT TO OUT-YEAR (OUT-NDX).

 1004-EASTER SECTION.
     SET OUT-NDX TO 4.
     MOVE YEAR-INPUT TO ZIN-YEAR OUT-YEAR (OUT-NDX).
     PERFORM 3000-EASTER.
     MOVE ZIN-MONTH TO OUT-MONTH (OUT-NDX).
     MOVE EST-D TO OUT-DAY (OUT-NDX).

 1005-MEM-DAY SECTION.
     SET OUT-NDX TO 5.
* MEMORIAL DAY IS LAST MONDAY IN MAY, SO WE NEED TO FIND JUNE 1.
     MOVE 6 TO ZIN-MONTH.
     MOVE YEAR-INPUT TO ZIN-YEAR.
     PERFORM 2000-ZELLER.
* ADJUST TO THE PREVIOUS MONDAY  (1)
     IF ZIN-DOW > 1
        COMPUTE ZIN-TEMP = ZIN-DOW - 1
     ELSE
        COMPUTE ZIN-TEMP = 7 - ZIN-DOW - 1
     END-IF.

* ADJUST TO THE PREVIOUS MONDAY (IN MAY)
     COMPUTE OUT-DAY (OUT-NDX) = 31 - ZIN-TEMP + 1.
     MOVE 5 TO OUT-MONTH (OUT-NDX).
     MOVE YEAR-INPUT TO OUT-YEAR (OUT-NDX).

 1006-INDEP-DAY SECTION.
* INDEPENDENCE DAY
     SET OUT-NDX TO 6.
     MOVE YEAR-INPUT TO OUT-YEAR (OUT-NDX).
     MOVE 7 TO OUT-MONTH (OUT-NDX).
     MOVE 4 TO OUT-DAY (OUT-NDX).

 1007-LABORDAY SECTION.
     SET OUT-NDX TO 7.
* LABOR DAY
     MOVE 9 TO OUT-MONTH (OUT-NDX) ZIN-MONTH.
     MOVE YEAR-INPUT TO ZIN-YEAR.
     PERFORM 2000-ZELLER.
* ADJUST TO THE FIRST MONDAY  (1)
     IF ZIN-DOW < 1
        COMPUTE ZIN-TEMP = 1 - ZIN-DOW
     ELSE
        COMPUTE ZIN-TEMP = 7 - ZIN-DOW + 1
     END-IF.
* ADJUST TO THE FIRST MONDAY
     COMPUTE OUT-DAY (OUT-NDX) = ZIN-DAY + ZIN-TEMP.
     MOVE YEAR-INPUT TO OUT-YEAR (OUT-NDX).

 1008-COLUMBUSDAY SECTION.
     SET OUT-NDX TO 8.
* COLUMBUS DAY
     MOVE 10 TO OUT-MONTH (OUT-NDX) ZIN-MONTH.
     MOVE YEAR-INPUT TO ZIN-YEAR.
     PERFORM 2000-ZELLER.
* ADJUST TO THE FIRST MONDAY  (1)
     IF ZIN-DOW < 1
        COMPUTE ZIN-TEMP = 1 - ZIN-DOW
     ELSE
        COMPUTE ZIN-TEMP = 7 - ZIN-DOW + 1
     END-IF.
* ADJUST TO THE SECOND MONDAY
     COMPUTE OUT-DAY (OUT-NDX) = ZIN-DAY + ZIN-TEMP + (1 * 7).
     MOVE YEAR-INPUT TO OUT-YEAR (OUT-NDX).

 1009-VETERANSDAY SECTION.
* VETERANS DAY
     SET OUT-NDX TO 9.
     MOVE YEAR-INPUT TO OUT-YEAR (OUT-NDX).
     MOVE 11 TO OUT-MONTH (OUT-NDX).
     MOVE 11 TO OUT-DAY (OUT-NDX).

 1010-THANKSGIVING SECTION.
     SET OUT-NDX TO 10.
* THANKSGIVING
     MOVE 11 TO OUT-MONTH (OUT-NDX) ZIN-MONTH.
     MOVE YEAR-INPUT TO ZIN-YEAR.
     PERFORM 2000-ZELLER.
* ADJUST TO THE FIRST THURSDAY  (4)
     IF ZIN-DOW < 4
        COMPUTE ZIN-TEMP = 4 - ZIN-DOW
     ELSE
        COMPUTE ZIN-TEMP = 7 - ZIN-DOW + 4
     END-IF.
* ADJUST TO THE FOURTH MONDAY
     COMPUTE OUT-DAY (OUT-NDX) = ZIN-DAY + ZIN-TEMP + (3 * 7).
     MOVE YEAR-INPUT TO OUT-YEAR (OUT-NDX).

 1011-CHRISTMAS SECTION.
* CHRISTMAS DAY
     SET OUT-NDX TO 11.
     MOVE YEAR-INPUT TO OUT-YEAR (OUT-NDX).
     MOVE 12 TO OUT-MONTH (OUT-NDX).
     MOVE 25 TO OUT-DAY (OUT-NDX).

 2000-ZELLER SECTION.
* An implementation of Zellers Congruence - Provides the
* first day of the month passed to ZIN-MONTH, RETURNS DAY OF
* WEEK IN ZIN-DOW..
* [URL unfurl="true"]http://www.adaic.org/docs/craft/html/ch04.htm[/URL]
* ZIN-DOW IS 0 = SUNDAY 1 = MONDAY 2 = TUESDAY 3 = WEDNESDAY
*            4 = THURSDAY 5 = FRIDAY 6 = SATURDAY
     IF ZIN-MONTH < 3 THEN
        SUBTRACT 1 FROM ZIN-YEAR
        ADD 10 TO ZIN-MONTH
     ELSE
        SUBTRACT 2 FROM ZIN-MONTH
     END-IF.
     DIVIDE ZIN-YEAR BY 100 GIVING ZIN-CENTURY REMAINDER ZIN-YEAR.
     COMPUTE ZIN-TEMP = (26 * ZIN-MONTH - 2) / 10.
     COMPUTE ZIN-TEMP = ZIN-TEMP + ZIN-DAY + ZIN-YEAR.
     COMPUTE ZIN-TEMP = ZIN-TEMP + (ZIN-YEAR / 4) + (ZIN-CENTURY / 4).
     COMPUTE ZIN-TEMP = ZIN-TEMP - (2 * ZIN-CENTURY).
     DIVIDE ZIN-TEMP BY 7 GIVING ZIN-TEMP REMAINDER ZIN-DOW.
     IF ZIN-DOW < 0
        ADD 7 TO ZIN-DOW
     END-IF.

 3000-EASTER SECTION.
*The algorithm uses the year, y, to give the month, m, and day,
* d, of Easter. The symbol * means multiply. Please note the
* following: This is an integer calculation. All variables
* are integers and all remainders from division are dropped.
* [URL unfurl="true"]http://aa.usno.navy.mil/faq/docs/easter.html[/URL]
*   c = y / 100
*   n = y - 19 * ( y / 19 )
*   k = ( c - 17 ) / 25
*   i = c - c / 4 - ( c - k ) / 3 + 19 * n + 15
*   i = i - 30 * ( i / 30 )
*   i = i - ( i / 28 ) * ( 1 - ( i / 28 ) * ( 29 / ( i + 1 ) )
*       * ( ( 21 - n ) / 11 ) )
*   j = y + y / 4 + i + 2 - c + c / 4
*   j = j - 7 * ( j / 7 )
**  l = i - j
*   m = 3 + ( l + 40 ) / 44
*   d = l + 28 - 31 * ( m / 4 )
*
     COMPUTE ZIN-CENTURY = ZIN-YEAR / 100.
     COMPUTE EST-N = ZIN-YEAR - 19 * (ZIN-YEAR / 19).
     COMPUTE EST-K = (ZIN-CENTURY - 17) / 25.
     COMPUTE EST-I = ZIN-CENTURY - (ZIN-CENTURY / 4) - (ZIN-CENTURY - EST-K) / 3.
     COMPUTE EST-I = EST-I + 19 * EST-N + 15.
     COMPUTE EST-I = EST-I - 30 * (EST-I / 30).
     COMPUTE EST-I = EST-I - (EST-I / 28) * (1 - (EST-I / 28) * (29 / (EST-I + 1))
                     * ((21 - EST-N) / 11)).
     COMPUTE EST-J = ZIN-YEAR + (ZIN-YEAR / 4) + EST-I + 2 - ZIN-CENTURY + (ZIN-CENTURY / 4)
     COMPUTE EST-J = EST-J - 7 * (EST-J / 7)
     COMPUTE EST-L = EST-I - EST-J.
     COMPUTE ZIN-MONTH = 3 + (EST-L + 40) / 44.
     COMPUTE EST-D = EST-L + 28 - 31 * (ZIN-MONTH / 4).
 
I don't follow the calculation, but Easter is the first Sunday on or after the first full moon on or after the Verneal Equinox. Can anyone match this to the above calculation?
 
Although this is not specific to COBOL, it is always useful to know the actual rule involved, if for no other reason than to remind ourselves that oversimplification is dangerous.

The usual statement, that Easter Day is the first Sunday after the full moon that occurs next after the vernal equinox, is not a precise statement of the actual ecclesiastical rules. The full moon involved is not the astronomical Full Moon but an ecclesiastical moon (determined from tables) that keeps, more or less, in step with the astronomical Moon.

The ecclesiastical rules are:

Easter falls on the first Sunday following the first ecclesiastical full moon that occurs on or after the day of the vernal equinox;

this particular ecclesiastical full moon is the 14th day of a tabular lunation (new moon);

and the vernal equinox is fixed as March 21.

resulting in that Easter can never occur before March 22 or later than April 25. The Gregorian dates for the ecclesiastical full moon come from the Gregorian tables. Therefore, the civil date of Easter depends upon which tables - Gregorian or pre-Gregorian - are used. The western (Roman Catholic and Protestent) Christian churches use the Gregorian tables; many eastern (Orthodox) Christian churches use the older tables based on the Julian Calendar.
- excerpted from
Pedantically yours,
jar
 
Here is an other one: thread740-122553
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top