Handling DATES
with REXX
Basic rules
Initially, here are the basic rules that prevent problems
related to dates with respect to the year 2000, frequently called
the Y2K problem.
- Rule I:
Always use the 'Base' date format for any date calculations and
internal date data.
- Rule II:
Always use the 'Standard' date format (ISO standard) to store a
human readable date.
- Rule III:
Always use 'Base' date, or alternatively the 'Standard' date
format for sorting.
('Base' date format provides best performance)
- Rule IV:
Always convert from either 'Base' or 'Standard' date format to
any individual (external) format used for presentation to the
human eye including any national language defined NLS
formats.
- Rule V:
Convert your data from any of the 'deficient' old formatted date
data to either 'Base' or 'Standard' date format as soon as
possible!
Remark: Note that the date conversion
function is not available in OS/2 Warp and REXX/6000. Please be
also aware that the functions retrieving file dates are not
available in VM/CMS and MVS/TSO. If you run OS/2 you are advised
to switch to Object REXX using the SWITCHRX command. In any case,
in particular when working on VM/CMS or MVS/TSO you should make
sure to have the latest release of REXX installed.
Calculation and conversion
Here are some examples how to use REXX built-in functions to
solve usual date calculation and conversion problems:
- Yesterday or tomorrow:
-
/* get today's date in 'Base' date format, e.g. '729584' */
today = Date('Base') /* calculate next day; returns '729585' */
tomorrow = today + 1 /* calculate previous day; returns '729583' */
yesterday = today - 1
- Date conversion:
-
To any format supported by the Date built-in
function:
/* returns '19980715' */
ISOdate = Date('Standard', today, 'Base') /* returns '07/15/98' */
USdate = Date('Usa',today, 'Base') /* returns '15 Jul 1998' */
Ndate = Date('Normal', today, 'Base')
- Day of the year:
-
The day within the year of today, the July 15,
1998 (current date):
day = Date('Days') /* returns 196 */
- Weekday of a particular
date:
-
/* returns 'Wednesday' */
weekday = Date('Weekday', '07/15/98', 'Usa') /* returns 2, 0 = Monday, 6 = Sunday */
dayOfWeek = Date('Base', '07/15/98', 'Usa')//7
- Date difference:
-
/* returns 20091 days */
days = today - Date('Base', '19430715', 'Standard')
- Month of day in year:
-
Calculating the name of the month a particular
date is in.
/* returns 'September' */
month = Date('Month', 250 ,'Days')
Formatting for output or input
By means of the translate function, a date format (assuming
'Standard' date format) can be easily transformed (by reordering
the digits and inserting or removing separation characters) into
any format desired with a single REXX statement:
-
/* ISO Standard date format without separator characters */
myISOdate = '19430715'
/* returns '15-07-1943' */
date1 = Translate('78-56-1234', myISOdate, '12345678')
/* returns '07/15/1943' */
date2 = Translate('56/78/1234', myISOdate, '12345678')
/* returns '15/07/1943' */
date3 = Translate('78/56/1234', myISOdate, '12345678')
Similarly, the converse transformation allows to
easily get an ISO date format from any date format with
separators, by example:
-
date1 = '15-07-1943'
/* returns '19430715' */
myISOdate = Translate('78904512', date1, '1234567890')
date2 = '07/15/1943'
/* returns '19430715' */
myISOdate = Translate('78901245', date2, '1234567890')
/* ISO Standard date format with separator characters */
anISOdate = '1943-07-15'
/* returns ISO Standard date w/o separators '19430715' */
myISOdate = Translate('12346790', anISOdate, '1234567890')
Another quite useful feature of REXX is the
windowed handling of the 'deficient' short date formats currently
causing so much trouble because of the Y2K. In this case, REXX by
default uses the hundreds within the window
-
today + 49 and today - 50 years.
Therefore, the 'Usa' date '07/15/43' is
interpreted as 'Standard' date '20430715' because the year 1943
would be outside the 100 year wide window of today, July 17,
1998! In this way, all dates within 50 years around the current
date are converted correctly without additional programming
effort.
Some useful functions
- Date validation
-
The validity of a date in a defined format,
e.g. ISO date, is checked easily as follows:
-
/* function checking the validity of an ISO date */
valiDate: procedure
parse arg ISOdate
/* catch syntax error produced by wrong date value */
signal on syntax
dummy = Date(, ISOdate, 'Standard')
return 0 /* is valid date */
syntax:
return 1 /* is invalid date */
- Test for Leap Year
-
The same technique can be used to implement a
functions that checks if the input date falls in a leap
year:
-
/* function checking for a leap year of an ISO date */
isLeap: procedure
parse arg ISOdate
/* catch syntax error produced by wrong date value */
signal on syntax
dummy = Date(, substr(ISOdate,1,4)'0229', 'Standard')
return 1 /* is valid date, --> leap year */
syntax:
return 0 /* is invalid date, --> no leap year */
- Daylight Saving Dates
-
Another useful example shows the calculation of
the dates for the Daylight Savings Time in the United
States:
-
/* US daylight saving time dates for a year */
dsDates: procedure
parse arg year
if arg() = 0 then do
/* Help text */
say 'Calculate the beginning and ending of Daylight'
say 'Savings Time in the US'
say ' (First Sunday in April and last Sunday in October)'
say 'Usage: dsDates '
return
end
/* Calculate Daylight start in base format */
DaylightStart = Date('Base', year'0401','Standard')
DayOfWeek = DaylightStart//7
/* If April 1st isn't a Sunday, */
if DayOfWeek < 6 then
/* take the next one */
DaylightStart = DaylightStart + 6 - DayOfWeek
/* Calculate Daylight end in base format */
DaylightEnd = Date('Base', year'1031', 'Standard')
DaylightEnd = DaylightEnd - (DaylightEnd + 1)//7
/* get today's date */
Today = Date('Base')
/* format the output dates */
SO = Translate('345.61,67890', Date(, DaylightStart, 'Base'),'1234567890')
EO = Translate('456.712,7890A', Date(, DaylightEnd, 'Base'),'1234567890A')
/* write the output */
say 'US Daylight Savings Time in' year
say ' starts on:' SO ' ('DaylightStart - Today 'days from now)'
say ' ends on:' EO ' ('DaylightEnd - Today 'days from now)'
return
Retrieving file dates
To retrieve a date associated with a file, two alternatives
are available, the Stream built-in function and the REXX
Utility function SysFileTree. How these are properly used
is described in the following examples.
Stream built-in function
This example shows how to get the date a file
was created or last modified using the Stream built-in function
with the command "QUERY TIMESTAMP":
-
/* get the date the file "profile.txt" was last modified */
filedate = stream("profile.txt", 'c', 'QUERY TIMESTAMP')
/* returns the date in ISO format, e.g. 1995-11-12 */
say filedate
Note: The old command "QUERY DATETIME'
providing only a two digit year component is still supported but
should not be used any longer.
The SysFileTree utility function
This utility function allows to retrieve the
file information using option "L" as follows:
-
/* get the date the file "profile.txt" was last modified */
rc = SysFileTree("profile.txt", myStem., "L")
/* says the date in ISO format, the time, etc., e.g. */
/* "1995-11-12 12:24:55 45 A---- d:\profile.txt" */
say myStem.1
Note: The old option 'T' providing only
a two digit year component is still supported but should not be
used any longer.
|