COBOL DATATYPE CONVERSION: Конвертировать дату в DDMMYY в упакованный десятичный код из 3 байтов

У меня есть требование, где я хочу переместить дату (DDMMYY) в числовом формате в упакованный десятичный / comp-3 из 3 байтов. дата должна быть перемещена в файл, где для нее выделено только 3 символа / байта. Это то, что я пытался.

 03  WD-DDMMYY-DT-NUMERIC         PIC 9(06).      
 03  WD-DDMMYY-DT-COMP3           PIC S9(06) COMP-3.
 03  WD-DDMMYY-REDF  REDEFINES WD-DDMMYY-DT-COMP3.
     05  WD-3CHARS-DT-COMP3       PIC X(03).      
     05  FILLER                   PIC X(01).    


Move WD-DDMMYY-DT-NUMERIC         to  WD-DDMMYY-DT-COMP3  
Move WD-3CHARS-DT-COMP3           to  file-variable -->  X(03)         

Я не получаю желаемое значение в выводе. как это можно сделать?

3 ответа

Ответ посчетам правильный, но я постараюсь дать более наглядный ответ, используя дату 150131 (31 января 2015 г.)

если вы объявите поле как

  05  WD-DDMMYY-DT-NUMERIC             PIC 9(06) comp-3.  

затем 150131 сохраняется в WD-DDMMYY-DT-NUMERIC как x'01 50 13 1c', который занимает 4 байта. Но если вы объявите поле как

  05  WD-DDMMYY-DT-NUMERIC             PIC 9(06)V9 comp-3.  
  05  FILLER    REDEFINES      WD-DDMMYY-DT-PD.
      10  WD-BCD                       PIC X(03).

затем 150131 сохраняется в WD-DDMMYY-DT-NUMERIC как x'15 01 31 0c', который снова занимает 4 байта, но WD-BCD содержит x'15 01 31', который содержит всю дату, и имеет длину 3 байта

Вы также захотите "распаковать" вашу дату позже в другой программе, поэтому используйте REDEFINES, а не группу с подчиненным упакованным десятичным числом:

       05  WD-DDMMYY-DT-NUMERIC             PIC 9(06).      
       05  WD-DDMMYY-DT-PD PACKED-DECIMAL   PIC 9(06)V9
                                              VALUE ZERO.
       05  FILLER 
             REDEFINES
               WD-DDMMYY-DT-PD.
           10  WD-BCD                       PIC X(03).
           10  FILLER                       PIC X.

       MOVE WD-DDMMYY-DT-NUMERIC     TO WD-DDMMYY-DT-PD
       MOVE WD-BCD                   TO wherever-you-want

Полубайт младшего разряда (nybble) поля упакованного десятичного числа указывает операционный знак (C для положительного, D для отрицательного, F для без операционного знака, рассматриваемый как положительный - есть также некоторые Непреференциальные знаки, A, Б, д).

Для части цифр упакованного десятичного числа одна цифра занимает один кусочек.

Для упакованного десятичного числа любое заданное число байтов позволит точно соответствовать нечетному числу цифр. Четному количеству цифр всегда должен предшествовать ноль (вам не стоит об этом беспокоиться, компилятор сделает это за вас).

Чтобы получить шесть десятичных цифр, "упакованных" в три байта, вы должны игнорировать знак (помня, что nybble используется даже для поля без знака). Этот результат является соглашением, которое называется Binary Coded Decimal (BCD). COBOL не имеет встроенной поддержки BCD, поэтому вам придется кодировать. Но не много.

Чтобы убрать знак с дороги, вам нужно сдвинуть цифры влево на один клочок, оставив знак там, где он есть. Оставить знак в покое не проблема, COBOL сделает это за вас. Сдвиг влево подобен умножению на степень 10. Чтобы сдвинуть влево, умножьте на 10.

Тем не менее, существует более точный способ организовать сдвиг, который состоит в том, чтобы определить упакованное десятичное поле, чтобы иметь одно десятичное место (V9). Когда ваша дата, очевидно, целое число, перемещается в это поле, десятичная часть будет равна нулю (одна цифра), а дата даты будет предшествовать нулю.

Стоит отметить, что в IBM Enterprise COBOL V5 любое умножение или деление на степень 10 фактически реализуется как соответствующий сдвиг.

Это будет означать, что код, сгенерированный компилятором V5, будет очень похож на MULTIPLY на 10 и MOVE на поле с одним десятичным знаком. Возможно идентично (я не могу проверить).

Чтобы "распаковать" дату:

       05  WD-DDMMYY-DT-NUMERIC             PIC 9(06).      
       05  WD-DDMMYY-DT-PD PACKED-DECIMAL   PIC 9(06)V9
                                              VALUE ZERO.
       05  FILLER 
             REDEFINES
               WD-DDMMYY-DT-PD.
           10  WD-BCD                       PIC X(03).
           10  FILLER                       PIC X.

       MOVE wherever-you-want        TO WD-BCD
       MOVE WD-DDMMYY-DT-PD          TO WD-DDMMYY-DT-NUMERIC

Обратите внимание на ЗНАЧЕНИЕ ЗНАЧЕНИЯ в этом определении. Так работает Enterprise COBOL (в любом случае, до V4.2), в действительности это не нужно, но это документально для программиста. Байт младшего разряда (четвертый) никогда не изменяется от своего начального значения, то есть он всегда содержит X'0F'. Компилятор на самом деле "закорачивает" это, потому что он все равно заставит вывод быть неподписанным, поэтому ему не нужен знак из поля источника.

01 WORKING-VARIABLES.
 03  WD-DDMMYY-DT-NUMERIC         PIC 9(06).      
 03  WD-3CHARS-DT-COMP3-X.
     05 WD-DDMMYY-DT-COMP3        PIC 9(08) COMP-3.
 03  FILLER REDEFINES WD-3CHARS-DT-COMP3-X.
     05 FILLER                    PIC X(01).
     05 WD-3CHARS-DT-COMP3        PIC X(03).


MOVE 311216                     TO WD-DDMMYY-DT-NUMERIC.
MULTIPLY WD-DDMMYY-DT-NUMERIC
  BY 10                     GIVING WD-DDMMYY-DT-COMP3.
Move WD-3CHARS-DT-COMP3         to FILE-O-FIELD.

должен решить вашу проблему.

Другие вопросы по тегам