HPlogo Communicator 3000 MPE/iX Release 6.0 (Platform Software Release C.60.00): HP 3000 MPE/iX Computer Systems > Chapter 9 Year 2000 Enhancements

New Date Intrinsics for MPE/iX

» 

Technical documentation

Complete book in PDF
» Feedback

 » Table of Contents

 » Index

by M Gopalakrishnan
Commercial Systems Division

This release of the MPE/iX operating system has enhanced intrinsics for handling date formats. These intrinsics are targeted to support widely used existing date formats in MPE/iX and three new date formats.

The date intrinsics are broadly categorized as follows:

  • HPDATECONVERT—Converting dates from one supported format to another.

  • HPDATEFORMAT—Converting the supported format dates to the display formats desired by the user.

  • HPDATEDIFF—Determining the number of days that separate two given dates.

  • HPDATEOFFSET—Adding/subtracting an offset (days) to/from the given date.

  • HPDATEVALIDATE—Validating the given date for conformance to a supported date format.

  • HPCALENDAR, HPFMTCALENDAR—Using the new 32-bit HPCALENDAR format.

The following sections will discuss various date formats and the syntax and semantics of new date intrinsics. COBOL and Pascal programs using these intrinsics are provided as examples.

Existing Date Formats

Existing date formats that are widely used are summarized in the following table, "Existing Date Formats." The column "Sortable?" indicates whether the dates can be sorted (either numerically or lexicographically depending on how they are stored). The last column "Y2K Ready?" indicates whether dates in the format under consideration can be used to represent dates beyond 1999-12-31. The column "#Bytes" represents the number of bytes required to store the date format.

Table 9-2 Existing Date Formats

Storage Type

# Bytes

Explanation

Sortable?

Y2K Ready?

longint [1]

8

Microseconds since 1970-01-01

yes

yes

(MPE time-stamp)

integer

4

Upper 2 bytes: year

yes

yes

next byte: month of year

bottom byte: day of month

integer

4

Upper 2 bytes: year

yes

yes

bottom 2 bytes: day of year

integer

4

Seconds since 1970-01-01

yes

yes

(POSIX.1 time() format; valid through 2038-01-18)

shortint

2

Upper 7 bits: #years since 1900

yes

yes

Lower 9 bits: day of the year

(CALENDAR format; valid up to 2027-12-31)

integer

4

YYMMDD date

yes

no

integer

4

MMDDYY date

no

no

integer

4

DDMMYY date

no

no

ASCII [2]

6

YYMMDD date

yes

no

ASCII

6

MMDDYY date

no

no

ASCII

6

DDMMYY date

no

no

ASCII

6

YYMMDD date YY:MM3000 date [3]

yes

yes

ASCII

6

MMDDYY date YY:MM3000 date

no

yes

ASCII

6

DDMMYY date YY:MM3000 date

no

yes

[1] "integer" and "longint" are binary values.

[2] "ASCII" means ASCII character code.

[3] MM3000 dates are represented as in the MM3000 product which used the ASCII letters "A" - "Z" for decades starting with the year 2000.

 

New Date Formats

Three new date formats are listed in the table, "HP Standard Formats." The first format is an integer representation of the ISO 8601 date format. The second is an ASCII representation of the same. The last date format is an extension of the existing 16-bit CALENDAR date format to a 32-bit format. These date formats will be referred to as "HP Standard Formats."

Table 9-3 HP Standard Formats

Storage Type

# Bytes

Explanation

Sortable?

Y2K Ready?

integer

4

YYYYMMDD date

yes

yes

ASCII

8

YYYYMMDD date

yes

yes

integer

4

Upper 23 bits: #years since 1900

yes

yes

Bottom 9 bits: day of the year.

(Extension of the existing CALENDAR format.)

 

Supported Date Formats

The "HP Standard Formats" and "Existing Date Formats" are combined in the following table, "Supported Date Formats." Each date format is assigned a date type code. The date intrinsics support these date formats and date type codes.

Table 9-4 Supported Date Formats

Date Type Code

Storage Type

# Bytes

Explanation

Sortable?

