Date and time of day functions are pretty convenient things to have in a program, or better yet, have in a service program. Getting date and time values happens to be simple using Built-in Function (BIF) operations. For example, consider the two fields defined to contain the time of day, and today's date.
0007.00 D TimeOfDay S 6 0 0008.00 D DateToday S 8 0
Loading a date and time to the fields above requires just two lines of code. Assuming you want the current date and time in the ISO format, the following code will populate the fields with the correct decimal representation of date and time.
0037.00 TimeOfDay = %dec(%char(%time():*hms0):6:0); 0038.00 DateToday = %dec(%char(%date():*iso0):8:0);
There are times, however, when a timestamp can be more convenient than a date or time representation. You can extract months and days and weeks from a date type field, but not hours and minutes. Conversely, you can extract minutes and hours from a time type field, but not days or weeks. With a timestamp (Z) type field, you can extract days and/or hours.
Creating a timestamp type variable and setting the value is not difficult, but there are several ways to accomplish initialization. You can initialize a timestamp type field with a literal -- 26 bytes describe the timestamp value (mmmmmm = milliseconds):
Or, using the %EDTW BIF you can create a character string from numeric variables to set a value for a timestamp:
0022.00 D TimeString S 26 0041.00 timestring = %editw(DateToday:' - - ') + '-' + 0042.00 %editw(TimeOfDay:'0 . . ') + '.000000'; 0043.00 timestring = %xlate(' ':'0':timestring); 0044.00 timestamped = %timestamp(timestring);
Note: The %XLATE here is used to flip any blanks to zero, since by rule, leading zeros are required to create timestamp data. Once the edited string is built -- hyphens to separate the date, periods to separate the time -- use %TIMESTAMP to assign the value to a timestamp type field.
Still referring to the fields described in the previous example, merely adding the date and the time representations, using the %DATE and %TIME BIF operations, will result in a timestamp type field in perhaps the easiest method of putting a value in a timestamp.
0005.00 D TimeStamped S Z 46.0 TimeStamped = %date(DateToday:*iso) + %time(TimeOfDay:*ISO);
Although it is still common practice to store data and time representation in fixed decimal fields in a database file, having a date, time or timestamp field for quick date/time functions within a program is handy. For instance, in many applications there is no need to show a user anything other than hours and minutes. (Would you schedule an appointment for 12:30 or for 12:30:06?)
0002.00 D HourMin S 4 0 0026.00 D Now S T 0052.00 Now = %time(TimeOfDay); 0053.00 0054.00 HourMin = %subdt(Now:*MN) + (%subdt(Now:*H) * 100);
Using the time of day, which from the first example is a six-digit numeric value, the instruction in line 52 converts the value to a time type variable, NOW. With the BIF %SUBDT, it becomes relatively simple to produce a four-digit time representation of hours and minutes.
There are, however, some caveats to working with date type fields yet storing the date value as a numeric representation. Case in point, a valid date represented in a date type field may safely be moved from the date field to an *ISO eight-digit numeric representation, but it will fail when the date is moved to a *MDY six-digit field, specifically where dates are stored as eight-digit ISO numeric values and then converted to a date field to be translated to a six-digit *MDY format for print or display.
It has long been my belief that the TEST(DE) operation is not sufficient to test the value of a date to be stored as a numeric value instead of a date type field. Under the covers of the machine (V5R2) a six-digit date representation is limited to the date range 1940, through 2039, by a date window mechanism. So, even though 20510531 is a valid ISO date and can be represented as a valid date and moved from a date type field into an ISO eight-digit numeric representation, it will cause an application error if a program makes the attempt to move the date type field value to a six-digit *MDY representation. That's because the date is out of the range of the permissible date window.
Therefore, if you want to ensure *MDY date representations do not present a potential problem, date tests need to be more extensive than simply checking to see if the value is a valid date. A valid date, such as the example of 2051/05/31, will not produce an error on the TEST(DE), yet the value can still present a problem within an application.
0056.00 TEST(DE) *ISO0 test80; 0057.00 IF %error; 0058.00 err_msg = 'invalid date'; 0059.00 ELSE; 0060.00 IF %dec(test80:8:0) > 20391231 0061.00 or %dec(test80:8:0) < 19391231; 0062.00 err_msg = 'date out of window'; 0063.00 ENDIF; 0064.00 ENDIF;
If you intended to use the date as something other than an eight-digit value, TEST(DE) needs to be combined with additional code to ensure that the date is one that fits within the window, as illustrated in the code snippet above.
Be advised, Julian dates represented as numeric values are limited to the same date window as dates in the *MDY format. However, in an odd sort of quirk, *CYMD representations do not conform to this window and may represent dates from the year1900 through year 2899.
About the author: Steve Croy is a programmer at USXpress Enterprises Inc. in Chattanooga, Tenn.
This was first published in June 2005