如何在AS400的CL程序中对输入DATE值进行有效性校验
AS/400 CL程序传入日期校验实现
CL本身没有原生的日期校验函数,最稳妥的方案是直接调用系统内置的日期检查命令,配合错误监控捕获异常,完全不需要自己手写大小月、闰年判断逻辑,能避免所有自定义逻辑的边界漏洞。
基础实现代码
假设传入的日期参数是最常用的8位字符格式YYYYMMDD,完整可直接复用的代码如下:
PGM PARM(&INPUT_DATE) /* 变量定义 */ DCL VAR(&INPUT_DATE) TYPE(*CHAR) LEN(8) /* 入参:传入的日期字符串 */ DCL VAR(&DATE_VALID) TYPE(*LGL) VALUE('1') /* 校验结果标记:1=合法 0=非法 */ DCL VAR(&ERR_MSGID) TYPE(*CHAR) LEN(7) /* 可选:存储错误ID用 */ /* 全局异常捕获,只要日期校验触发报错就跳转到非法处理分支 */ MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(DATE_INVALID)) /* 核心校验逻辑:调用系统日期检查命令 */ CHKDATE DATE(&INPUT_DATE) TYPE(*CYMD) /* 注意:TYPE参数必须和传入日期的格式匹配,常用对应关系: *MDY = MMDDYY 6位格式 *DMY = DDMMYY 6位格式 *YMD = YYMMDD 6位格式 *CYMD = YYYYMMDD 8位格式 *CDMY = DDMMYYYY 8位格式 *CMDY = MMDDYYYY 8位格式 */ /* 校验通过,直接进入主业务逻辑 */ GOTO CMDLBL(MAIN_LOGIC) DATE_INVALID: /* 日期非法分支:标记校验失败,可按需加错误提示、返回参数赋值等逻辑 */ CHGVAR VAR(&DATE_VALID) VALUE('0') /* 可选:读取具体错误信息,比如月份超出范围、日期超过当月天数、非闰年2月29日等 */ RCVMSG MSGTYPE(*EXCP) MSGID(&ERR_MSGID) MAIN_LOGIC: /* 后续业务逻辑通过&DATE_VALID判断日期是否合法即可 */ ENDPGM
兼容老版本系统的方案
如果你的OS/400版本较老没有CHKDATE命令,直接替换成CVTDAT日期转换命令即可,逻辑完全一致:非法日期会直接抛出CPF0550、CPF0551、CPF0552等异常,被上面的MONMSG捕获,不需要改其他逻辑。示例替换代码:
/* 用CVTDAT替代CHKDATE,尝试将传入日期转成作业默认日期格式,非法就抛错 */ DCL VAR(&TMP_DATE) TYPE(*CHAR) LEN(6) CVTDAT DATE(&INPUT_DATE) TOVAR(&TMP_DATE) FROMFMT(*CYMD) TOFMT(*JOB)
注意事项
- 不要手写日期判断逻辑:自己写大小月、闰年判断很容易漏规则,比如整百年份需要被400整除才是闰年(1900年、2100年都不是闰年),系统命令已经封装了所有官方日期规则,稳定性远高于自定义代码
- 如果传入的日期带分隔符(比如
YYYY-MM-DD、MM/DD/YYYY),先做一步字符串清洗,把分隔符删掉转成对应格式的纯数字字符串,再传入校验命令即可。比如处理横杠分隔的10位日期:
/* 把2024-05-20这种格式转成20240520的8位纯数字 */ CHGVAR VAR(&CLEAN_DATE) VALUE(%SST(&INPUT_DATE 1 4) *CAT %SST(&INPUT_DATE 6 2) *CAT %SST(&INPUT_DATE 9 2))
- 校验前不需要单独判断入参是不是纯数字,只要包含非数字字符,
CHKDATE/CVTDAT会直接抛错,归为非法日期即可。
内容的提问来源于stack exchange,提问作者Kunal Roy
相关产品推荐
相关产品推荐