Y2K Ready?

1

longint

8

MPE time-stamp

yes

yes

(microseconds since 1970-01-01)

2

integer

4

Upper 2 bytes: year

yes

yes

next byte: month of year

bottom byte: day of month

3

integer

4

Upper 2 bytes: year

yes

yes

bottom 2 bytes: day of year

4

integer

4

Upper 23 bits: #years since 1900

yes

yes

bottom 9 bits: day of the year.

(analogous to the existing CALENDAR format.)

  

10

integer

4

Seconds since 1970-01-01

yes

yes

(POSIX.1 time() format; valid through 2038-01-18)

14

shortint

2

Upper 7 bits: #years since 1900

yes

yes

Lower 9 bits: day of the year

(CALENDAR format; valid up to 2027-12-31)

15

integer

4

YYMMDD date

yes

no

16

integer

4

MMDDYY date

no

no

17

integer

4

DDMMYY date

no

no

18

integer

4

YYYYMMDD date

yes

yes

25

ASCII

6

YYMMDD date

yes

no

26

ASCII

6

MMDDYY date

no

no

27

ASCII

6

DDMMYY date

no

no

35

ASCII

6

YYMMDD date YY:MM3000 date[1]

yes

yes

36

ASCII

6

MMDDYY date YY:MM3000 date

no

yes

37

ASCII

6

DDMMYY date YY:MM3000 date

no

yes

38

ASCII

8

YYYYMMDD date

yes

yes

[1] MM3000 dates are represented as in the MM3000 product which used the ASCII letters "A" - "Z" for decades starting with the year 2000.

 

Special Date Values

Special date values to represent UNKNOWN, INVALID, NEVER, NEEDED, EXPIRED, and ILLEGAL dates are defined for dates in "HP standard formats." The following table captures this date value information. The other date formats have been in existence for some time and hence the special date values are not defined for them. These special dates, when passed to the HPDATEFORMAT intrinsic, will result in a corresponding output string. For example, passing "00000103" to HPDATEFORMAT will result in the output string: "NEEDED".

When special dates are passed to HPDATECONVERT, HPDATEOFFSET, and HPDATEDIFF intrinsics as input dates, an error status is returned and the output date is initialized to a binary zero value or a blank string, depending on the date type of the output date.

Table 9-5 Special Date Values

DataType

Format

Un-

known

Invalid

NeverNeededExpiredIllegal

4

YYYYDDD

0

0000367

0000368

0000369

0000370

0000371

18

YYYYMMDD

0

00000101

00000102

00000103

00000104

0000105

38

YYYYMMDD

"blank"

"0000010"

"00000102"

"00000103"

"00000104"

"0000105"

 

New Date Intrinsics

The date intrinsics support dates in the range 0001-01-01 through 9999-12-31. They use the Gregorian calendar for all calculations beyond 1753. The calendar followed by the intrinsics ignores the fact that calendars in different countries changed at different times and some dates were dropped from the calendar (around the year 1753). The validity of dates prior to 1753 cannot be guaranteed. All intrinsics accept byte-aligned input/output date parameters, and all these intrinsics are NM callable.

On an error, the intrinsics initialize the output parameters to either a binary zero or a blank string depending on the type of the parameter.

Though the date type "4" can represent years beyond 9999, a year beyond 9999 (which needs five digits/characters) is considered an error.

It is recommended that character array based output date parameters are initialized to blanks before passing them as arguments to these intrinsics.

New errors and warnings are documented in the System Message Catalog, SYSCAT.PUB.SYS, under the date intrinsics subsystem number 529.

HPDATECONVERT

This intrinsic converts the dates from one supported format to another.

Syntax

               I32V     *     I32V      *     I32  I32V
HPDATECONVERT(inputcode,inputdate,outputcode,outputdate,status,cutoff)

Parameters

inputcode

is a 32-bit signed integer by value.

The value should be one of the date type codes listed in the table, "Supported Date Formats."

inputdate

varies for type by reference.

The interpretation depends upon the value of inputcode. See the table, "Supported Date Formats," for the supported date codes and their layouts.

outputcode

