编辑 DATE 字段的部分以组成日期值

Editing portions of DATE field to compose a date value

当使用 RPGLE 的 %date() 函数时,我可以 "converte" 显示日期的字符串,例如 '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 个)不同的字段,而不是存储在定义为 'date' 的字段中:在日期部分,一个月份和 1 或 2(取决于数据库文件的年龄)年份字段为 4 位数字,或者一个字段为 2 位数字世纪,一个字段为 2 位数字年份(2019 -> 存储为“2019”或“20”和“19”)

一开始,我学会了将 3 个分区日期字段与数据结构分组,并为我的 DDSDSPF/PRTF)或 [=48= 使用覆盖 "date-subfield" ]. 我 "discovered" 我自己喜欢 DATE 字段,我可以使用 %date() BIF 将表示完整日期的数据结构子字段转换为我需要的日期字段。但出于某些原因,我不想为每个 "new" 日期创建一个新的数据结构。

就像使用 %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') 

我的"old"方式是这样的:

**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 时,我不得不为 FROM 日期、TO 日期和数据库中的日期编写一个 DS。好吧,我承认我可以像上面那样做,只需制作一个 DS 并将其用于三个日期。但我希望我可以定义一个日期字段并编写如下代码:

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

所以我不必每次都为日期转换构建一个 DS。

但是正如@jmarkmurphy 回答的那样,我现在想出了一个解决方案,即让一个 DS 具有 three/four 日期子字段和一个定义为 DATE 的覆盖子字段,因此我不必使用 %date()

您是在问如何在 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

没有允许您编辑日期、时间或时间戳字段的一部分的功能。但是正如您所说,您可以使用数据结构来做到这一点。鉴于您不想仅仅为了设置多个日期字段的日期值而创建多个数据结构,您可以使用这样的单个基于数据结构:

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;

我肯定会创建一组过程来从各个部分创建日期、时间或时间戳。要处理年份可能分为两部分的事实,请将第四个 "century" 参数定义为 OPTIONS(*NOPASS),如果未通过,该过程将期望年份部分包含所有四位数字。

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

如果您也不想创建一些过程,实际上有一种方法可以做到这一点而无需任何额外操作:

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

但那是一些讨厌的代码...