This subseries will cover the main date- and time-related functions SQL has to offer, providing examples of possible applications of this interesting and useful set of scalar functions.
I’ll start by showing how to convert other data types to Date, Time, and Timestamp data. Handling dates and times in RPG has always been a pain. It’s true that the new-ish BIFs help a lot, but apparently simple tasks such as determining the day of the week of a given date or finding out when will the next Monday occurs require loads of RPG code to implement. SQL offers a very interesting set of scalar functions that can really help when it comes to handling date-related data.
Let’s start with the basics. SQL has three date-related data types: Date, Time and Timestamp. You have probably used them in your RPG programs, or at least you have seen them defined in D-specs, with the D, T, and Z data type definition, respectively. But SQL’s data types are not an exact copy of their RPG counterparts. Here’s a quick definition of these three data types, taken from IBM’s DB2 for i Reference manual:
A date is a three-part value (year, month, and day) designating a point in time under the Gregorian calendar, which is assumed to have been in effect from the year 1 A.D. The range of the year part is 0001 to 9999. The date formats *JUL, *MDY, *DMY, and *YMD can only represent dates in the range 1940 through 2039. The range of the month part is 1 to 12. The range of the day part is 1 to x, where x is 28, 29, 30, or 31, depending on the month and year. The internal representation of a date is a string of 4 bytes that contains an integer. The integer (called the Scaliger number) represents the date.
A time is a three-part value (hour, minute, and second) designating a time of day using a 24-hour clock. The range of the hour part is 0 to 24, while the range of the minute and second parts is 0 to 59. If the hour is 24, the minute and second specifications are both zero. The internal representation of a time is a string of 3 bytes. Each byte consists of two packed decimal digits. The first byte represents the hour, the second byte the minute, and the last byte the second.
A timestamp is a six or seven part value (year, month, day, hour, minute, second, and optional fractional second) that represents a date and time. The time portion of a timestamp value can include a specification of fractional seconds. The number of digits in the fractional seconds is specified using an attribute in the range from 0 to 12 with a default of 6. The internal representation of a timestamp is a string of between 7 and 13 bytes. The first 4 bytes represent the date, the next 3 bytes the time, and the last 0 to 6 bytes the fractional seconds.”
It’s a Date
So let’s start with the conversion functions that are directly related with the Date data type. The DATE function converts a date, a timestamp, a character string, a graphic string, or any numeric data type to a date data type. While the first two input data types are obvious—a Date data type doesn’t require conversion, and a timestamp is converted by simply dropping the time part of the timestamp—things get a little murky when the input parameter is a string. In this case, either a valid date representation in string format, such as ‘2014-11-16’ is provided or a 7-character string representing a date in yyyynnn format, where yyyy represents the year and nnn the number of days elapsed since January 1st, is provided; for instance, ‘2015035’ represents February 4th 2015. The numeric data type will be converted in similar fashion, but it will represent the number of days elapsed since January 1st 0001 (0001-01-01 in ISO date format). This means that DATE(35) returns a Date data type variable containing the 0001-02-04 date value. Here’s an example that illustrates the several options:
This statement returns three date data type values, holding the dates 2014-11-16, 2015-02-04 and 0001-02-04, respectively. I don’t know why, but I couldn’t get the third example to work in a V7R1 system. This feature doesn’t seem to be a novelty of V7R2, like the RPAD and LPAD functions I mentioned a few articles ago. IBM’s DB2 for i Reference manual doesn’t help either, because this is not marked as a new feature.
The TIME function is somewhat similar to date: It returns a time data type value, converted from a date, a time, a timestamp, a character string, or a graphic string data type. Converting a date data type to a time data type results in 00:00:00 (or midnight); the time data type doesn’t actually require a conversion; in the timestamp data type case, the date part is dropped; finally, the strings must represent a valid date, time, or timestamp in order to be converted to a time data type value.
This statement returns two time date type values, 10:23:25 and 13:15:45, respectively. Note that the first expression of the SELECT clause converts a string to timestamp and then that timestamp to time. Note that this last conversion would have failed if, for instance, the string contained ’25.15.45’, because this is not a valid time representation.
Seriously Accurate Date and Time: The Timestamp
The TIMESTAMP function is a bit more difficult to wrap your head around because of the way its parameters work. This function has two parameters. The first is conceptually similar to DATE and TIME’s first parameter: a date, a timestamp, or a string that represents a valid date or timestamp. The strangeness is in the second parameter: It can be either a date, a timestamp, or a string from which the system can extract a time or an integer constant representing the number of fractional seconds. In this case, the second parameter’s value must be in the range 0 through 12. Let me try to make this clearer with a couple of examples; first, a simple timestamp conversion using a Date data type value in the first parameter and a Time data type value in the second one:
SELECT TIMESTAMP(DATE(‘2014-11-16’), TIME(’16.28.45’))
The execution of this statement will produce a timestamp data type value of ‘2014-11-16-16.26.45.000000’. That’s fairly straightforward, right?
The next article will continue to discuss date-related scalar functions, covering a few that don’t have an RPG equivalent and that usually take a bit of coding to implement, such as the Day of the Week function, for instance. Until then, let me know what you think in the comments section below.