What is UNIX

Year 2000 :The Millennium Rollover

Practical advice for users of the Single UNIX® Specification

A White Paper from the X/Open Base Working Group.

Version 1.4 Last update June 8 1998

Abstract

Many existing computer programmes use dates represented by only two digits for the year value rather than the full four digits (for example 84 rather than 1984). This works fine for years in the range 1900-1999 (on some systems this range may be limited to 1970-1999) but will yield unpredictable results when used with years outside of this range. We will all experience the results of this software problem in less than 1000 working days time, that is in January 2000.

This white paper outlines the problem, give some general advice on how to prepare, and gives practical advice on how to use interfaces within the Single UNIX Specification to cope with the millennium rollover.

Sample test programs to check for rollover handling are available from The Open Group test tools download page at http://www.opengroup.org/testing/downloads.html.


1.1 What is the problem, and why did it occur?

In its simplest terms this is a programming error in that data has been processed and stored in log files and databases using a two digit format for the "year" value, that is 99 rather than 1999. This has occurred mainly since programmers have attempted to minimise the amount of expensive disk storage and memory used. Calculations based on the year value in its two digit format are likely to yield unspecified results once the value rolls over to "00" in the year 2000.

Many COBOL programmers have tended to mix data and control information, usually to save space in databases. In particular, for example, the "year" field would be a date if numerically larger than say 20, and a command or EOF flag if from 0 to 19. So, rollover will potentially cause great excitement for some database users, much more than wrong dates.

Some operating systems have taken a different approach to handling two digit dates by adopting a sliding window. Depending on the size of the sliding window this can cause other problems, and is generally not suitable for applications considering large date ranges, such as pension funds.

The solution proposed in this white paper takes an alternative approach, and is a workaround to maintain backwards compatibility for existing users. The proper solution is to specify all years in four digits.

1.2 How can we prepare and adapt to this problem?

Examine your source code and look for date usage within the code. Update your source code so it can handle data in the range 1900-2099. If the system you are using has a 32-bit signed time_t be aware that problems may occur as soon as the year 2038. If this matters you should consider upgrading to a platform supporting 64-bit signed time_t or 32-bit unsigned time_t values.

Look for any log files that store dates in two digit format, examine how the data is processed. Consider converting such log files to use four digit format. Alternately adopt an approach for interpreting two digit date formats (see the Advice to Implementors section in getdate() below).

Test your source code by looking for usage for the Single UNIX Specification interfaces noted below, setting the date on your system to the year 2000, and executing the code (Warning it is recommended that such tests are run on a testbed system and not on a live production system).

1.3 The Single UNIX Specification and the Millennium Rollover

There are some interfaces within the Single UNIX Specification which can use two digit notation for year values, these are highlighted below together with recommendations on how the two digit dates should be interpreted.

[ Please note that the Future Directions identified in this document have been applied in Version 2 of the Single UNIX Specification ]


2. API usage

2.1 getdate()

struct tm *getdate(const char *string);

The X/Open CAE Specification, System Interfaces and Headers Issue 4, Version 2 (September 1994), in the entry for getdate() on page 231, states the following with respect to the format code %y:

        "%y     year within century (00-99)"
Suppose there is a line of the form "%m/%d/%y" in the template file, and a call is made:

    struct tm * p_tm;
    p_tm = getdate( "11/22/02" ); 
It is not specified what would be represented in the struct tm for the century. This could be interpreted as either 11/22/1902 or 11/22/2002 since the implementation does not know which "century" this is to refer to.

Advice to programmers: Use the %Y field descriptor which defines year as a four digit field (ccyy).

Advice to implementors: Define %y such that when a century is not otherwise specified, values in the range 69-99 refer to the twentieth century and values in the range 00-68 refer to the twenty-first century. This is consistent with the touch command within the X/Open CAE specifications.

Future directions: Issue 5 of the System Interfaces & Headers CAE Specification (February 1997) adds the %C specifier to the interface to denote the century, and interprets the %y specifier in the absence of a century as per the advice to implementors section above. An application usage note is added recommending use of %Y over %y.

2.2 strptime()

char *strptime(const char *buf, const char *format, struct tm *tm);

The X/Open CAE Specification, System Interfaces and Headers Issue 4, Version 2 (September 1994), in the entry for strptime() on page 615, states the following with respect to the format code %y:

        "%y     is the year within century [00,99]; leading zeros are
                permitted but not required"
