开发者

Any date should be converted to end of the month date in cobol?

开发者 https://www.devze.com 2023-03-19 11:37 出处:网络
I have a requirement where any date (DD.MM.YYYY) should be converted to last date of month (ex: If date is 20.01.1999 then it should convert in开发者_StackOverflow中文版to 31.01.1999) ?Exactly what ar

I have a requirement where any date (DD.MM.YYYY) should be converted to last date of month (ex: If date is 20.01.1999 then it should convert in开发者_StackOverflow中文版to 31.01.1999) ?


Exactly what are you having trouble with? COBOL or the algorithm? I'm guessing its COBOL.

I'm not going to give you a direct answer because you are obviously leaning the language and there is value in working out the specific details for yourself.

Here are a couple of hints:

Define a date field in WORKING-STORAGE so that you can pick out the day, month and year as separate items. Something like:

01 TEST-DATE.
   05 TEST-DAY     PIC 99.
   05              PIC X.
   05 TEST-MONTH   PIC 99.
   05              PIC X.
   05 TEST-YEAR    PIC 9999.

Note the unnamed PIC X fields. These contain the day/month/year delimiters. They do not need to be given data names because you do not need to reference them. Sometimes this type of data item is given the name FILLER, but the name is optional.

Read up on the EVALUATE statement. Here is a link to the IBM Enterprise COBOL manual. This description of EVALUATE should be similar in all versions of COBOL.

MOVE the date of interest TO TEST-DATE. Now you can reference the year, month and day as individual items: TEST-DAY, TEST-MONTH and TEST-YEAR.

Use EVALUATE to test the month (TEST-MONTH). If the month is a 30 day month then MOVE 30 to TEST-DAY. Do the same for 31 day months. February is a special case because of leap years. Once you have determined that the month is February, test TEST-YEAR to determine if it is a leap year and MOVE 28 or 29 TO TEST-DAY depending on the outcome of the test.

Now TEST-DATE will contain the date you are looking for. MOVE it to wherever it is needed.


You can use function integer-of-date which gives returns an integral value corresponding to any date. Assuming your input date is in ddmmyyyy format and you expect hte output in the same format. Lets say date is 20011999 and you want as 31011999. You can follow the below steps.

  • Increase the month of the input date by one. (20*02*1999)
  • Make the day as 01 and use function integer-of-date (*01*021999)
  • subtract one from the integer returned.
  • use function date-of-integer which will give you the required result.

Note here you will have to add one more check for handling December month.


Here you go! Run the code here

IDENTIFICATION DIVISION.                               
PROGRAM-ID. STACK2.                                    
DATA DIVISION.                                         
WORKING-STORAGE SECTION.                               
01 WS-DATE        PIC X(10).                           
01 WORK-DATE.                                          
   05 WORK-DAY    PIC 9(2).                            
   05             PIC X.                               
   05 WORK-MONTH  PIC 9(2).                            
   05             PIC X.                               
   05 WORK-YEAR   PIC 9(4).                            
01 MONTH-31 PIC 9(2).                                  
   88 IS-MONTH-31 VALUES 01, 03, 05, 07, 08, 10, 12.   
   88 IS-MONTH-30 VALUES 04, 06, 09, 11.               
01 WS-C           PIC 9(4) VALUE 0.                    
01 WS-D           PIC 9(4) VALUE 0.                    
PROCEDURE DIVISION.                                    
    ACCEPT WS-DATE.                                    
    MOVE WS-DATE TO WORK-DATE.                         
    DISPLAY 'ACTUALE TEST-DATE: ' WORK-DATE.             
    MOVE WORK-MONTH TO MONTH-31.                       
    EVALUATE TRUE                                      
    WHEN IS-MONTH-31                                   
    MOVE 31 TO WORK-DAY                                             
    WHEN IS-MONTH-30                                    
    MOVE 30 TO WORK-DAY                                              
    WHEN OTHER                                          
    DIVIDE WORK-YEAR BY 4 GIVING WS-C REMAINDER WS-D    
    IF WS-D NOT EQUAL 0                                 
    MOVE 28 TO WORK-DAY                                 
    ELSE                                                
    MOVE 29 TO WORK-DAY                                 
    END-IF                                              
    END-EVALUATE.  
    DISPLAY 'MODIFIED TEST-DATE: ' WORK-DATE                                     
    STOP RUN.                                           

This solution goes hand in hand with @NealB's answer.


The procedure "compute-month-end-date" does not require any checks for leap year or December.

   identification division.
   program-id. last-day.
   data division.
   working-storage section.
   1 test-date.
    88 test-1 value "20.01.1999".
    88 test-2 value "20.02.2004".
    88 test-3 value "20.12.2005".
     2 dd pic 99.
     2 pic x.
     2 mm pic 99.
     2 pic x.
     2 yyyy pic 9999.

   1 month-end-date binary pic 9(8) value 0.

   procedure division.
   begin.
       set test-1 to true
       perform run-test
       set test-2 to true
       perform run-test
       set test-3 to true
       perform run-test
       stop run
       .

   run-test.
       display test-date " to " with no advancing
       perform test-date-to-iso
       perform compute-month-end-date
       perform iso-to-test-date
       display test-date
       .

   compute-month-end-date.

       *> get date in following month
       compute month-end-date = function
           integer-of-date (month-end-date) + 32
           - function mod (month-end-date 100)
       compute month-end-date = function
           date-of-integer (month-end-date)

       *> get last day of target month
       compute month-end-date = function
           integer-of-date (month-end-date)
           - function mod (month-end-date 100)
       compute month-end-date = function
           date-of-integer (month-end-date)
       .

   test-date-to-iso.
       compute month-end-date = yyyy * 10000
           + mm * 100 + dd
       .

   iso-to-test-date.
       move month-end-date to dd
       .
   end program last-day.

Results:

20.01.1999 to 31.01.1999
20.02.2004 to 29.02.2004
20.12.2005 to 31.12.2005

While this might be a bit daunting to the novice COBOL programmer, there is a simple explanation. The procedure "compute-month-end-date" consists of two identical parts with the exception of the "+32".

Taking the second part first, it subtracts the day of month from the integer of a date giving the integer value for the 'zeroth' day of the month. This is precisely the integer value for the last day of the prior month. The following compute gives the date in 'yyyymmdd' format.

The first part does the same, except that it adds 32 to get a date in the following month, the 1st through the 4th, depending on the number of days in the original month.

Taken togther 19990120 is first changed to 19990201, then changed to 19990131. And 20040220 to 20040303, then 20040229. 20051220 to 20060101, then 20051231.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号