is a 32-bit signed integer by value.

The value should be one of the date type codes listed in the table, "Supported Date Formats."

outputdate

returns the date as per the format chosen by the outputcode parameter.

See the table, "Supported Date Formats," for the supported datecodes and their layouts.

status

is the HPE_STATUS parameter through which the error codes are returned. A value of 0 indicates no error and no warnings.

cutoff

is a 32-bit signed integer by value (optional).

This is used in validating the input parameter when the input date has two-digit year. This is a required parameter for dates with two-digit years. In all other cases, this parameter is ignored.

If the cutoff parameter is given as -1, the value of the CI environment variable HPSPLITYEAR is used as the cutoff year.

This parameter's value should be in the range 0 .. 100. If the value of the parameter is 50, two digit years in the range 0 .. 49 will translate to 200 .. 2049 and those in the range 50 .. 99 will be translated to 1950..1999. If you specify the cutoff year as 70, the mapping will be 0 .. 69 as 2000 .. 2069 and 70 .. 99 as 1970 .. 1999.

HPDATEFORMAT

You can use this routine to format the dates that can be combinations of display formats as explained below. Many of these elements are taken from ALLBASE/SQL date formats.

You can convert dates in the "Supported Date Formats" to a display string of your choice (with restrictions). The HPDATEFORMAT intrinsic will accept these format strings. The format specification strings can have the following syntax:

Syntax

[{FormatElement}{Punctuation}]

Table 9-6 Valid Parameters for FormatElement

CC

Century (01 to 99)

YYYY

Year (0001 to 9999)

YY

Year of century (00 to 99) with leading zeros suppressed (0 to 99)

Q

Calendar quarter of the year (1 to 4)

MM

Month of the year (01 to 12)

ZMM

Month of the year with leading zeros suppressed (1 to 12)

DD

Day of the month (01 to 31)

ZDD

Day of the month with leading zero suppressed (1 to 31)

DDD

Day of the year (001 to 366).

ZDDD

DDD with leading zeros suppressed (1 to 366)

D

Day of the week (1 to 7 where Sunday is 1, Monday is 2,...)

WW

Week of the year (01 to 53)

ZWW

Week of the year with leading zero suppressed (1 to 53)

Mon

Month of the year in ASCII format (Jan, Feb,...)

Day

Day of the week in ASCII format (Sun, Mon,...)

MON

Month of the year in ASCII (uppercase) format (JAN, FEB,...)

DAY

Day of the week in ASCII (uppercase) format (SUN, MON,...)

 

Table 9-7 Valid Characters for Punctuation

-

Hyphen

/

Slash

.

Dot

Blank

,

Comma

Null (or no delimiter)

 

Thus, YYYY.MON.DAY, YY/MM/DD, DDMONYY, and DD-ZMM-YYYY are valid date formats. For example, "31 Jan 1997" when formatted through DD-ZMM-YYYY results in "31-1-1997," formatted through YYYY.MON.DAY results in "1997.JAN.FRI," while YYYYMMDD results in "19970131."

NOTE: Mixing the NULL punctuation character with other punctuation characters is not allowed. Thus, YYYY/MM/DD is a valid format, while YYYYMM/DD is not. fmtdatelen parameter is length of formatspec parameter including the null termination character.

Syntax

            I32V    *      CA        CA    I32    I32  I32V
HPDATEFORMAT(datecode,inputdate,formatspec,fmtdate,fmtdatelen,status,cutoff)

Parameters

datecode

is a 32-bit signed integer by value.

This value should be one of the date type codes listed in the table, "Supported Date Formats."

inputdate

is the input date.

The interpretation depends upon the value of datecode. See the table, "Supported Date Formats," for the supported datecodes and their layouts.

formatspec

is a character array (required).

This should be a NULL terminated string as per the syntax explained above in the table, "Format Specification Strings."

fmtdate

is a character array (required).

This array size should be at least that of formatspec. On return, it will contain the date formatted as per the formatspec.

