Professional Documents
Culture Documents
About Dates But Never Dared To Ask, Part 1
About Dates But Never Dared To Ask, Part 1
About Dates But Never Dared To Ask, Part 1
Home About this blog List of all posts IBM i user groups Legal notices Privacy policy Search this site
Tu e s d a y, O c t o b e r 2 0 , 2 0 1 5
Rather than address each item I have found I thought it would be better to write about the
Date data type and how I can use them in my RPG code. This will be spread out over several
posts, as to cover all I want to do is too much for just one. Let’s start today with what I
consider the basics.
Date formats
The date is stored as YYYYMMDD in Date data type variables, fields, and columns. Date
formats are just the way the date is presented to us, much like an edit mask or edit code.
Some formats can be used when defining Date data types variables, fields, and columns. Then
there are others that are only used to move values in or out of Date data types. Contact Form
These are the formats that are used for defining variables, fields, and columns: Name
/ - . , (19)40/01/01 –
*YMD Year/month/day YY/MM/DD
& (20)39/12/31
Send
/ - . , (19)40/001 –
*JUL Julian YY/DDD
& (20)39/365
International Standards 0001-01-01 – 9999-12-
*ISO YYYY-MM-DD -
Organization 31
01/01/0001 –
*USA USA standard MM/DD/YYYY /
12/31/9999
01.01.0001 –
*EUR European standard DD.MM.YYYY .
31.12.9999
0001-01-01 – 9999-12-
*JIS Japanese Industrial Standard YYYY-MM-DD -
31
These are the date formats that can only be used when moving value into or out of Date data
types:
Layout (with
Format default Valid Links to useful sites
name Description separator) separators Range
1 The range of dates expressed in conventional written format are January 1 1900 - December
6 IBM Documentation for 7.1
31 2899.
I have seen the *CYMD format most commonly used in older databases, designed in the days PowerSystems Redbooks (inc.
7
IBM i)
when the cost of disk was so expensive it was decided to use only one number for the century
to save disk space.
Personally, I think that the *CMMDDYY and *CDDMMYY are ridiculous and I cannot think of a reason Popular Posts: Last
to use them. 30 days
In all free RPG defining variables with these different date format could not be simpler as all I Defining variables in RPG all
4
have to do is define the variable as a date followed by the format I want to use: free
For those of you who still have to use fixed format definitions I would define the variable with a Defining Procedures in RPG all
4
"D" in the data type column and the DATFMT in the keyword column: free
But wait, for the date on line 9 I have not given a date format. In this case the default date Labels
format, *ISO, assumed.
I can change the default date format by using the DATFMT keyword in the Control options/H- 1 CL
specs. In the example below the default date format will be *EUR (DD.MM.YYYY).
DSPF
2
In all free RPG:
HISTORY
3
ctl-opt datfmt(*eur) ;
4 IFS
Or in fixed format.
5 LF
HKeywords+++++
6 NEW RELEASE
H datfmt(*eur)
NODE.JS
7
In DDS files, whether a Physical, Display, or Printer file, I define the date in the same way:
8 OPERATIONS
A..........T.Name++++++RLen++TDpB......Functions+++
A FLD_DATE L DATFMT(*USA) 9 PF
PROGRAMMING
To define it as a Date data type field I put "L" in the Data type column. "D" was already taken 10
when the Date data type was introduced, it used in Display files for an alphanumeric fields that
QUERY
can contain only numeric digits. As I am in USA I always use the DATFMT(*USA) so that when 11
the date is displayed in various tools, like Query, it will be shown in *USA format. If I did not
use the DATFMT the date would be displayed in *ISO format. 12 RPG
A date column can be coded in a (SQL) DDL table with the following statement: SHARED
13
I have added the NOT NULL as I do not want the date to be null if it contains no value. 16 VIRTUAL USER GROUP
► 2017 (92)
►
03 YMD_date = %date() ;
► 2016 (85)
►
► August (7)
►
Line 9: As the date in USA_date is outside the allowed range for a *MDY formatted Date data
type the program errors with the following message: ► July (5)
►
► June (7)
►
► January (6)
►
Date data types cannot be zero, as it is not a valid date. When I clear DMY_date, line 10, it will
contain the lowest date possible in that format, 01/01/40. Another way I can initialize a date to ► 2014 (94)
►
its lowest value is shown on line 11, using *LOVAL initializes JIS_date with 0001-01-01. Now
► 2013 (59)
►
the opposite, if I move *HIVAL to ISO_date I get 9999-12-31, line 12.
When moving other data types to Date types I always need to be sure that they contain
something that represents a date. If it does not I am going to get an error. Too many times I
have been told by other developers "Even though it is a number that field always contain a
valid date". Then at 3 AM a program errors as there is a record with "date" value of zero. Make
it your rule to always validate the other data type's value before moving it to a Date data type.
I did a brief post about this called Validating dates in RPGLE, and I hope with a combination of
this post and that one I cover pretty much all aspects of date validation.
We are provided with the TEST(DE) operation for validating any incoming data type is a date. I
need to provide the format I wish to validate the incoming value with, and the variable
containing the "date". In the example below I am validating that NumericDate contains a value
that is compatible with the *USA format, if it does not then the %ERROR is set on:
Before I give more detailed examples I need to introduce five new variables to our program:
Or in fixed format:
DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords+++++++
01 D A_USA S 8 inz('09201995')
02 D A_YMD S 10 inz('93.01.21')
03 D A_ISO1 S 8 inz
04 D A_ISO2 S 10 inz('19501024')
05 D N_CYMD S 7 0 inz(1150930)
The names of the variables describe the types of "dates" contained within them. Notice that
A_ISO1 is blank, therefore, it is not a valid "date". Below are examples of how I would move
these "dates" into Data date types of different types:
In the next grouping, lines 10 – 13, I am validating a *YMD formatted date with a period (. ) as
the separator. As the "date" is valid means that MDY_date contains 01/21/93.
Line 14 – 19 is the best example as it shows what you should do if the "date" is invalid or
valid. As this variable is blank it is going to be invalid. The validation on line 14 checks for a
"date" in ISO format with no separator character (*ISO0). As this "date" fails the validation the
error indicator is on, line 15. I have chosen to clear the date variable, line 16. There are times
when I might want to move another "date" in, for example today's date, instead.
In the group lines 20 – 23 I validate A_ISO2 as an alphanumeric ISO date without a date
separator, and then move the value into a *JIS formatted date. The result is that JIS_date
contains 1950-10-24.
When validating and moving numeric variables I do not have to worry about a separator
character. In the example shown in lines 24 – 27 I am using a numeric representation of a
*CYMD formatted date. As I said earlier I cannot define a *CYMD Date data type, but I use this
format to move a value from a variable into a Date data type of another format. On lines 24
and 26 there is no separator character with the date format. The result is that USA_date
contains 09/30/2015.
To move a value from Date data type into other types I use the %CHAR or %DEC depending on
what the result variable is. The examples below take the values in the Date formats above and
move them into other types of variables:
28 A_USA = %char(JIS_date:*usa0) ;
29 A_YMD = %char(USA_date:*ymd&) ;
30 A_ISO1 = %char(MDY_date:*iso0) ;
31 A_ISO2 = %char(JIS_date:*cymd-) ;
32 N_CYMD = %dec(YMD_date:*cymd) ;
Line 28: The value in JIS_date is converted to a character data type using the %CHAR built in
function. The second parameter in the %CHAR is the format I want to output to the variable
A_USA, in this line it is *USA format with no separator. A_USA = '10241950'.
Line 29: The interesting thing about the line is the use of the "&" as the character separator,
this denotes that the separator will be a blank. A_YMD = '15 09 30'.
Line 31: Using the *CYMD with the date separator character results in A_ISO2 = '090-10-24 '.
Line 32: I am using the %DEC built in function with a second parameter of the format I want the
result to contain. There is no date separator as I am moving this into a numeric field. N_CYMD
= 0950920.
You can learn more about these BIFs on the IBM website:
This article was written for IBM i 7.2, and it should work with earlier releases too.
5 comments:
Great post. Just a small correction, the ability to use %DEC with a second parameter to move a
date into a numeric variable is also allowed in 7.1.
Reply
Replies
I think that came in one of the more recent TRs. The IBM i I used for testing with
release 7.1 would not allow it.
Correction made.
Reply
I have always assumed (a dangerous practice) that CMDY and CDMY were there for shops that
stored their dates in 6-digit packed decimal fields using MDY or DMY format. Converting
applications to use the high-order nibble, which was not being used for anyting, to store the
year would be minimally disruptive. I can't think of any reason a shop would choose one of
these formats if other formats were feasible. I doubt it was any extra effort for IBM to support
these format.
Reply
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.
Powered by Blogger.