如何在 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 模块是最直接的方法。
我需要获取上个月的最后一天。所以这个 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 模块是最直接的方法。