If an invalid date is passed, on return from the intrinsic its contents will be UNKNOWN. For the "HP Standard Formats," if special values in the table, "Special Date Values," are passed for date parameter, on return from the intrinsic, the value of the string will be appropriately initialized. For example, for the date type 18, the initialized values for different special date values are as follows:

Date Value

Returned Contents

00000000

"UNKNOWN"

00000101

"INVALID"

00000102

"NEVER"

00000103

"NEEDED"

00000104

"EXPIRED"

00000105

"ILLEGAL"

If the character array passed does not have enough space to hold the special values or the formatted date, the behavior is undefined.

fmtdatelen

is a 32 bit integer by reference (required).

On input, it is the length of the formatspec parameter.

On return, it represents the number of characters HPDATEFORMAT placed into fmtdate.

status

is the HPE_STATUS parameter through which the error codes are returned. A value of 0 indicates no error and no warnings.

cutoff

is a 32-bit signed integer by value (optional).

This is used in validating and converting from two-digit to four-digit years. (See HPDATECONVERT documentation for more information on the cutoff parameter).

HPDATEDIFF

This intrinsic determines the number of days that separate two given dates.

Syntax

          I32V     *      *       I32    I32  I32V
HPDATEDIFF(datecode, firstdate,seconddate,diffindays,status,cutoff)

Parameters

datecode

is a 32-bit signed integer by value.

This value should be one of the date type codes listed in the table, "Supported Date Formats."

firstdate

is the first input date. The interpretation depends upon the value of datecode. See the table, "Supported Date Formats," for the supported datecodes and their layouts.

seconddate

is the second input date. The interpretation depends upon the value of datecode. See the table, "Supported Date Formats," for the supported datecodes and their layouts.

diffindays

is the number of days difference between the two dates, computed as: seconddateminusfirstdate. Thus, if seconddate is earlier than firstdate, diffindays will be negative.

status

is the HPE_STATUS parameter through which the error codes are returned. A value of 0 indicates no error and no warnings.

cutoff

is a 32-bit signed integer by value (optional).

This is used in validating and converting the two-digit years to four-digit years before computing the difference. (See HPDATECONVERT documentation for more information on cutoff parameter.)

HPDATEOFFSET

This intrinsic adds or subtracts a specified offset to or from the given date.

Syntax

             I32V     *     I32V    *      I32  I32V
HPDATEOFFSET(datecode,inputdate,offset,outputdate,status,cutoff)

Parameters

datecode

is a 32-bit signed integer by value

This value should be one of the date type codes listed in the table, "Supported Date Formats."

inputdate

is the input date. The interpretation depends upon the value of datecode. See the table, "Supported Date Formats," for the supported datecodes and their layouts.

offset

is a 32-bit signed integer by value.

The number of days to be added to the input date. A negative value will result in a subtraction.

outputdate

is the output date. The result of the date offset operation. The interpretation depends upon the value of datecode. See the table, "Supported Date Formats," for the supported datecodes and their layouts.

status

is the HPE_STATUS parameter through which the error codes are returned. A value of 0 indicates no error and no warnings.

cutoff

is a 32-bit signed integer by value (optional).

This is used in validating and converting the two-digit years to four digit ones before computing the difference. (See HPDATECONVERT documentation for more information.)

HPDATEVALIDATE

This intrinsic checks the validity of the given date with respect to the supported formats given in the table, "Supported Date Formats."

Syntax

 I32                 I32V     *    I32V
result := HPDATEVALIDATE(datecode,inputdate,cutoff)

Parameters

datecode

is a 32-bit signed integer by value.

This value should be one of the date type codes listed in the table, "Supported Date Formats."

inputdate

is the input date.

The interpretation depends upon the value of datecode. See the table, "Supported Date Formats," for the supported datecodes and their layouts.

cutoff

is a 32-bit signed integer by value (optional).

This is used in validating dates with two digit years. (See HPDATECONVERT documentation for more information on cutoff parameter).

result

is a 32-bit signed integer (assigned functional return).

This value will be 0 if the inputdate conforms to the date format represented by datecode. If it is not so, its value will be positive. If an error has occurred in evaluating the conformance, its value will be negative. This return value ranges from -999 to 1.

