DATE, TIME, and DATETIME Fields

This chapter shows you how you can use DATE, TIME, and DATETIME fields in assignments, ACCEPT (validation), PRINT and SEND statements (Display).

DATE, TIME, and DATETIME Fields. 1

Introduction. 1

Section 1.  DATE fields. 1

Assignment To DATE Fields. 1

From Constants. 1

From Fields. 2

Initialising DATE fields with VALUE.. 3

Displaying DATE fields. 3

Assignment From DATE Fields. 3

Validating DATE Data. 4

Character input 4

Numeric Input 4

Date Arithmetic. 4

Date Comparisons. 5

Section 2.  TIME fields. 5

Section 3.  DATETIME fields. 5

Text Conventions. 5

 

Introduction

A field may be defined with type DATE, TIME, or DATETIME: -

DEFINE W DATA(

    Date1 DATE DPIC 'dd-MMM-yy',

    Date2 DATE DPIC 'dd.mmmm.yyyy',

    Date3 DATE DPIC 'dd/mm/yy',

    Date5 DATE DPIC 'yyyy.ddd',

    Date6 DATE DPIC 'ddd/yy',

    SpecialDate DATE VALUE 19631122);

    Time1 TIME,

    DateTime1 DATETIME );

 

By defining fields like this you make it clear to others, and to Jazz, the type of data that is in these fields: what it is used for, what values are valid, and how it should be displayed.   Jazz can ensure that it is set validly: for example

DEFINE X DATA(Date5 CHAR(9));

ACCEPT(W.Date5 = X.Date5) MESSAGE(Err.Msg);

will report an error if the CHAR(9) value in X.Date5 is not a valid date in format 'yyyy.ddd', such as 2016.060.

 

DATE and TIME fields are internally the same as INTEGER fields, in COBOL PIC S9(9) COMP, with initial value ZERO which means “No DATE (or TIME) value”  A DATETIME field is a combination: you can think of it as either a BIGINT field, or a GROUP containing a DATE and a TIME field. 

 

Whatever the DPIC (Display PICture), data in a DATE field is always stored as 8 digits: four year digits, two month, and two day.  Thus with value 2016.060 in X.Date5, W.Date5 is set to 20160229 (2016 is a leap year).

 

Refer to JazzLRM_Data.#Display_Options for information about DPIC.

 

TIME and DATETIME fields are not implemented yet, except for definition. TIME data will be stored as 9 digits: 2 for hour (00 to 23), 2 for minute (00 to 59), 2 for seconds (00 to 59), and 3 for milliseconds.

Section 1.  DATE fields

Assignment To DATE Fields.

A DATE field may be set from a constant, another DATE field, or (subject to various rules) a numeric or string field.   Date fields can also be set in Date Arithmetic.

From Constants

If you set a DATE field from a constant, then Jazz will interpret and validate the value when your program is checked, according to these rules: -

·                     Numeric constants, without any separator characters.  For example: -

W.Date1 = 20160228;

The value is in order year, month, and day no matter what DPIC is used. 

 

·                     Numeric constants, with single separator character “.” or “/”.  If there is only a single separator character then the value is interpreted as an ordinal date, with the part before the separator being interpreted as year, and the part after the separator being interpreted as the day value from 1 to 366 (366 if a leap year).  If the year is less than 100, then the current century is added, as below.  The separator can be either “.” or “/”.  Thus

W.Date1 = 18.300;

#568 I Date Value is 27 Oct 2018

W.Date1 = 2018/300;

#568 I Date Value is 27 Oct 2018

The ordinal date is interpreted as a string, so leading zeros don’t have to be given:  18.25 is interpreted as day 25, not as day 250.

W.Date2 = 18.25;

#568 I Date Value is 25 Jan 2018

 

·                     Numeric constants with two separator characters.  For example

W.Date1 = 04/3/2018;

#568 I Date Value is 04 Mar 2018

W.Date1 = 4/3/18;

#568 I Date Value is 04 Mar 2018

To resolve ambiguity between year and month the field’s DPIC is used. W.Date1 .has no explicit DPIC and so has the default DPIC 'dd mmm yy', so day comes before month.  W.Date2 has American-style DPIC 'mm dd yy'  and so 4/3 is interpreted as 3rd April, not 4th March.

W.Date2= 4/3/18;

