Любая дата должна быть преобразована в дату конца месяца в коболе?

У меня есть требование, согласно которому любая дата (ДД.ММ.ГГГГ) должна быть преобразована в последнюю дату месяца (например, если дата 20.01.1999, то она должна быть преобразована в 31.01.1999)?


person sai    schedule 12.07.2011    source источник


Ответы (4)


С чем именно у вас проблемы? КОБОЛ или алгоритм? Я предполагаю, что это COBOL.

Я не собираюсь давать вам прямой ответ, потому что вы, очевидно, склоняетесь к языку, и есть смысл проработать конкретные детали для себя.

Вот несколько советов:

Определите поле даты в WORKING-STORAGE, чтобы вы могли выбрать день, месяц и год как отдельные элементы. Что-то типа:

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

Обратите внимание на безымянные поля PIC X. Они содержат разделители дня/месяца/года. Им не нужно давать имена данных, потому что вам не нужно ссылаться на них. Иногда этому типу элемента данных дается имя FILLER, но это имя необязательно.

Прочтите заявление EVALUATE. Вот ссылка на руководство IBM Enterprise COBOL. Это описание EVALUATE должно быть одинаковым во всех версиях COBOL.

MOVE интересующая дата TO TEST-DATE. Теперь вы можете ссылаться на год, месяц и день как на отдельные элементы: TEST-DAY, TEST-MONTH и TEST-YEAR.

Используйте EVALUATE для проверки месяца (TEST-MONTH). Если месяц 30-дневный, то MOVE от 30 до TEST-DAY. Сделайте то же самое для 31-дневного месяца. Февраль — особый случай из-за високосных лет. Как только вы определили, что это февраль, проверьте TEST-YEAR, чтобы определить, является ли это високосным годом, и MOVE 28 или 29 ДО TEST-DAY в зависимости от результатов теста.

Теперь TEST-DATE будет содержать искомую дату. MOVE туда, где это необходимо.

person NealB    schedule 12.07.2011

Вы можете использовать функцию integer-of-date, которая возвращает целочисленное значение, соответствующее любой дате. Предполагая, что ваша дата ввода находится в формате ддммгггг, и вы ожидаете, что вывод будет в том же формате. Допустим, дата 20011999, а вы хотите 31011999. Вы можете выполнить следующие шаги.

  • Увеличьте месяц входной даты на единицу. (20*02*1999)
  • Сделайте день равным 01 и используйте функцию integer-of-date (*01*021999)
  • вычесть единицу из возвращаемого целого числа.
  • используйте функцию date-of-integer, которая даст вам требуемый результат.

Обратите внимание, что здесь вам нужно будет добавить еще один чек для обработки декабрьского месяца.

person cobtech    schedule 09.08.2011

Ну вот! Запустите код здесь

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.                                           

Это решение идет рука об руку с ответом @NealB.

person Srinivasan JV    schedule 21.05.2018

Процедура «вычислить дату окончания месяца» не требует проверки високосного года или декабря.

   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.

Полученные результаты:

20.01.1999 to 31.01.1999
20.02.2004 to 29.02.2004
20.12.2005 to 31.12.2005

Хотя это может показаться немного пугающим для начинающего программиста на языке COBOL, этому есть простое объяснение. Процедура «вычислить-месяц-конец-даты» состоит из двух одинаковых частей, за исключением «+32».

Беря сначала вторую часть, он вычитает день месяца из целого числа даты, давая целочисленное значение для «нулевого» дня месяца. Это в точности целочисленное значение последнего дня предыдущего месяца. Следующее вычисление дает дату в формате «ггггммдд».

Первая часть делает то же самое, за исключением того, что добавляет 32, чтобы получить дату в следующем месяце, с 1-го по 4-й, в зависимости от количества дней в исходном месяце.

В совокупности 19990120 сначала заменяется на 19990201, а затем заменяется на 19990131. И 20040220 до 20040303, потом 20040229. 20051220 до 20060101, затем 20051231.

person Rick Smith    schedule 16.05.2018