Wednesday, May 25, 2022

Start testing the new date rule

1970 rule window dates

Since the beginning of time on OS/400, the beloved ancestor of IBM i, six long dates have always used the "1940 rule" to determine the century.

If Year >= 40 then Century = 19
If Year < 40 then Century = 20

2039 is not that far in the future, only 17 years away, IBM has developed a replacement rule, "1970 rule".

If Year >= 70 then Century = 19
If Year < 70 then Century = 20

As part of the IBM i 7.5 announcement IBM has said that the new rule will be implemented in a future release or Technology Refresh.

IBM is giving a foretaste of the new rule in 7.5. I used the word "foretaste" as the "1940 rule" has not been replaced, but the new rule can be implemented on top of it, if you so desire. The rule can either be applied to your entire system, which I do NOT recommend, or it can be implemented just to the current job.

In 7.5 the "1970 rule" is implemented by an Environmental Variable: QIBM_QBASEYEAR

If you wanted to apply this to your entire partition, which is NOT what I recommend, you would use the following command:

ADDENVVAR ENVVAR(QIBM_QBASEYEAR) VALUE(1970) LEVEL(*SYS)

By all means you can delete the environment variable, but who knows what effects it will have on all of the jobs using your applications.

It is safer to just apply it to the current job:

ADDENVVAR ENVVAR(QIBM_QBASEYEAR) VALUE(1970) LEVEL(*JOB) REPLACE(*YES)

I then need to use the Change Job Command, CHGJOB, to apply the job's environmental variable to the job.

CHGJOB JOB(*) DATFMT(*MDY)

As I am in the USA I would use the Date Format of *MDY. If you use another date format, *DMY or *YMD, you would use that in this parameter.

I can check if the environmental variable has been added to the current job using the Work With Environmental Variables command, WRKENVVAR.

                      Work with Environment Vars (*JOB) 

Type options, press Enter.
  1=Add   2=Change   4=Remove   5=Display details   6=Print

Opt  Name                        Value
 _                          
 _   PASE_USRGRP_LIMITED         'N'
 _   QIBM_PASE_USE_PRESTART_J >  'Y'
 _   LANG                        '/QSYS.LIB/EN_US.LOCALE'
 _   ILE_DEBUGGER_1              'ALLOW_WIDE_SCREEN'
 _   QIBM_QBASEYEAR              '1970'

Alas, this screen does not show at which level the environmental variable has been applied. The only way I could see that was to use the "2", and I could see the level at the bottom of that screen.

There is another "change" that was explained in the announcement. For any command parameter that is defined as *DATE you can enter the date as either six long or eight long, which includes the century. I tested on all the partitions I have with different releases and found that I could use the eight long date in IBM i 7.3 and up.

Below is what I found running tests in one session that had the environmental variable and another did not.

The first tests I performed were with date parameters in commands.

First command with a date that came to minds is the Submit Job command, SBMJOB. If I use the Schedule Date parameter with the date of 01/01/40 in the job without the environmental variable I get the following:

SBMJOB CMD(CALL PGM(A)) SCDDATE(010140)

Specified date or time has passed.

The error message comes as no surprise as January 1, 1940 has passed.

I can submit the job with the eight long date:

SBMJOB CMD(CALL PGM(A)) SCDDATE(01012040)

And the job is successfully submitted.

In the job with the environmental variable when I use the six long date:

SBMJOB CMD(CALL PGM(A)) SCDDATE(010140)

The job is successful as the date this time has been interpreted as January 1, 2040. But you have to assume what I am telling you.

To show this with the actual dates I built my own command: MYCMD

01  CMD PROMPT('My command for dates')

02  PARM KWD(DATE) TYPE(*DATE) PROMPT(*DATE)

My command has only one parameter, a *DATE type. Below is the Command Processing Program, or CPP, for this command.

01  PGM        PARM(&DATE)

02  DCL        VAR(&DATE) TYPE(*CHAR) LEN(7)

03  DMPCLPGM

04  ENDPGM

Lines 1 and 2: The command passes one parameter to the CPP, the date. Which I have defined as a character variable. Why seven long? The date is passed from the command to the program in *CYMD format.

Line 3: I want to generate a program dump, within which will be value of the &DATE variable.

First time I ran my command was in the job was still using the "1940 rule".:

MYCMD DATE(010140)

Looking in the job log I can see that the date starts with "0", which indicates that the century is "19".

Variable               Type        Length         Value
                                                   *...+....1
&DATE                    *CHAR            7       '0400101'

When I use the eight long date with the command:

MYCMD DATE(01012040)

The dump shows that the century is "1", and the date is January 1, 2040.

Variable               Type        Length         Value
                                                   *...+....1
&DATE                    *CHAR            7       '1400101'

Another test with the "1940 rule", this time with the date of January 1,1969.

MYCMD DATE(010169)

This returns the century of "0", i.e. January 1, 1969:

Variable               Type        Length         Value
                                                   *...+...
&DATE                    *CHAR            7       '0690101'

Now into the job with the environmental variable, and the "1970 rule". Executing my command with the date 010140:

MYCMD DATE(010140)

With the "1970 rule" this is interpreted as January 1, 2040:

Variable               Type        Length         Value
                                                   *...+....1
&DATE                    *CHAR            7       '1400101'

I am not going to test 01012040 as it is obvious what the result for that will be.

Now for date 010169:

MYCMD DATE(010169)

The date has been interpreted as January 1, 2069.

Variable               Type        Length         Value
                                                   *...+...
&DATE                    *CHAR            7       '1690101'

What about in the common IBM i programming languages. IBM said they would still use the old rule, but I wanted to really make sure.

First up CL. I thought the best way to test converting six to eight long dates was to use the Convert Date command, CVTDAT:

01  DCL        VAR(&DATE1) TYPE(*CHAR) LEN(6) VALUE('010140')
02  DCL        VAR(&DATE2) TYPE(*CHAR) LEN(10)

03  CVTDAT     DATE(&DATE1) TOVAR(&DATE2) FROMFMT(*MDY) TOFMT(*ISO)

Line 1: The six long date that will be converted to *ISO, with date separator characters.

line 2: The converted date will be in this variable.

Line 3: The CVTDAT command.

No matter which job I ran it in the value returned in &DATE2 was '1940-01-01'.

I tried RPG next.

01  **free

02  dsply %date('010140':*mdy0) ;

03  *inlr = *on ;

Again it did not matter which job I ran it in the displayed value was:

DSPLY  1940-01-01

I have written before about SQL's date "windowing" and as far as I can tell this remains unchanged.

Go ahead test anything that uses a command with a date parameter in it. Until the "1970 rule" is applied to CL and RPG, and I would assume Cobol, there is, IMHO, only limited testing that could be performed. But I would like to thank IBM for giving us the feature so that we are aware of what the future will bring, and we can start testing what would need to change to implement a new rule.

 

You can learn more about the "1970 rule" environmental variable from the IBM website here.

 

This article was written for IBM i 7.5.

1 comment:

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.