Редактирование частей поля DATE для составления значения даты - PullRequest
0 голосов
/ 07 марта 2019

При использовании функции %date() в RPGLE я могу "преобразовать" строку с отображением даты, например, '2019-01-01' через %date('2019-01-01':*ISO) или '20190202' через %date('20190202':*ISO0) в поле даты.

dcl-s dateISO date(*ISO);

dateISO = %date('2019-01-01':*ISO);
dsply dateISO;
dateISO = %date('20190202':*ISO0);
dsply dateISO;           

В моей текущей базе данных значения даты разбиты на 3 (иногда 4) разных поля, а не хранятся в полях, определенных как «дата»: включено для части дня, одно для месяца и 1 или 2 (зависит от возраста файла базы данных) поля для года в виде четырехзначного числа или одно для двухзначного века и одно для двухзначного года (2019 -> сохраняются как «2019» или «20» и «19»)

Вначале я собирался сгруппировать 3 зонированных поля даты со структурой данных и использовать наложенное «подполе даты» для моего DDS (DSPF/PRTF) или «работы с датами». Я «открыл» для себя красоту полей DATE и то, что я могу использовать %date() BIF для преобразования подполя структуры данных, которое представляет полную дату, в мое необходимое поле даты. Но по причинам, я не хочу создавать новую структуру данных для каждой «новой» даты.

Так же, как и использование %subdt() для извлечения частей DATE или TIMESTAMP, я надеялся, что смогу редактировать часть поля DATE.

Кто-нибудь знает, как это сделать?

Редактировать:

Для всех тех, кто думает, я хочу получить часть даты: НЕТ, я просто хочу отредактировать (как написано в заголовке) часть даты. Как у меня есть определение DDS PF, как это:

 A          R TESTPFR
 A
 A            T1NUMB         6S 0       TEXT('Some number')
 A            T1TEXT        10A         TEXT('Some text')
 A            T1DTDD         2S 0       TEXT('Day part')
 A            T1DTMM         2S 0       TEXT('Month part')
 A            T1DTYY         4S 0       TEXT('Year part') 

Мой "старый" способ был таким:

**free
ctl-opt decedit('0,') datedit(*dmy) dftactgrp(*no) option(*nodebugio:*srcstmt:*nounref);

dcl-f testpf disk; // Database File

dcl-ds dateDS qualified; // DS for "converting"
  date zoned(8) pos(1);
  day zoned(2) pos(1);
  month zoned(2) pos(3);
  year zoned(4) pos(5);
end-ds;
dcl-s dateISO date(*ISO); // Destination Date field
dcl-ds testpfrDS likerec(testpfr); // Record definition if the database file


read testpfr testpfrDS;
dow (not %eof(testpf));
  dateDS.day = testpfrDS.t1dtdd ; //t1dtdd is the day field
  dateDs.month = testpfrDS.t1dtmm; //t1dtdd is the month field
  dateDs.year = testpfrDS.t1dtyy; //t1dtdd is the year field

  dateISO = %date(dateDS.date:*EUR);
  dsply dateISO; // Work with the date

  read testpfr testpfrDS;
enddo;

*inlr = *on; 

Это означает, что мне приходилось определять структуру данных в каждой новой программе, помещать поля PF в подполя и преобразовывать наложенное подполе. В этом случае это не было слишком много накладных расходов. Но когда задействовал DSPF, когда использование вводило диапазон дат, мне пришлось написать DS для даты FROM, даты TO и даты из базы данных. Хорошо, я признаю, что мог бы сделать это как выше, просто сделать один DS и использовать это для трех дат. Но я надеялся, что смогу просто определить поле даты и код наподобие этого:

%subdt(dateISO:*day) = testpfrDS.t1dtdd;
%subdt(dateISO:*month) = testpfrDS.t1dtmm;
%subdt(dateISO:*year) = testpfrDS.t1dtyy; 

Так что мне не нужно каждый раз создавать DS для преобразования даты.

Но, как ответил @jmarkmurphy, теперь я нашел решение иметь DS с тремя / четырьмя подполями даты и одним перекрывающим подполем, который определен как DATE, поэтому мне не нужно использовать %date()

Ответы [ 3 ]

2 голосов
/ 07 марта 2019

Нет функции, позволяющей редактировать часть поля даты, времени или отметки времени. Но, как вы сказали, вы можете сделать это с помощью структуры данных. Учитывая, что вы не хотите создавать несколько структур данных только для того, чтобы установить значение дня для нескольких полей даты, вы можете использовать единственную структуру данных на основе, например:

dcl-ds DateIso    Qualified Based(%pDateIso);
  year            Signed(4:0) Pos(1);
  month           Signed(2:0) Pos(6);
  day             Signed(2:0) Pos(9);
end-ds;
dcl-s pDateIso    Pointer;

dcl-s startDate   Date(*iso);
dcl-s endDate     Date(*iso);

pDateIso = %addr(startDate);
DateIso.day = 1;

pDateIso = %addr(endDate);
pDateIso.month = 1;

Вы также можете использовать RPGIV для создания подпроцедуры, которая делает то, что вы хотите.

dcl-proc SetDateDay;
  dcl-pi *n Date(*iso);
    date    Date const;
    day     Int(5) const;
  end-pi

  dcl-ds *n;
    dateIso       Date(*iso);
    dateday       Signed(2:0) Pos(9);
  end-ds;

  dateIso = date;
  dateday = day;
  return dateIso;
end-proc;
1 голос
/ 08 марта 2019

Я бы определенно создал набор процедур для создания даты, времени или отметки времени из различных частей.Чтобы справиться с тем фактом, что год может состоять из двух частей, определите четвертый параметр "столетие" как OPTIONS (* NOPASS), и если он не пройден, процедура будет ожидать, что часть года будет иметь все четыре цифры.

date = makeDate(dd : mm : yy);
or
date = makeDate(dd : mm : yy: cc);

Если вы не хотите создавать несколько процедур, на самом деле есть способ сделать это без каких-либо дополнительных действий:

   date = %date(cc * 1000000 + yy * 10000 + mm * 100 + dd); // untested

Но это какой-то неприятный код ...

0 голосов
/ 07 марта 2019

Вы спрашиваете, как добавить или вычесть дни, месяцы, годы и т. Д. В поле даты RPG?Я думаю, что вы можете просмотреть список встроенных функций RPGLE здесь: https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rzasd/bifs.htm

Если вы нажмете, например,% DAYS, это приведет вас к примеру здесь: https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rzasd/bbmon.htm#bbmon__ebmonths

...