如何在 CL 中获取月份的最后一天

How to get the last day of month in a CL

我需要获取上个月的最后一天。所以这个 CL 可以在新月的第 3 天 运行。 我可以在 CL 中做一个 Select 语句吗(我们在 7.1 中)

或者,如果不是,需要哪些步骤来编码并将此日期保存在一个小 table 中。

CL 实际上不支持日期数据类型。所以它不支持像 SQL 或 RPGLE 那样的日期算法。

如果您只需要确保某项工作在每月 3 日 运行 完成,为什么不使用工作调度程序呢?基本作业调度程序包含在 OS 中,或者您可能有 Advance Job Scheduler (AJS)。

对于基本作业调度程序:

ADDJOBSCDE JOB(MTH3RDDAY) CMD(CALL PGM(MYPGM)) FRQ(*MONTHLY) 
   SCDDATE(110315) SCDTIME('08:00')  

FRQ(*MONTHLY) SCDDATE(110315) 是每个月 3 日重复工作的关键。

如果您选择继续让 CL 确定它是否应该运行;我会建议一个 RPGLE 程序,它只是 return 是一个月中的某一天。这样 return 值就是一个简单的整数,您的 CL 不必尝试从日期的字符或数字表示中解析日期。

如果您需要有关该程序的帮助,post一个新问题并将其标记为 RPGLE。

下面是一个使用 CL 计算上个月最后一天的简单示例。

PGM                                                                       

DCL        VAR(&CYMD) TYPE(*CHAR) LEN(7)                                  
DCL        VAR(&JUL) TYPE(*CHAR) LEN(5)                                   
DCL        VAR(&JUL#) TYPE(*DEC) LEN(5)                                   

RTVJOBA    CYMDDATE(&CYMD)                                                
CHGVAR     VAR(%SST(&CYMD 6 2)) VALUE('01')                               
CVTDAT     DATE(&CYMD) TOVAR(&JUL) FROMFMT(*CYMD) TOFMT(*JUL) TOSEP(*NONE)                                     
CHGVAR     VAR(&JUL#) VALUE(&JUL)                                         
CHGVAR     VAR(&JUL#) VALUE(&JUL# - 1)                                    
CHGVAR     VAR(&JUL) VALUE(&JUL#)                                         
CVTDAT     DATE(&JUL) TOVAR(&CYMD) FROMFMT(*JUL) TOFMT(*CYMD) TOSEP(*NONE)

ENDPGM

从技术上讲,可以在 CL 中执行 SELECT;但它需要对 SQL CLI API 进行编码才能完成。不适合没有经验的人,不值得付出努力。不过,CL 可以 运行 INSERT 或 UPDATE 语句,然后使用 RCVF 检索插入的值。调用用 RPG、COBOL 或 C 编写的模块来执行 SQL 要容易得多。如果这些语言看起来遥不可及,那么 REXX 可以轻松地执行 SQL 并将值传递给 CL。

没有 SQL,日期数学似乎是最好的。如果你想通过 CL 当月的 "last day",最简单的方法可能是设置为下个月的第一天并减去“1 天”。下面显示了一个使用一对 CEE* Date and TIME APIs:

的例子
pgm

   dcl   &fromDate1     *char        6
   dcl   &fromDate2     *char        8
   dcl   &resultDate    *char        8

   dcl   &qyear         *char        2
   dcl   &qmonth        *char        2


   dcl   &rtnVal1       *int
   dcl   &rtnVal2       *int
   dcl   &picStr1       *char        6   value( 'YYMMDD' )
   dcl   &picStr2       *char        8   value( 'YYYYMMDD' )


   rtvsysval   sysval( QYEAR ) rtnvar( &qyear )
   rtvsysval   sysval( QMONTH ) rtnvar( &qmonth )

/* Set to a day near month-end... */
   chgvar      &fromDate1   ( &qyear *cat &qmonth *cat '28' )

   callprc      CEEDAYS      ( +
                               &fromDate1     +
                               &picStr1       +
                               &rtnVal1       +
                               *omit          +
                             )

/* Add enough days to guarantee in "next month"... */
   chgvar             &rtnVal2        ( &rtnVal1 + 4 )

   callprc      CEEDATE      ( +
                               &rtnVal2       +
                               &picStr2       +
                               &fromDate2     +
                               *omit          +
                             )

/* Set to 1st day of next month... */
   chgvar %sst( &fromDate2 7 2 )     '01'

   callprc      CEEDAYS      ( +
                               &fromDate2     +
                               &picStr2       +
                               &rtnVal1       +
                               *omit          +
                             )

/* Subtract 1 day to get to "last day"... */
   chgvar             &rtnVal2        ( &rtnVal1 - 1 )

   callprc      CEEDATE      ( +
                               &rtnVal2       +
                               &picStr2       +
                               &resultDate    +
                               *omit          +
                             )

/* Dump to show &resultDate is last-day of this month... */
dmpclpgm

   return

endpgm

它首先将日期设置为当月的 28 日,然后添加 4 天。使用这些值可确保第一个计算日期始终在 "next month" 内。然后它采用该日期并将日期编号设置为“01”。从中减去“1 天”。

这两个 API 与称为 "Lilian day" 的表示一起工作。这只是自 1582 年 10 月 14 日以来的天数的整数值。日期可以转换为 Lilian 天数,然后简单的整数数学可以加或减,但需要多少天。生成的整数可以转换回日期值。

您可以指定一个 'picture string' 来描述输入和输出日期的日期格式。我对初始输入使用 6 字符格式,但对输出使用 8 字符格式。您可以根据需要修改格式。最后,它只是 运行s DMPCLPGM 来显示结果。您可以设置一个 PARM() 变量来 return 任何调用它的结果。

示例代码中的结果是当月的最后一天。稍微改变一下,它可以很容易地简化为 return 下个月的第 3 天。

我考虑过在 SYSIBM.SYSDUMMY1 上创建一个 VIEW 来表达 LAST_DAY();但是虽然 VIEW 在 SELECT 语句中运行良好,但它在 i 6.1 中使 RUNQRY 崩溃。尝试让它与 CL 的 RCVF 一起工作似乎不值得。

我还测试了在月末添加 运行 的虚拟作业调度程序条目。然后我使用适当的 API 从条目中检索 NextSubmissionDate。这工作得很好,但太晦涩难懂,不是一个好的解决方案。当然,如果整个目的是安排一个作业,那么简单地为它添加一个调度程序条目可能就是应该做的。检索 NextSubmissionDate 只是一种将 LastDayOfMonth 加入任何 CL 程序的方法。

但如果那是目的,简单地有一个计算最后一天的 CL 模块是最直接的方法。