HPCALENDAR

The new HPCALENDAR intrinsic returns the date in the supported date type code 4 listed in the table, "Supported Date Formats." (This is also a HP standard format.)

Syntax

 I32
date := HPCALENDAR ;

where date is the 32-bit unsigned integer (assigned functional return).

This returns the calendar date in the following format:

Table 9-8 HPCALENDAR Date Format

Bits

Value/Meaning

23:9

Day of year

0:23

Year since 1900

 

HPFMTCALENDAR

This a new routine to handle HPCALENDAR format. It does the same job as FMTCALENDAR except that it accepts the 32-bit integer returned by HPCALENDAR intrinsic.

Syntax

              I32V  CA
HPFMTCALENDAR(date,formatdate)

Parameters

date

is a 32-bit signed integer by value

This holds the calendar date, in the same format as the HPCALENDAR intrinsic (that is, date type 4).

formatdate

returns the formatted calendar date in a 17-character array. If the day of the month is less than 10, a blank precedes it. For example,

FRI, JAN  6, 1989

Examples

Following are two examples:

  • The Pascal program example uses most of the new date intrinsics.

  • The COBOL program example uses the HPDATECONVERT intrinsic.

Pascal Example of New Date Intrinsics


$standard_level 'hp_modcal'$

Program dateintr(input,output);

{Constants for the different date types.}
const
hp_dt_mpe_time_stamp_fmt = 1;
hp_dt_packed_yymmdd_fmt = 2;
hp_dt_packed_yyddd_fmt = 3;
hp_dt_new_calendar_fmt = 4;

hp_dt_posix_time_stamp_fmt = 10;

hp_dt_calendar_fmt = 14;
hp_dt_int_yymmdd_fmt = 15;
hp_dt_int_mmddyy_fmt = 16;
hp_dt_int_ddmmyy_fmt = 17;
hp_dt_int_yyyymmdd_fmt = 18;

hp_dt_ascii_yymmdd_fmt = 25;
hp_dt_ascii_mmddyy_fmt = 26;
hp_dt_ascii_ddmmyy_fmt = 27;

hp_dt_mm3000_yymmdd_fmt = 35;
hp_dt_mm3000_mmddyy_fmt = 36;
hp_dt_mm3000_ddmmyy_fmt = 37;
hp_dt_ascii_yyyymmdd_fmt = 38;

{Type definitions for the program}
type
pac_20 = packed array [1..20] of char;
iptr_type = ^integer;

VAR
date2_pac : pac_20; {Dates in packed character arrays.}
fmt_pac : pac_20;
print_pac : pac_20;

cutoff : integer; {To represent cutoff date.}
date1 : integer; {Working dates.}
date1_18 : integer;
date2_18 : integer;
date3_18 : integer;
i : integer; {temp variables.}
inptype : integer;
j : integer;
outtype : integer;
print_len : integer; {Length of formatted date.}
temp_date : integer; {Another temp variable}

status : integer;

function HPCALENDAR : integer; intrinsic;
procedure HPFMTCALENDAR; intrinsic;
function HPDATEVALIDATE : integer; intrinsic;
procedure HPDATEFORMAT ; intrinsic;
procedure HPDATECONVERT ; intrinsic;
procedure HPDATEOFFSET ; intrinsic;
procedure HPDATEDIFF ; intrinsic;
begin
{Initialize the variables.}
cutoff := 50;
inptype := hp_dt_int_ddmmyy_fmt;

date2_pac := '960121'; {The YYMMDD date in Supported format '25'.}
date1 := 230196; {The DDMMYY date in Supported format '17'.}


{conversion from one non standard formatto another}
HPDATECONVERT(inptype,date1,hp_dt_ascii_yymmdd_fmt,fmt_pac,
status,cutoff);
if( status <> 0) then
writeln('HPDATECONVERT intrinsic returned error',status);

{Convert 'date1' to the YYYYMMDD integer format. With 50}
{as the cutoff year. }
outtype := hp_dt_int_yyyymmdd_fmt;
HPDATECONVERT(inptype,date1,outtype,date1_18,status,cutoff);
if( status <> 0) then
writeln('HPDATECONVERT intrinsic returned error',status);


