The idea for this post came from a meeting of the programming managers at work. My programming nemesis, the "I can do everything you do in RPGIV just as well using RPGIII" guy, was bragging that no-one could write a better way of changing a date into words than his old RPG38 program.

"I can do what your program does in just a few lines of code," I explained. He disputed that I could, and the challenge was on.

His old program is passed a date, as a number, and returns:

Day number of the week, where 1 = Sunday, 2 = Monday, etc. Day of the week Name of the month The date in words, for example "THURSDAY JANUARY 1, 2017"

All of this information can be gathered using SQL functions. I have mentioned them in a previous post about date functions in SQL, and feel it is worth repeating.

I consider the code for this is so simple, I am going to jump straight into it with no further explanation.

Let me start with the section where I define all my variables.

01 **free 02 dcl-s DayName char(10) ; 03 dcl-s DayNumber zoned(1) ; 04 dcl-s DayOfMonth zoned(2) ; 05 dcl-s MonthName char(10) ; 06 dcl-s YearNumber zoned(4) ; 07 dcl-s FullDateString char(25) ; 08 dcl-s ThisDate date ; 09 dcl-s ThisChar char(10) ;

I am not going to explain much about this code as you regular readers of this blog will know what all this means. The only thing I will say is that the data type ZONED , lines 3, 4, and 6, is the equivalent of "signed" numeric in fixed format definitions.

Let me start with today's date.

10 exec sql SET :DayNumber = DAYOFWEEK(CURRENT DATE) ; 11 exec sql SET :DayName = DAYNAME(CURRENT DATE) ; 12 exec sql SET :DayOfMonth = DAYOFMONTH(CURRENT DATE) ; 13 exec sql SET :MonthName = MONTHNAME(CURRENT DATE) ; 14 exec sql SET :YearNumber = YEAR(CURRENT DATE) ; 15 FullDateString = %trimr(DayName) + ' ' + %trimr(MonthName) + ' ' + %char(DayOfMonth) + ', ' + %char(YearNumber) ; 16 dsply ('Today is ' + FullDateString) ;

By using CURRENT DATE in these statements it will always the date for today, whether I run this tomorrow, next week, next month, etc. I don't have to use a parameter with these functions. Unlike that program, where he has to pass UDATE to get the data for today.

Line 10: DAYOFWEEK returns a single numeric value to represent the day of the week. Sunday is 1, Monday 2, etc.

Line 11: DAYNAME returns the name of the day of the week, in mixed case. For example, "Sunday".

Line 12: DAYOFMONTH return the numeric value of the day of the month. For example if today is the 15th it returns 15.

Line 13: MONTHNAME returns the name of the month, in mixed case. For example, "December".

Line 14: YEAR returns the year from the date as a numeric value.

Line 15: Let me put all of that together. I am using this format as I am in the USA. You can easily change it to fit the format you are familiar with in your part of the world.

Line 16: Now let's display what I made. This gives me:

DSPLY Today is Wednesday December 21, 2016

And what about other dates, not just today.

17 ThisDate = d'1962-07-21' ; 18 exec sql SET :DayName = DAYNAME(:ThisDate) ; 19 exec sql SET :DayOfMonth = DAYOFMONTH(:ThisDate) ; 20 exec sql SET :MonthName = MONTHNAME(:ThisDate) ; 21 exec sql SET :YearNumber = YEAR(:ThisDate) ; 22 FullDateString = %trimr(DayName) + ' ' + %trimr(MonthName) + ' ' + %char(DayOfMonth) + ', ' + %char(YearNumber) ; 23 dsply ('07/21/1962 was ' + FullDateString) ;

Line 17: ThisDate is defined as a date field on line 8, and I am moving a date to it here.

Line 18 – 22: This is the same as I showed in the previous example, but rather than CURRENT DATE being the passed parameter I am using the date field.

When the DSPLY operation is performed I see:

DSPLY 07/21/1962 was Saturday July 21, 1962

I can even use character (alphanumeric) variables in these functions.

24 ThisChar = '04/27/1937' ; 25 exec sql SET :DayName = DAYNAME(:ThisChar) ; 26 exec sql SET :DayOfMonth = DAYOFMONTH(:ThisChar) ; 27 exec sql SET :MonthName = MONTHNAME(:ThisChar) ; 28 exec sql SET :YearNumber = YEAR(:ThisChar) ; 29 FullDateString = %trimr(DayName) + ' ' + %trimr(MonthName) + ' ' + %char(DayOfMonth) + ', ' + %char(YearNumber) ; 30 dsply ('04/27/1937 was ' + FullDateString) ;

These functions accept ' 04/27/1937 ' as it formatted like a valid date. When line 30 is executed I see.

DSPLY 04/27/1937 was Tuesday April 27, 1937

Providing the value in the character field is in a valid date format then these functions will accept it:

24 ThisChar = '1898-01-21' ; 30 dsply ('01/21/1898 was ' + FullDateString) ;

The above displays:

DSPLY 01/21/1898 was Friday January 21, 1898

Alas, when I try to use numbers as parameters the program will not compile.

So in six lines I can do the same as his 200+ line RPG38 program!

I call this individual my "programming nemesis" as a joke. He is a nice person, who I do socialize with outside of work. We just don't agree on the way to program on IBM i.

This article was written for IBM i 7.3, and should work for earlier releases too.