RPG and Dates

Date manipulation in RPG

RPG & SQL Date Operations

RPG can be used to manipulate dates, in various formats. With the inclusion of Built-In-Functions, calculating the day of the week, (1 for Monday) can be managed in just one line of code by using BIFs %REM AND %DIFF. (Note the example below.) Dates can easily be manuiplated adding or subtracting using %MONTHS and %DAYS, even %YEARS. Embedded SQL can add another avenue of date calculations to an RPG program.

In the sample code below the line of code, EXEC SQL SET :DIFFDATE = :DATE1 - :DATE2 returns the result to a data structure. Unlike the RPG date difference calculations, the SQL date manipulation returns the difference in days, months, and years. SQL also has a date fuction, DAYOFWEEK which will return the day of the week as a number (1,2,3, etc.).

       Ctl-Opt Option( *NoDebugIO : *SrcStmt ) DftActGrp( *No )                                     
               ActGrp( 'DATE1' ) PgmInfo( *PCML : *Module )                                         
               Main(Main) BNDDIR('QC2LE':'SC0000_BD') ;                                                                      
                                                                                                    
       Dcl-Pr CEETREC              extproc('CEETREC');                                              
          rc         Int(10) const options(*omit)    ;                                              
          user_rc    Int(10) const options(*omit)    ;                                              
       End-Pr;                                                                                      
 
       Dcl-DS *n                      ;                                                             
         DiffDate        zoned(8:0)     ;                                                           
           DiffYears     zoned(4:0) overlay(DiffDate) ;                                             
           DiffMonths    zoned(2:0) overlay(DiffDate: *Next) ;                                      
           DiffDays      zoned(2:0) overlay(DiffDate: *Next) ;                                      
       END-DS;                                                                                      
                                                                                                                                                                                                       
       Dcl-S Today         zoned(8:0)      ;                                                        
       Dcl-S NbrofDays     packed(9:0)     ;                                                        
       Dcl-S NumDays       packed(9:0)     ;                                                        
       Dcl-S weekDay       int(10)         ;                                                        
       Dcl-S weekDay7      int(10)         ;                                                        
       Dcl-S dayOfWeek     int(10)         ;                                                        
       Dcl-S dayOfWeek2    int(10)         ;                                                        
       Dcl-S dayOfYear     int(10)         ;                                                        
       Dcl-S dateChar      char(10)        ;                                                        
       Dcl-S dayName       char(12)        ;                                                        
       Dcl-S Date1         date            inz(d'2018-11-08') ;                                     
       Dcl-S Date2         date            inz(*sys)          ;                                     
       Dcl-S DtTmStamp     timeStamp       inz(*SYS)          ;                                                                                          
       Dcl-S firstDate     date            ;                                                        
       Dcl-S lastDate      date            ;                                                        
       Dcl-S baseDate      date            inz(*job) ;                                              
       Dcl-S daysIn        zoned(2:0) inz(1) ;                                                      
                                                                                                    
       Dcl-Proc Main                                           ;                                    
       Dcl-PI   *n       extPgm('DATEDIFF')                    ;                                    
          endProgram     char(1) const                         ;                                    
       END-PI                                                  ;                                    
                                                                                                    
          Exec SQL                                                                                  
              set option                                                                            
              Commit = *None,                                                                       
              Naming = *Sys,                                                                        
              DECRESULT = (63, 63, 0),                                                              
              datfmt = *ISO ;                                                                       
                                                                                                    
          Today = %dec(%date:*ISO) ;                                                                
                                                                                                                                                                                                       
          firstDate = BaseDate - %days(%subdt(BaseDate:*d) - 1) +                                   
              %days(DaysIn - 1)                                 ;                                    
                                                                                                    
                                                                                                    
          EXEC SQL                                                                                  
              set :DiffDate  = :Date1 - :Date2                    ;                                 
                                                                                                    
          EXEC SQL                                                                                  
              set :lastDate  = last_day(:Date2)                   ;                                 
                                                                                                    
          EXEC SQL                                                                                  
             set :DateChar  = TO_CHAR(:DtTmStamp, 'MM-DD-YYYY')   ;                                 
                                                                                                    
          EXEC SQL                                                                                  
             set :DayName  = dayName(:date2)                      ;                                 
                                                                                                    
          numDays = %Diff(Date1: Date2: *Days)                    ;                                 
                                                                                                    
          EXEC SQL set :dayOfWeek = dayOfWeek_ISO(:date2)         ;                                 
          EXEC SQL set :dayOfWeek2 = dayOfWeek(:date2)            ;                                 
                                                                                                    
          WeekDay = %rem(%diff(Date2:d'0001-01-01':*d) : 7) + 1   ;                                 
          WeekDay7= %rem(%diff(Date2:d'0001-01-07':*d) : 7) + 1   ;                                 
                                                                                                    
          EXEC SQL set :dayOfYear = dayOfYear(:date2);                                                                            
                                                                                                    
          *inlr = *on                                             ;                                 
                                                                                                    
          If endProgram = 'Y'                                     ;                                 
             CEETREC(*omit: 0)                                    ; // exit Program                 
          EndIf                                                   ;                                 
                                                                                                    
          RETURN ;                                                                                  
                                                                                                    
       END-PROC;     

CEE Date APIs

