Subtracting Date/Time AS400 V5R4

190 pts.
Tags:
RPG
RPG Date Formatting
RPGLE
V5R4
I am familiar with the subdur command. I have used it to get the # of days between 2 dates and the number of minutes between 2 times. How do I get the difference in minutes when the times fall on separate days. I guess I need to know how to calculate the interval between 2 times when the dates are different.

Software/Hardware used:
AS400 V5R4

Answer Wiki

Thanks. We'll let you know when a new response is added.

You might use SUBDUR consecutively to get a value for *DAYS, *HOURS and *MINUTES. The number of minutes is then ((Days*1440)+(Hours*60)+Minutes). You might need to do some testing to determine what happens if the difference is greater than a whole Month.

Alternatively, you can convert two timestamps to two NumberOfSeconds values with the <a href=”http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=/apis/CEESECS.htm”>Convert Timestamp to Number of Seconds (CEESECS) API</a>. The difference between the two values is the number of elapsed seconds. Divide by 60 to obtain Minutes.

I’d probably go with the CEESECS API. A pretty straightforward proc could be created for this.

Tom

Discuss This Question: 5  Replies

 
There was an error processing your information. Please try again later.
Thanks. We'll let you know when a new response is added.
Send me notifications when members answer or reply to this question.

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy
  • GHENDER
    Do you have an example of how to use this API? I looked at the link you included and I can see how to call it manually but I can't figure out how to write it in a CL program.
    190 pointsBadges:
    report
  • TomLiotta
    ...how to write it in a CL program. I apologize -- I assumed you meant RPG after you mentioned SUBDUR. Although the CEESECS API can be called successfully with ILE CL, the seconds value is only useful for passing into other APIs. If you need to do arithmetic operations on the value, you need to pass it to a language that can handle 8-byte floating point variables. RPG can do it. In case it's useful for you, here's a minimal RPG proc that subtracts a float-8 from another float-8 and returns a packed (15,3):
         H NoMain
    
         D SubFlt8         pr            15p 3 extproc( 'SUBFLT8' )
         D flt8_1                         8f   const
         D flt8_2                         8f   const
    
         p SubFlt8         b                   export
    
         D SubFlt8         pi            15p 3
         D flt8_1                         8f   const
         D flt8_2                         8f   const
    
         C                   return    ( flt8_1 - flt8_2 )
    
         p SubFlt8         e
    This ILE CL module calls that proc a few times in order to show a few hours, minutes and seconds differences between some different timestamps:
    pgm    ( +
           )
    
       dcl   &FirstDate     *char       26     value( '2010-08-04-14.20.29.073376' )
       dcl   &SecndDate     *char       26     value( '2010-08-04-16.46.04.073376' )
       dcl   &ThirdDate     *char       26     value( '2010-08-05-14.20.29.073376' )
       dcl   &ForthDate     *char       26     value( '2010-08-05-16.40.29.073376' )
       dcl   &FifthDate     *char       11     value( 'Aug 05 2010' )
    
       dcl   &NowDate       *char       26     value( '2010-08-05-16.46.04.073376' )
    
       dcl   &PicStr        *char       26     value( 'YYYY-MM-DD-HH.MI.SS.999999' )
    
       dcl   &RtnVal1       *char        8
       dcl   &RtnVal2       *char        8
    
       dcl   &NbrSecs       *dec      ( 15 3 ) value( 0 )
       dcl   &NbrMins       *dec      ( 15 3 ) value( 0 )
       dcl   &NbrHrs        *dec      ( 15 3 ) value( 0 )
    
    
       callprc      CEESECS      ( +
                                   &NowDate       +
                                   &PicStr        +
                                   &RtnVal1       +
                                   *omit          +
                                 )
    
    
       callprc      CEESECS      ( +
                                   &FirstDate     +
                                   &PicStr        +
                                   &RtnVal2       +
                                   *omit          +
                                 )
    
       callprc      SUBFLT8      ( +
                                   &RtnVal1       +
                                   &RtnVal2       +
                                 ) +
                           rtnval( &NbrSecs )
    
       chgvar       &NbrMins     ( &NbrSecs / 60 )
       chgvar       &NbrHrs      ( &NbrSecs / ( 60 * 60 ) )
    
    dmpclpgm
    
       callprc      CEESECS      ( +
                                   &SecndDate     +
                                   &PicStr        +
                                   &RtnVal2       +
                                   *omit          +
                                 )
    
       callprc      SUBFLT8      ( +
                                   &RtnVal1       +
                                   &RtnVal2       +
                                 ) +
                           rtnval( &NbrSecs )
    
       chgvar       &NbrMins     ( &NbrSecs / 60 )
       chgvar       &NbrHrs      ( &NbrSecs / ( 60 * 60 ) )
    
    dmpclpgm
    
       callprc      CEESECS      ( +
                                   &ThirdDate     +
                                   &PicStr        +
                                   &RtnVal2       +
                                   *omit          +
                                 )
    
       callprc      SUBFLT8      ( +
                                   &RtnVal1       +
                                   &RtnVal2       +
                                 ) +
                           rtnval( &NbrSecs )
    
       chgvar       &NbrMins     ( &NbrSecs / 60 )
       chgvar       &NbrHrs      ( &NbrSecs / ( 60 * 60 ) )
    
    dmpclpgm
    
       callprc      CEESECS      ( +
                                   &ForthDate     +
                                   &PicStr        +
                                   &RtnVal2       +
                                   *omit          +
                                 )
    
       callprc      SUBFLT8      ( +
                                   &RtnVal1       +
                                   &RtnVal2       +
                                 ) +
                           rtnval( &NbrSecs )
    
       chgvar       &NbrMins     ( &NbrSecs / 60 )
       chgvar       &NbrHrs      ( &NbrSecs / ( 60 * 60 ) )
    
    dmpclpgm
    
       callprc      CEESECS      ( +
                                   &FifthDate     +
                                   'Mmm DD YYYY'  +
                                   &RtnVal2       +
                                   *omit          +
                                 )
    
       callprc      SUBFLT8      ( +
                                   &RtnVal1       +
                                   &RtnVal2       +
                                 ) +
                           rtnval( &NbrSecs )
    
       chgvar       &NbrMins     ( &NbrSecs / 60 )
       chgvar       &NbrHrs      ( &NbrSecs / ( 60 * 60 ) )
    
    dmpclpgm
    
       return
    
    endpgm
    There are five different date/time values at the top, followed by a &NowDate value. Each of the first five date/times are subtracted from &NowDate in turn. The resulting hours/minutes/seconds are shown in the dumps that happen after each round. You'll quickly see the &FifthDate is very different from all of the others. Some of this code comes from a basic test procedure that I had handy. It was using a date/time value that was formatted as a timestamp, so the "picture string" variable was set up for a timestamp. I duplicated the values and made minor changes in order to show how the number of seconds between each date and &NowDate really did come out correct. But I put &FifthDate into this example to show how date/time string values can be described through the "picture string" variable value. As I said earlier, there is a lot of flexibility. For this one, I used a constant picture string and I let the time portion go as a default. The dumps will show enough to figure out what the defaults are. Note that instead of using a constant for the &NowDate value, I could have simply retrieved the QDATETIME system value and created an appropriate picture string as the program ran. Sorry about not thinking of CL at the start. I just didn't see a mention of it. Otherwise I might not have said anything. Tom
    125,585 pointsBadges:
    report
  • TomLiotta
    I recalled seeing a way to handle Float8 values in ILE CL, but didn't have reference handy at the time I posted the earlier example. I did a search last night and ran across an article by former IBMer Bruce Vining who demonstrated using the _LBCPYNV builtin API. The builtin isn't fully described in the article, but the usage may be enough to compare against the documentation to learn most ways to use it. New questions can be asked if necessary. Here it's used to convert the Float8 into a *DEC (15 0) without first creating an additional external proc in a different language. This allows everything to be done in ILE CL. The CL below does what the previous one does in terms of results. It uses the same 'current' timestamp value and the same five sample past dates. The decimal seconds value has been slightly changed to make it an integer value, to accommodate the straight conversion. The 'number of seconds' value is going to be an integer value anyway. The CEESECS and _LBCPYNV APIs might be put into a proc that accepts a date or two, and possibly a format (or two), and returns a difference.
    pgm    ( +
           )
    
       dcl   &FirstDate     *char       26     value( '2010-08-04-14.20.29.073376' )
       dcl   &SecndDate     *char       26     value( '2010-08-04-16.46.04.073376' )
       dcl   &ThirdDate     *char       26     value( '2010-08-05-14.20.29.073376' )
       dcl   &ForthDate     *char       26     value( '2010-08-05-16.40.29.073376' )
       dcl   &FifthDate     *char       11     value( 'Aug 05 2010' )
    
       dcl   &NowDate       *char       26     value( '2010-08-05-16.46.04.073376' )
    
       dcl   &PicStr        *char       26     value( 'YYYY-MM-DD-HH.MI.SS.999999' )
    
       dcl   &RtnVal1       *char        8
       dcl   &RtnVal2       *char        8
    
       dcl   &NowSecs       *dec      ( 15 0 ) value( 0 )
       dcl   &PastSecs      *dec      ( 15 0 ) value( 0 )
    
       dcl   &NbrSecs       *dec      ( 15 0 ) value( 0 )
       dcl   &NbrMins       *dec      ( 15 3 ) value( 0 )
       dcl   &NbrHrs        *dec      ( 15 3 ) value( 0 )
    
       dcl   &Flt_Dfn       *char        7     value( x'01000800000000' )
       dcl   &Dec_Dfn       *char        7     value( x'03000F00000000' )
    
    
    /* Get NumberOfSeconds for our "Now" date to use later... */
       callprc      CEESECS      ( +
                                   &NowDate       +
                                   &PicStr        +
                                   &RtnVal1       +
                                   *omit          +
                                 )
    
    /* ...and turn Float8 into *DEC (15 0)... */
       callprc      '_LBCPYNV'   ( +
                                   &NowSecs       +
                                   &Dec_Dfn       +
                                   &RtnVal1       +
                                   &Flt_Dfn       +
                                 )
    
    /* Get NumberOfSeconds for our First test date... */
       callprc      CEESECS      ( +
                                   &FirstDate     +
                                   &PicStr        +
                                   &RtnVal2       +
                                   *omit          +
                                 )
       callprc      '_LBCPYNV'   ( +
                                   &PastSecs      +
                                   &Dec_Dfn       +
                                   &RtnVal2       +
                                   &Flt_Dfn       +
                                 )
    
    /* Get difference between "Now" and our first past date... */
       chgvar       &NbrSecs     ( &NowSecs - &PastSecs )
    
    /* ...and also convert to both minutes and hours... */
       chgvar       &NbrMins     ( &NbrSecs / 60 )
       chgvar       &NbrHrs      ( &NbrSecs / ( 60 * 60 ) )
    
    dmpclpgm
    
    /* Get NumberOfSeconds for our Second test date... */
       callprc      CEESECS      ( +
                                   &SecndDate     +
                                   &PicStr        +
                                   &RtnVal2       +
                                   *omit          +
                                 )
       callprc      '_LBCPYNV'   ( +
                                   &PastSecs      +
                                   &Dec_Dfn       +
                                   &RtnVal2       +
                                   &Flt_Dfn       +
                                 )
    
    /* Get difference between "Now" and our second past date... */
       chgvar       &NbrSecs     ( &NowSecs - &PastSecs )
    
       chgvar       &NbrMins     ( &NbrSecs / 60 )
       chgvar       &NbrHrs      ( &NbrSecs / ( 60 * 60 ) )
    
    dmpclpgm
    
    /* Get NumberOfSeconds for our Third test date... */
       callprc      CEESECS      ( +
                                   &ThirdDate     +
                                   &PicStr        +
                                   &RtnVal2       +
                                   *omit          +
                                 )
       callprc      '_LBCPYNV'   ( +
                                   &PastSecs      +
                                   &Dec_Dfn       +
                                   &RtnVal2       +
                                   &Flt_Dfn       +
                                 )
    
    /* Get difference between "Now" and our third past date... */
       chgvar       &NbrSecs     ( &NowSecs - &PastSecs )
    
       chgvar       &NbrMins     ( &NbrSecs / 60 )
       chgvar       &NbrHrs      ( &NbrSecs / ( 60 * 60 ) )
    
    dmpclpgm
    
    /* Get NumberOfSeconds for our Fourth test date... */
       callprc      CEESECS      ( +
                                   &ForthDate     +
                                   &PicStr        +
                                   &RtnVal2       +
                                   *omit          +
                                 )
       callprc      '_LBCPYNV'   ( +
                                   &PastSecs      +
                                   &Dec_Dfn       +
                                   &RtnVal2       +
                                   &Flt_Dfn       +
                                 )
    
    /* Get difference between "Now" and our fourth past date... */
       chgvar       &NbrSecs     ( &NowSecs - &PastSecs )
    
       chgvar       &NbrMins     ( &NbrSecs / 60 )
       chgvar       &NbrHrs      ( &NbrSecs / ( 60 * 60 ) )
    
    dmpclpgm
    
    /* Get NumberOfSeconds for our Fifth test date... */
       callprc      CEESECS      ( +
                                   &FifthDate     +
                                   'Mmm DD YYYY'  +
                                   &RtnVal2       +
                                   *omit          +
                                 )
       callprc      '_LBCPYNV'   ( +
                                   &PastSecs      +
                                   &Dec_Dfn       +
                                   &RtnVal2       +
                                   &Flt_Dfn       +
                                 )
    
    /* Get difference between "Now" and our fifth past date... */
       chgvar       &NbrSecs     ( &NowSecs - &PastSecs )
    
       chgvar       &NbrMins     ( &NbrSecs / 60 )
       chgvar       &NbrHrs      ( &NbrSecs / ( 60 * 60 ) )
    
    dmpclpgm
    
       return
    
    endpgm
    In its simplest form, compile it as a module named SUBDURHMS and create the program as:
    CRTPGM PGM( SUBDURHMS )
           BNDDIR(QC2LE)
    Name it however you choose and specify other parms as desired. Tom
    125,585 pointsBadges:
    report
  • Eric Witham
    There is a built in function that you can use called %DIFF d DiffInDays s 4s 0 inz d DiffInHours s 4s 0 inz d DiffInMonths s 4s 0 inz d DiffInYears s 4s 0 inz d FromDateInISO s d inz d ToDateInISO s d inz eval DiffInDays = %Diff(FromDateInISO:ToDateInISO:*DAYS) eval DiffInMonths = %Diff(FromDateInISO:ToDateInISO:*MONTHS) eval DiffInYears = %Diff(FromDateInISO:ToDateInISO:*YEARS) You would probably have to do some funky calculations, but this built in function works pretty nicely. You can also use it with timestamps also. The IBM WebSphere Development Studio ILE RPG Language Reference Version 5 manual (SC09-2508-06) has this built in function on PDF page 525 and 526. The URL to that manual is: http://publib.boulder.ibm.com/infocenter/iseries/v5r4/topic/books/sc092508.pdf Hope this helps!
    690 pointsBadges:
    report
  • TomLiotta
    There is a built in function that you can use called %DIFF In ILE RPG, that is correct. A couple points in the manual can tend to be misleading, but it's a very useful %bif:
         H Debug
         D TstNum          s              7  0 inz( 0 )
    
         D t1              s               z   inz( *sys )
         D t2              s               z   inz( *sys )
    
         C                   seton                                        LR
    
         c                   eval      t2 -= %days( 2 )
         c                   eval      t2 -= %minutes( 10 )
         c                   eval      TstNum = %diff( t1 : t2 : *minutes )
    
         C                   dump
    The two timestamp fields are both initialized to the system date. Then two days are subtracted from t2 and 10 minutes are also subtracted from t2. That should make the total difference between the two timestamps as being 2 days and 10 minutes. The result of the %diff() is 2890 minutes. With 1440 minutes in a day, it's right on. Tom
    125,585 pointsBadges:
    report

Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to:

To follow this tag...

There was an error processing your information. Please try again later.

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy

Thanks! We'll email you when relevant content is added and updated.

Following