#568 I Date Value is 03 Apr 2018

Note that the DPIC is used only to get the order of the sections Day, Month, and Year.  Even with DPIC 'dd mmm yy' you can give the month as a number, while with DPIC 'dd mm yy' you could give the month as “Jan” etc.  You can give more or fewer spaces, you do not have to give exactly the layout of the DPIC.

 

The date value is validated: for example: -

W.Date1 = 20170229;  [Not a leap year

#568 E Date Value invalid: Day Invalid

 

·                     To reset a date to its initial value, or to zero indicating that the field contains no date, use

            W.Date1 = JAZZ.$Init;

or

            W.Date1 = JAZZ.$Null;

(You’ll simply write $Init or $Null, leaving it to Jazz to insert the qualification)

 

·                     String constants. With a string value the value is checked as follows: -

1.         The string is split into parts, based on the separator character.  Jazz scans the string for characters {"/", "-", ".", " "} and the first of these characters found is used as the separator character.  With value

Date1 DATE DPIC 'dd-MMM-yy', …

W.Date1 = '27 May 17';

the blank between 27 and May is used as a separator, even though the DPIC uses “-”.  Both separator characters must be the same, so

W.Date1 = '27 May-17';

is invalid.

 

2.                  If there is no separator character the string is interpreted as an eight-digit number, as described above.

3.                  If there are only two parts, then the date is interpreted as an ordinal date, i.e. a year number followed by day-of-year.  Thus 2018.300 => 27th October, 2018.  The same rules as above for numeric constants are followed: the century may be omitted, and leading zeros for the day part are not necessary:  '18.25' is interpreted as day 25, not day 250, so this means 25th January 2018.

 

4.                  The DPIC is used to determine the order, in cases where this is ambiguous.  Thus with a value

W.Date1 = '4 3 17';

does this mean the 4th of March 2017 (British), or the 3rd of April 2017 (American), or the 17th of March 2004 (possibly Japanese)?  The DPIC resolves this ambiguity as described for numeric constants with separators.

From Fields

You can set DATE fields from

·         another DATE field,

·         an INTEGER field

·         a DECIMAL field with at least 8 digits and no decimal fraction

·         a DECIMAL field defined DECIMAL (7,3) or DECIMAL(5,3), or

·         a CHAR or VARCHAR field. 

 

If the source type is not DATE then it is recommended that data is assigned using an ACCEPT statement: for example
           
ACCEPT (W.Date1 = W.DecimalField);
instead of using a simple assignment
            W.Date1 = W.DecimalField;

In both cases Jazz will check the input, but errors may not be reported unless ACCEPT is used.

 

Rules are as described above for assignments BUT you need to be careful to ensure that DECIMAL fractions are handled as you want.  For example: -

            W.Date1 = '18.25';  means the 25th day of [20]18.

            W.Date1 = 18.25; interprets “18.25” as a string, and gives the same value.

Both assign the 25th day of January to the date.  However DECIMAL fractions are handled according to the normal rules of maths.  Thus

            DNbr2 DECIMAL(7,3),

            W.DNbr2 = 2018.25; 

If you follow this with an assignment to a date field: -

            W.Date1 = W.DNbr2;

the date is not the 25th January, it is some time in September.  The first assignment is a normal arithmetic assignment: there’s nothing in it to say that this value is intended to be a DATE, so it assigns 2018 and 25/100 to W.DNbr2, and is identical in value to

            W.DNbr2 = 2018.250; 

To have the fractional part interpreted as days-of-the-year you must write leading zeros and avoid fractions larger than 366.

W.DNbr2 = 2018.025;  [25th Jan

W.Date1 = W.DNbr2;

·         Date values can also be set with an expression of the form  Date1 = Date2 +/- value, for example

W.Date1 = W.Date2 + 30;

See Date Arithmetic below for more information.

Initialising DATE fields with VALUE

Like other fields a DATE field can be defined with an initial value: -

DEFINE W DATA(

    Date1 DATE DPIC 'dd mmm yy' VALUE 20180304,

#568 I Date Value is 04 Mar 2018

Initial values may be an eight-digit number, in format yyyymmdd, as above, or a decimal number which will be interpreted as an ordinal date: -

    DateG DATE VALUE 18.300,

#568 I Date Value is 27 Oct 2018

or a string value giving a date as if printed with the field’s DPIC: -

    DateB DATE DPIC 'mm dd yy' VALUE '4 3 18',

#568 I Date Value is 03 Apr 2018

In all cases message #568 will tell you how the date is interpreted, to avoid confusion between American and other date forms, and the COBOL fields will be an integer (COMP S9(9) VALUE 20180304 if the date is 4th March 2018).

Displaying DATE fields

When a DATE field is printed, or displayed on a screen, then it is formatted according to its DPIC.  Refer to JazzLRM_Data.#Display_Options for information about DPIC.

Assignment From DATE Fields.

A DATE field may be assigned to

·         Another DATE field

·         A numeric variable

Assigning a DATE to a number will assign an eight-digit numeric value such as 20180124.  A message will be produced if the numeric variable has fewer than 8 digits.  If the target number has a suitable DPIC then the value will be easy to interpret: for example

DEFINE X DATA(Number INTEGER DPIC '9999,99,99');

DEFINE W DATA(Date1 DATE DPIC 'dd-MMM-yy');

X.Number = W.Date1;

PRINT (W.Date1, X.Number);

resulting in output like this: -

*-Date1-* *-Number-*

29-Feb-16 2016,02,29

 

·         A CHAR or VARCHAR variable.  The date field will be formatted to a string according to its DPIC.  For example: -

DEFINE W DATA(

    Date2 DATE DPIC 'dd.MMMM.yyyy');

DEFINE X DATA(

    Date2 CHAR(17);

W.Date2 = 20171217;

X.Date2 = W.Date2;

assigns value '17.December.2017' to X.Date2.

 

Refer to JazzLRM_Data.#Display_Options for information about DPIC.

Validating DATE Data

When variable data is assigned to a DATE field it is recommended that you use ACCEPT, rather than a simple assignment, as this will validate that the assigned data is actually a date, setting $Error and producing messages when the source field cannot be converted to a valid date.  Refer to JazzLRM_Accept for more information about ACCEPT.  As with any other ACCEPT statement, several validations and assignments may be combined into one statement: -

ACCEPT(W.Date1 = X.Date1, W.Date5 = X.Date5) MESSAGE(Err.Msg);

and assignment targets (W.Date1, W.Date5 in the example above) may be omitted if the target is implied or there’s no assignment because a DATE field is being validated in place.

Character input

If the source fields (X.Date1, X.Date5 in the example above) have type CHAR or VARCHAR then if possible their value is converted into a date with these rules: -

1.                  Firstly Jazz looks for possible separator characters: “/”, “-”, “.”, or “ ”.  The first of these to be found is chosen as the separator character, even if it is not the leftmost.  Thus if the string contains “12 3/4” then Jazz will use “/” as separator because it looks for this first. 

 

2.                  The string value is then broken into parts using the separator character.  Thus the string above would be broken into two parts, “12 3” and “4”.   More realistically,

“12345678bbbb”    =>    1 part, “12345678”

“18.155”          =>    2 parts, “18”, “155”

“1/2/3”           =>    3 parts, “1”, “2”, “3”
           

3.                  If one part, then the string is interpreted as an eight digit number in format yyyymmdd.   12345678 is invalid: 56 is greater than 12, and no month has 78 days.  However a value 20180325 would be valid.

4.                  If two parts the string value is interpreted as an ordinal date.  For year values less than 100 the century added, thus 10 becomes 2018.  The day-of-year must be a number from 1 to 366.  Thus 18:155 is the 155th day of 2018, i.e. 4th June 2018.

5.                  If three parts, then the DPIC of the target field is used to give the relative order of day, month, and year.  Thus with
            DPIC 'dd mmm yyyy'             :           “1/2/3” means 1st Feb, 2003
           
DPIC 'mm dd yy'        :           “1/2/3” means 2nd January 2003.
Note that the Jazz interprets the date as flexibly as possible, so that you don’t can give a numeric month when the
DPIC specifies an alphabetic abbreviation or the full month name, and vice versa.   Day must be a number from 1 to the maximum for the month, month must be a number from 1 to 12 or one of the valid month abbreviations or names, and year must be a number from 100 to 9999.  If the year is < 100, the current century is added.  None of the numeric values may be negative.

 

6.                  If there are four or more parts, then the value is invalid.

Numeric Input

A number is first range-checked: it must not be less than 10000101  (1 Jan 1000) or greater than 99991231  (31st December 9999).  If it survives this check, then the value of Month (digits 5-6) and Day (7-8) are checked as above.

Date Arithmetic

You can write simple date arithmetic assignments of the form

            Date1 = Date2 operator Value;

for example

W.Date1 = W.Date2 + 30;

 

To increase or decrease a date you can use the assignment operators += and -=.  Thus

            W.Date1 += 30;

is equivalent to

W.Date1 = W.Date1 + 30;

 

The operator may be + or -, but no other (multiplication (*) or division (/)).

 

The difference value may be a constant or a field.  Fields must have one of the types valid for assignment to a date.  Difference values are interpreted as described above for date assignment, being broken into parts by the separator character, except that any (or all) of the year, month, and day sections may be zero.  Thus

W.Date1 = W.Date2 + 2.300;

adds 2 years and 300 days to W.Date2. With three-part dates DPIC resolves the ambiguity between British-form dates (Day, Month, Year) and American-form dates (Month, Day, Year), so that if W.Date2 has DPIC 'mm dd yy' then

      W.Date1 = W.Date2 + 2/3/0;

adds two months and three days to W.Date2.

 

The assignment may only have a single operator and may not use parenthesis.  Thus

W.Date1 = W.Date2 + W.NBR * 2;

is not valid.

 

The logic of Date arithmetic is

1.                  The Date Difference value is converted to a GROUP with four SMALLINT values representing the number of years, months, days-of-month and days-of-year to be added or subtracted.  This value is like a DATE field except that any or all parts may be zero.

2.                  Logic is as follows.

a.      Add/Subtract years

b.      Add/Subtract months  

If months < 1 (-) then

Subtract 1 from years, add 12 to months

elseif Months > 12 (+) then

Add 1 to years, subtract 12 from months

c.      Set days-in-Feb to 29 if a leap year, else 28

d.      Add/Subtract Days

If Days < 1 (-) then

Subtract 1 from months

If months < 1 then

Subtract 1 from years, add 12 to months

Add days-in-month to Days

Elseif Days > days-in-month (+) then

Subtract days-in-month from Days

Add 1 to months

If months > 12 then

Add 1 to years, subtract 12 from months

3.                  If the date difference was given as a simple number, or an ordinal date, then the days part will be in the days-of-year field.  With date assignment,

                        W.Date1 = 18.155;

W.Date1 is set to 04 Jun 2018, but adding 155 days to a date is not the same as adding 4 days and 6 months, as the result of date arithmetic depends on the starting date to which the difference is added or subtracted.

Date Comparisons

DATE fields can be used in comparisons.  All the usual comparison operators =, <>, >, >=, <, <=, are available.

Section 2.  TIME fields

Not yet implemented, except for definition.  TIME data will be stored as 9 digits: 2 for hour (00 to 23), 2 for minute (00 to 59), 2 for seconds (00 to 59), and 3 for milliseconds.  

 

As with DATE fields, assignment of constant data will be validated by Jazz when the program is checked, and variable data can be validated with ACCEPT. 

 

DPIC formats for TIME data will be defined. 

 

Built-in functions $Hour, $Minute, $Second, and $MSecond will extract the various parts of a time.

 

TIME arithmetic will be supported: details to be defined.

 

Section 3.  DATETIME fields

Not yet implemented, except for definition.  A DATETIME field is like a GROUP defined

    DTGroup GROUP,

        DatePart DATE,

        TimePart TIME,

        end GROUP);

except that adding or subtracting time from Timepart does not affect Datepart, whereas adding or subtracting time from a DATETIME field can change the date part of the DATETIME field.

 

Assignment between DATETIME and DATE or TIME fields is permitted: -

·         Datetime = Date;   Datepart set, Timepart is set to 00:00:00:000

·         Datetime = Time;   Date set to 0, Timepart set.  E-level message

·         Datetime &= Time; Datepart unchanged, Timepart set.

·         Date = Datetime;  Datepart is assigned, Timepart ignored

·         Time = Datetime;  Timepart is assigned, Datepart ignored.

Text Conventions  

Some material is like this, written in the normal text, but coloured green. This is material that hasn’t been implemented yet. As this material is implemented the text is reviewed, changed as necessary, and changed to normal text colour.