The CEE APIs offer tremendous flexibility. The format word allows the API to return a string that could be a three-letter day, the number of the day of the week, or the date, or even the text of the month, day of the week, and year.

       Ctl-Opt Option( *NoDebugIO : *SrcStmt ) DftActGrp( *No )                                     
               ActGrp( 'DATE1' ) PgmInfo( *PCML : *Module )                                         
               Main(Main) BNDDIR('QC2LE':'SC0000_BD') ;                                             

       Dcl-Pr CEETREC              extproc('CEETREC');                                              
          rc         Int(10) const options(*omit)    ;                                              
          user_rc    Int(10) const options(*omit)    ;                                              
       End-Pr;                                                                                      
                                                                                                    
       Dcl-PR CEEDAYS                ExtProc('CEEDAYS') OpDesc  ;                                   
         DateString                  char(32)           Const   ;                                   
         FormatString                char(32)           Const   ;                                   
         LilianDate                  int(10)                    ;                                   
         Error                       char(12)   Options(*Omit)  ;                                   
       End-Pr;                                                                                      
                                                                                                    
       Dcl-PR CEEDATE                ExtProc('CEEDATE') OpDesc  ;                                   
         LilianDate                  int(10)            Const   ;                                   
         FormatString                char(32)           Const   ;                                   
         DateString                  char(32)                   ;                                   
         Error                       char(12)   Options(*Omit)  ;                                   
       End-Pr;                                                                                      
                                                                                                    
       Dcl-PR CEEDYWK                ExtProc('CEEDYWK') OpDesc  ;                                   
         LilianDate                  int(10)            Const   ;                                   
         dayOfWeek                   int(10)            Const   ;                                   
         Error                       char(12)   Options(*Omit)  ;                                   
       End-Pr;                                                                                      
                                                                                                    
       Dcl-DS *n                      ;                                                             
         DiffDate        zoned(8:0)     ;                                                           
           DiffYears     zoned(4:0) overlay(DiffDate) ;                                             
           DiffMonths    zoned(2:0) overlay(DiffDate: *Next) ;                                      
           DiffDays      zoned(2:0) overlay(DiffDate: *Next) ;                                      
       END-DS;                                                                                      
                                                                                                    
       Dcl-DS  CeeFB                                          ;                                     
         MsgSev          uns(5)                               ;  //        2-byte severity code     
         MsgNo           uns(5)                               ;  //        2-byte message code      
         Bits            char(1)                              ;                                     
      ** Case - 2-bits defining format of condition                                                 
      ** Severity - 3-bits defining condition severity                                              
      ** Control  - 3-bits describing control variables                                             
         Facilyty_id     char(3)                              ;                                     
         I_S_Info        uns(10)                              ; //        0=no message issued       
       End-DS                                                 ;                                     
                                                                                                    

       Dcl-S Today         date            inz(*sys)          ;                                                                       
       Dcl-S sWorkDate     char(8)         ;                                                        
       Dcl-S sDateInWords  char(32)        ;                                                        
       Dcl-S nLil          int(10)         ;                                                        
       Dcl-S sFormat       char(32)        ;                                                        
       Dcl-S ceeWeekDay    int(10)         ; 
 
       Dcl-Proc Main                                           ;                                    
       Dcl-PI   *n       extPgm('DATECEE')                     ;                                    
          endProgram     char(1) const                         ;                                    
       END-PI                                                  ;                                    
                                                                                                    
          Exec SQL                                                                                  
              set option                                                                            
              Commit = *None,                                                                       
              Naming = *Sys,                                                                        
              DECRESULT = (63, 63, 0),                                                              
              datfmt = *ISO ;                                                                       
                                                                                                                                           
          sFormat = 'Wwwwwwwwwz, Mmmmmmmmmz ZD, YYYY'             ;                                 
          sWorkDate = %char(Today: *iso0)                         ;                                 
          Callp(e) CEEDAYS (sWorkDate: 'YYYYMMDD': nLil : *Omit)  ;                                 
          Callp(e) CEEDATE (nLil: sFormat:  sDateInWords: *Omit)  ;                                 
          Callp(e) CEEDYWK (nLil: ceeWeekDay            : *Omit)  ;                                 
                                                                                                    
          *inlr = *on                                             ;                                 
                                                                                                    
          If endProgram = 'Y'                                     ;                                 
             CEETREC(*omit: 0)                                    ; // exit Program                 
          EndIf                                                   ;                                 
                                                                                                    
          RETURN ;                                                                                  
                                                                                                    
       END-PROC;                                                                                  

Lilian Date Picture string

Picture String Character String
YY
YYMM
YY-MM
YYMMDD
YYYYMMDD
YYYY-MM-DD
YYYY-ZM-ZD
YY.MM.DD
YY.MM.DD
88
8805
88-05
880516
19880516
1988-05-16
1988-5-16
Showa 63.05.16 (in a DBCS string)
MinKow 77.05.16 (in a DBCS string)
MM
MMDD
MM/DD
MMDDYY
MM/DD/YYYY
ZM/DD/YYYY
05
0517
05/17
051788
05/17/1988
5/17/1988
DD
DDMM
DDMMYY
DD.MM.YY
DD.MM.YYYY
DD Mmm YYYY
18
1805
180588
18.05.88
18.05.1988
18 May 1988
DDD
YYDDD
YY.DDD
YYYY.DDD
140
88140
88.140
1988.140
YY/MM/DD HH:MI:SS.99
YYYY/ZM/ZD ZH:MI AP
88/05/20 00:00:00.00
88/5/20 0:00 AM
WWW., MMM DD, YYYY
Www., Mmm DD, YYYY
Wwwwwwwwww, Mmmmmmmmmm DD, YYYY
Wwwwwwwwwz, Mmmmmmmmmz DD, YYYY
SAT., MAY 21, 1988
Sat., May 21, 1988
Saturday , May 21, 1988
Saturday, May 21, 1988