{Convert the 'date2_pac' to a YYMMDD integer format.}
{Default cutoff is assumed (i.e., 50) }
HPDATECONVERT(hp_dt_ascii_yymmdd_fmt,date2_pac,
outtype,date2_18,status);
if( status <> 0) then
writeln('HPDATECONVERT intrinsic returned error',status);

{compute the difference between the two dates}
HPDATEDIFF(outtype, date1_18,date2_18,temp_date,status,cutoff);

if( temp_date < 0) then
writeln(date1,' is #',temp_date,
'days later compared to ',date2_pac)
else if (temp_date > 0) then
writeln(date2_pac,' is #',temp_date,
'days later compared to ',date1)
else writeln(date1,' is same as ',date2_pac);


{offset date1_18 by the difference to get the }
{value of date2_18 through HPDATEOFFSET intrinsic.}
HPDATEOFFSET(outtype,date1_18,temp_date,date3_18,status,cutoff);
if( (date3_18 <> date2_18 ) and (status = 0)) then
writeln('Error Malfunction of HPDATEOFFSET intrinsic');

{Use the flexibility in converting the date to a display }
{string. Use '#0' to NULL terminate the format }
{specification string. }
fmt_pac := 'YY.ZMM.ZDD'#0;
print_len := 11; { 11 characters including #0 in fmt_pac }
HPDATEFORMAT(outtype,date1_18,fmt_pac,print_pac,print_len,status);
     if( status <> 0) then
writeln('HPDATEFORMAT intrinsic returned error',status);

writeln('The converted date is: ',print_pac);

{The following demonstrates how a byte array can be }
{passed in place of an integer. We are storing the }
{integer 230196 in a packed array of characters, which is}
{an equivalent of a byte array. We subsequently cast the }
{address of this array to an integer pointer to read the }
{integer value out of it. }
HPDATECONVERT(hp_dt_int_yyyymmdd_fmt,date1_18,
hp_dt_int_ddmmyy_fmt,fmt_pac,status);

$push, type_coercion 'storage'$
if( iptr_type (addr(fmt_pac))^ = date1 ) then
writeln( 'Program worked fine! ')
else writeln( 'Error, in using byte array parameters !');
$pop$

end.

The expected output from the program is:

230196 is #     2days later compared to 960121
The converted date is : 96.1.23
Program worked fine!
COBOL Example of HPDATECONVERT
       IDENTIFICATION DIVISION.
PROGRAM-ID. DATEINTR.
REMARKS. SAMPLE PROGRAM USING DATE INTRINSICS
DATA DIVISION.
WORKING-STORAGE SECTION.
*Date code for YYMMDD is 25, for YYYYMMDD is 38
01 INDATE-CODE PIC S9(9) VALUE 25.
01 OUTDATE-CODE PIC S9(9) VALUE 38.
01 SPLITYEAR PIC S9(9) VALUE 70.
01 OUTDATE-YYYYMMDD PIC X(8) VALUE SPACES.
01 INDATE-YYMMDD PIC X(6) VALUE SPACES.
01 STATUS-VAR.
05 S-INFO PIC S9(4) COMP VALUE 0.
05 S-SUBSYS PIC S9(4) COMP VALUE 0.

PROCEDURE DIVISION.
CONVERT-DATE-PARA.
DISPLAY 'Enter the date in YYMMDD format:'
ACCEPT INDATE-YYMMDD
CALL INTRINSIC "HPDATECONVERT" USING
INDATE-CODE
INDATE-YYMMDD
OUTDATE-CODE
OUTDATE-YYYYMMDD
STATUS-VAR
SPLITYEAR
IF S-INFO NOT = 0
PERFORM DISPLAY-ERROR
ELSE
DISPLAY "Convert Date in YYYYMMDD = " OUTDATE-YYYYMMDD
END-IF
STOP RUN.

DISPLAY-ERROR.
DISPLAY "HPDATECONVERT FAILED. ERROR = " S-INFO.
Feedback to webmaster