Wednesday, May 27, 2020

Improvements to RPG's timestamps

improvements to rpg timestamp

Ever since timestamps were introduction to RPG I have always felt aggrieved that they never contained the entire timestamp. Timestamps have six decimal places following the seconds and only the first three positions, milliseconds, were filled. The last three positions were always zero. Occasionally I have found in timestamp fields in two records with same value. I would unable to determine which record is older, without using other fields or the file's relative record number.

The latest round of new Technology Refreshes, IBM i 7.4 TR2 and 7.3 TR8, brought improvements to the way RPG does timestamps.

Some of what I am going to describe here may have been available in earlier releases or TRs.

One of the things I learned from the documentation is that I can define timestamps of different lengths:

01  dcl-s WorkX timestamp ;
02  dcl-s Work0 timestamp(0) ;
03  dcl-s Work1 timestamp(1) ;
04  dcl-s Work3 timestamp(3) ;
05  dcl-s Work12 timestamp(12) ;

Line 1: I have always defined timestamps in my RPG programs this way, this is the timestamp with the six decimal places.

Lines 2 - 4: I did not know I could define timestamps with different number of decimal places.

Line 5: This is new with the latest TRs, a timestamp with 12 decimal places. I will describe how it is special below.

Let me move values from the timestamp built in function, %TIMESTAMP, to these variables:

06  WorkX = %timestamp() ;
07  Work0 = %timestamp() ;
08  Work1 = %timestamp() ;
09  Work3 = %timestamp() ;
10  Work12 = %timestamp(*unique) ;

Lines 6 - 9: These are basically the same, moving the value returned from the timestamp BIF to the different size timestamp variables.

Line 10: This is the line that is all new. The special value *UNIQUE has to be used to fill the 12 decimal places of Work12 I will explain the significance of those what is in the 12 places when we see the values returned when I debugged the program:

WORKX = '2020-05-20-20.58.42.998389'
WORK0 = '2020-05-20-20.58.42' 
WORK1 = '2020-05-20-20.58.42.9'
WORK3 = '2020-05-20-20.58.42.998'
WORK12 = '2020-05-20-20.58.42.998429000244'

The default timestamp variable, WORKX, now contains a timestamp to the full number of decimal places, microseconds. This was introduced in the latest TRs, and makes me a happy man.

The other variables, WORK0, WORK1, and WORK3, all have the expected number of decimal places.

I need to explain what is in the decimal places for WORK12. The first six numbers in the decimal, 988429, are the microseconds from the timestamp. The last six numbers, 000244, are a unique number generated to guarantee that this timestamp value is unique.

If I wanted to populate the "regular" timestamp variable, WorkX, with timestamps of differing lengths I would use the value *SYS as a parameter passed to the timestamp BIF followed by the number of decimal places I want. For example:

11  WorkX = %timestamp(*sys) ;
 
Debug: WORKX = '2020-05-20-21.02.46.706974'

As I did not give the number of decimal places the default, six, is given.

In the example below I want zero decimal places in my timestamp. The timestamp still has its six decimal places, but they are all zero.

12  WorkX = %timestamp(*sys:0) ;

Debug: WORKX = '2020-05-20-21.03.06.000000'

Below as I "asked" for only one decimal place I have only one in my variable.

13  WorkX = %timestamp(*sys:1) ;

Debug: WORKX = '2020-05-20-21.03.32.200000'

In the example below I want just the milliseconds, first three decimal places, in my timestamp variable.

14  WorkX = %timestamp(*sys:3) ;

Debug: WORKX = '2020-05-20-21.03.54.407000'

I am not going to give more examples as I am sure you get the idea.

If I wanted to calculate the difference between two timestamps that included the unique number I would want to exclude the unique part from the calculation. I can just use the first six decimal places:

i = %diff(%timestamp(TS2:6) :
          %timestamp(TS1:6) :
          *mseconds) ;

 

You can learn more about the changes to RPG's timestamp built in function from the IBM website here.

 

This article was written for IBM i 7.4 TR2 and 7.3 TR8.

10 comments:

  1. Be aware that if you compile a program using the %timestamp function on a system with the PTF that allows the new functionality installed and save and restore that program on a system without that PTF installed, the program will error. See the description for PTF SI73189.

    ReplyDelete
  2. With %timestamp(*unique) is it that the unique digit is always 000244?

    ReplyDelete
  3. I noticed that existing programs did not automatically populate 6 decimals once the PTF was installed. I had to recompile the program and then it worked.

    ReplyDelete
  4. What I've been doing is use a 3 digit counter and insert it into the microseconds portion of the timestamp. I code it like this...
    (sorry for not using fully free) :)


    D tsCurrent s z
    D DS inz
    D iMicro 10s 0 inz(-1)
    D @Micro 3s 0 overlay(iMicro:8)
    ...
    imicro += 1 ;
    tsCurrent = %timestamp() + %mseconds(@micro) ;

    ReplyDelete
  5. Anyone know if you can populate a timestamp with 12 milliseconds from SQL? I can't determine if it's possible or not.
    Thanks.

    ReplyDelete
    Replies
    1. Are you meaning you want 12 "milliseconds" rather than the standard 6?
      12.12.12.123456789012

      I don't think you can get a smaller time than milliseconds.
      12.12.12.123456

      Delete
  6. Does *unique mean unique within just that job? Or system wide? Other? Thanks.

    Ringer

    ReplyDelete
    Replies
    1. *UNIQUE is used within a program, and only applies to the timestamp variable within the program.

      Delete

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.