A White Paper from the X/Open Base Working Group.
Version 1.4 Last update June 8 1998
Abstract
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.
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.
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).
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 ]
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
.
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.
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).
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.
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 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.