When using RPGLE's %date()
function I can "converte" a string displaying a date like '2019-01-01'
via %date('2019-01-01':*ISO)
or '20190202'
via %date('20190202':*ISO0)
into a date field.
dcl-s dateISO date(*ISO);
dateISO = %date('2019-01-01':*ISO);
dsply dateISO;
dateISO = %date('20190202':*ISO0);
dsply dateISO;
On my current database date values are split up into 3 (sometimes 4) different fields rather than stored in fields defined as 'date': On for the day part, one for the month and 1 or 2 (depends on the age of the database file) fields for either the year as 4 digit or one field for the 2 digit century and one for the 2 digit year (2019 -> stored as '2019' or '20' and '19')
In my beginning, I leard to group the 3 zoned date fields with a data structure and use the overlaying "date-subfield" for my DDS
(DSPF/PRTF
) or "working with dates".
I "discovered" for myself the beauty of DATE fields and that I can use the %date()
BIF to convert the data structure subfield, which represents the full date, to my needed date field. But for reasons, I don't want to create a new data structure for each "new" date.
So like using %subdt()
for extracting portions of a DATE or TIMESTAMP I hoped that I can edit a portion of a DATE field.
Does anyone know how to do it?
Edit:
To all those who thougt I want to GET a portion of a date: NO, I just want to EDIT (as written in the headline) a portion of the date. Like I have a DDS PF definition like this:
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')
My "old" way was like this:
**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;
This ment that I had to define a data structure in each new program, put the PF fields into the subfields and convert the overlaying subfield. In this case this was not that much overhead. But when having DSPF involved where the use input a range of date, I had to write a DS for the FROM date, the TO date and the date from the database. Ok I admit that I could make it like above, just make one DS and use this for the three dates. But my hope was that I can just define a date field and code someting like this:
%subdt(dateISO:*day) = testpfrDS.t1dtdd;
%subdt(dateISO:*month) = testpfrDS.t1dtmm;
%subdt(dateISO:*year) = testpfrDS.t1dtyy;
So I don't have to built a DS for the date conversion every time.
But as @jmarkmurphy answered, I now came up with the solution of having a DS with the three/four date subfields and one overlaying subfield which is defined as DATE, so I dnon't have to use %date()
There is no function that allows you to edit a portion of a date, time or timestamp field. But as you said, you can do so with a data structure. Given that you don't want to create multiple data structures just for the purpose of setting the day value of multiple date fields, you could use a single Based data structure like this:
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;
You could also leverage RPGIV to create a sub-procedure that does what you want.
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;