Suppose that the following call is made:

    struct tm thetime;
    strptime( "11/22/02", "%m/%d/%y", &thetime );
It is not specified what would be represented in the struct tm for the century. This could be interpreted as either 11/22/1902 or 11/22/2002 since the implementation does not know which "century" this is to refer to.

Advice to programmers: Use the %Y field descriptor which defines year as a four digit field (ccyy).

Advice to implementors: Define %y such that when a century is not otherwise specified, values in the range 69-99 refer to the twentieth century and values in the range 00-68 refer to the twenty-first century. This is consistent with the touch command within the X/Open CAE specifications.

Future directions: Issue 5 of the System Interfaces & Headers CAE Specification (February 1997) denotes the interpretation of the ranges in the advice to implementors section above.


3. Commands Usage

3.1 date

The following excerpt from the OPERANDS section of the date command in the X/Open CAE Specification, Commands & Utilities Issue 4, Version 2 (September 1994), page 247, states:

       EX      mmddhhmm[yy]

Attempt to set the system date and time from the value given in the
operand.  This is only possible if the user has appropriate privileges and
the system permits the setting of the system date and time.  The first mm
is the month (number); dd is the day (number); hh is the hour (number,
24-hour system); the second mm is the minute (number) and yy is the last
two digits of the year and is optional.  

The yy specifier is a two digit specifier to the year and thus does not denote the century.

Advice to programmers: Consult your supplier for their handling of the yy specifier.

Advice to implementors: Define yy such that if century is not specified, then values in the range [69-99] refer to years in the twentieth century (1969 to 1999 inclusive), and values in the range [00-68] refer to years in the twenty-first century (2000 to 2068 inclusive). This is consistent with the touch command within the X/Open CAE specifications.

Future directions: Issue 5 of the Commands & Utilities CAE Specification denotes the interpretation of the ranges in the advice to implementors section above, and also adjust the synopsis for this command such that century handling is added as follows:


	EX	mmddhhmm[[cc]yy]

Attempt to set the system date and time from the value given in the
operand.  This is only possible if the user has appropriate privileges and
the system permits the setting of the system date and time.  The first mm
is the month (number); dd is the day (number); hh is the hour (number,
24-hour system); the second mm is the minute (number); cc is
the century and is the first two digits of the year (this is optional),
yy is the last two digits of the year and is optional.
If century is not specified, then values in the range [69-99] refer to
years in the twentieth century (1969 to 1999 inclusive), and values in the 
range [00-68] refer to years in the twenty-first century (2000 to 2068 inclusive). 

3.2 prs, get

The following excerpt from the OPTIONS section of the prs and get commands in the X/Open CAE Specification, Commands & Utilities Issue 4, Version 2 (September 1994), page 588 and page 361 respectively, states:

-c cutoff

indicates the cutoff date-time, in the form:

YY[MM[DD[HH[MM[SS]]]]]

The YY specifier is a two digit specifier to the year and thus does not denote the century.

Advice to programmers: Consult your supplier for their handling of the YY specifier.

Advice to implementors: Define YY such that values in the range 69-99 refer to the twentieth century and values in the range 00-68 refer to the twenty-first century. This is consistent with the touch command within the X/Open CAE specifications.

Future directions: Issue 5 of the Commands & Utilities CAE Specification denotes the interpretation of the ranges in the advice to implementors section above. The prs and get commands are the only commands where users will not be able to specify a full four digit date, and this is due to the existing file format limitations.

3.3 touch

IEEE Standard POSIX 1003.2 (Shell & Utilities) defines the "-t time" option as only extending to at least midnight January 1 Year 2000.

Advice to programmers: Consult your supplier for their handling of the -t option.

Advice to implementors: Define -t to handle times at least up to the year 2038.

Future directions: Issue 5 of the Commands & Utilities CAE Specification changes the text as follows as an extension over IEEE Std 1003.2:

On the touch manual page in the OPTIONS section "-t time" change the year 2000 in "midnight 1 January 2000 UCT" to be 2038 and make the wording less ambiguous as follows:

"The range of valid times past the Epoch is
implementation-dependent, but will extend to at least
the time 0 hours, 0 minutes, 0 seconds, January 1,
2038, Coordinated Universal Time."


Read other technical papers.

Read or download the complete Single UNIX Specification from http://www.UNIX-systems.org/go/unix.

Copyright © 1997-1998 The Open Group

UNIX is a registered trademark of The Open Group.