November 30

1 comments

Use RPG to find the day of the week

By NickLitten

November 30, 2017

RPG, date, procedure, snippet, SRVPGM

Day of the week

I wanted a handy little RPG code snippet to return the day name for a date. My requirement was to  feed in a date like “Nov 30 2017” and it to tell me that its ‘Thursday’. Google to the rescue, I found a nice little article by RAFAEL VICTORIA-PEREIRA (Thankyou Sir!) which has a code sample doing 99% of what I want. It’s a couple of years old so, a quick code refactor, modernize and here it is.

Original old style RPG article is here

Here are the two main code snippets in a Service program ready for your copy/paste delight:

Service Program @SRVDATE to find DAY OF THE WEEK

 // +---------------------------------------------------------+
 // | Name - @SRVDATE                                         |
 // | Function - Look up a date and return the day name       |
 // +---------------------------------------------------------+
 //
 // CRTRPGMOD MODULE(@srvdate )
 // DBGVIEW(*NONE)
 // BNDDIR('yourbinder')
 // ----------
 // CRTSRVPGM SRVPGM(@srvdate )
 // MODULE(@srvdate )
 // EXPORT(*ALL)
 // SRCFILE(@BINDER)
 // SRCMBR(@srvdate )
 // ACTGRP(*CALLER)
 // REPLACE(*YES)
 //
 // Modification History
 // 2017-11-30 NJL01 Created as part of version(185) revamp project.
 // ----------------------------------------------------------------
Rpg day of week
ctl-opt
 debug
 option(*nodebugio:*srcstmt)
 datfmt(*iso-) timfmt(*iso.)
 fixnbr(*zoned:*inputpacked)
 indent('| ') truncnbr(*yes)
 expropts(*resdecpos)
 copyright('| @srvdate 2017.11.30')
 nomain;


// Day of the week (returns the day of the week of a given date as nbr)
// From Monday(1) thru Sunday(7)
dcl-proc #rtvDayNumber export;
dcl-pi #rtvDayNumber zoned(1);
  p_Date date const;
end-pi;

dcl-s rtnDayNumber zoned(1) inz(9);
dcl-s RefDate date inz(d'0001-01-01');

 // Validate input date (this should be good but lets double check to be sure)
 TEST(E) p_Date;
 IF %ERROR;
   RETURN rtnDayNumber;
 ENDIF;

 // If the input parm is ok, calculate the day of the week
 rtnDayNumber = %REM(%DIFF(p_Date:RefDate:*DAYS):7)+1;

 return rtnDayNumber;

end-proc;
// Day of the week (returns the day of the week of a given date in text)
dcl-proc #rtvDayName export;
dcl-pi #rtvDayName char(10);
  p_Date date const;
end-pi;

dcl-s rtnDayName char(10) inz(*blanks);
dcl-s p_daynbr zoned(1);

 // calculate the day number for our input date
 p_daynbr = #rtvDayNumber(p_date);

 // if our date is squiffy then return an error
 IF p_DayNbr < 1 Or p_DayNbr > 7;
   rtnDayName = '*UNKNOWN';
 else;

   // If the input date is ok, Return the corresponding text
   select;
   when p_DayNbr = 1;
     rtnDayName = 'Monday';
   when p_DayNbr = 2;
     rtnDayName = 'Tuesday';
   when p_DayNbr = 3;
     rtnDayName = 'Wednesday';
   when p_DayNbr = 4;
     rtnDayName = 'Thursday';
   when p_DayNbr = 5;
     rtnDayName = 'Friday';
   when p_DayNbr = 6;
     rtnDayName = 'Saturday';
   when p_DayNbr = 7;
     rtnDayName = 'Sunday';
   endsl;
 endif;

return rtnDayName;

end-proc;

Binder Language

STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('your signature here')
 EXPORT SYMBOL(#rtvDayNumber)
 EXPORT SYMBOL(#rtvDayName)
ENDPGMEXP

Code Example

In our programs we would add that service program and then just do this for any given date:

// +-----------------------------------------------------------------+ 
// | #DATE - Date Handlign Procedures from SRVPGM (@SRVDATE) | 
// +-----------------------------------------------------------------+ 
 
dcl-pr #rtvDayNumber zoned(1); 
 *n date const; // p_date 
end-pr; 
 
dcl-pr #rtvDayName char(10); 
 *n date const; // p_date 
end-pr;

then in our mainline code we simply ask it for the day name

name_of_day = @rtvDayName ( someDate );

*boom

Worked like a charm.

So, I’ve got the little service program working, documented it, written this blog in less time than I would have taken to figure it out and written it myself.

This internet thing is bloody useful sometimes. I think it’s going to catch on….

  • Should really add the Date Format keyword to the Pr/Pi Nick or you may get “interesting” results if the programmer who uses this routine just happens to code a different default on the Ctl-Opt than was used when the service proc was created. Hard-coding th format along with Const deals with that.

    Also, although the logic I use is not exactly the same (a slightly bastardized version of mine appears in the RPG “Sorcerers” redbook) – if you do away with the +1 in the main calc and then add 7 if the result was < 1 then you don't need to handle a special case "unknown". In other words: WorkNum = %diff( WorkDate : Anysunday : *days); WorkDay = %rem(WorkNum :7); // Testing for < 1 allows for the situation where the input date // is earlier than the base date (AnySunday) If WorkDay < 1; Return WorkDay += 7; Else; Return WorkDay; Endif; In mine I use two lines to do the base calc because it was a teaching example developed when we first introduced subprocs back in V3r2.

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

    Join the IBM i Community for FREE Presentations, Lessons, Hints and Tips

    >