The purpose of this document is to provide information to developers of software for Sun systems when writing or updating code that inputs, manipulates or outputs dates. The specific emphasis is to enhance conformity with the SunSoft year 2000 Compliance Statement.
A product certified as being year 2000 compliant will not produce errors in date data related to the year change from December 31, 1999 to January 1, 2000 and date representation by the product will be accurate into the future, until the year 2037. The handling of leap years will be done correctly.
The compliant product will define specific, non ambiguous representation, handling, and interpretation of centuries represented by two digits if such representation is allowed by the product.
The most recent version of this compliance statement can be found at http://www.sun.com/y2000/statement.html. [6]
All guidelines from POSIX [1] and X/Open [2] [3] must be taken into account. Please check these references as they have changed and will change again over time . As this document may not reflect the most recent changes, be sure that the most recent version is referenced. The basic guidelines are:
The criteria for compliance is to give a compliance status with reference to options One, Two or Three. Note that noncompliance is not an option. All products must state to which option the product is compliant. The goal for all products is Option One. Options Two and Three should be considered as stepping stones to Option One.
Option One: Software is considered to be Option One compliant if all dates are explicitly and unambiguously represented when used at input, internal manipulation, and output. Option One compliant software must handle leap years correctly.
Note: Using 1XX (the number of years since 1900 used in struct tm, field tm_year) to represent the year 20XX in input/output is ambiguous; however, using a time_t to manipulate dates is OK.
Option Two: Software is considered to be Option Two compliant if all dates are interpreted according to the two-digit rule from X/Open: 00 through 68 represent 2000 through 2068; 69 through 99 represent 1969 through 1999. This rule is taken directly from the X/Open guidelines [3].
Option Three: Software is considered to be Option Three compliant if all dates are expressed with a two-digit year and are interpreted as either 1900s or 2000s according to a convention (which differs from Option Two) that is explained explicitly in the user documentation.
Note -- The use of 1XX to represent the year 20XX in input or output is not acceptable at any option of compliance.
Look at the year 2000 ABI tools at http://www.sun.com/sunsoft/dev-progs/abi/ . The tools can be downloaded and there is also comprehensive documentation available.
The existing date- and time-related sections of the "Developer's Guide to Internationalization" [5] remain valid and are the basis for year 2000 coding style. Properly internationalized code never needs to reference fields from a date in struct tm form. Continue to use the supplied OS date routines. All new code should adhere to Option One compliance. Do not implement new date routines unless there is a compelling reason to do so. Remaining consistent will make fixing any y2038 problems in the future easier.
For bulletproof leap year calculations in C and C++ use #include <tzfile.h> and use the isleap(y) macro. It is not a documented interface. Make sure that this particular macro is used and not other inferior isleap macros. The macro follows this simple rule:
Note -- Year 2000 is a leap year.
strptime()
When validating or manipulating dates remember that strptime() is not the right function - use getdate(). Only use strptime() if the date format is a single fixed format and requires no validation. When using strptime(), be sure to check that the return value is not NULL and that the return value points to the character following the last character expected for the date ('\0' if the entire string should match).
getdate()
Use getdate() to validate dates. It parses according to the user-supplied template and has better error handling for inaccurate input. It can handle a list of possible formats contained in /etc/datemsk. This file is specific to a machine and hence could be localized. Also note that if /etc/datemsk already exists then it is being used by other system utilities.
The C, C++, Fortran 90, and Ada compilers have no known year 2000 problems. The Pascal compiler date() function uses a two-digit year. A new function, fdate(), will be year 2000 compliant. The FORTRAN 77 compiler has a known limitation when using the VMS date extension. It uses the PDP11 date format, which has a two-digit year. The use of an alternative new date function, DATE_AND_TIME, is recommended. Also, the DATE and IDATE routines will produce two-digit years with extra 0s or digits (for example, 100 for the year 2000). A patch is planned to fix this.
For more detail please refer to "Solaris and the year 2000" [4]. This document contains the details and applicable version numbers of all year 2000 related fixes. There are issues with strptime(), strftime(), mktime(), asctime(), date, touch, sccs, listen, and at. This is not a full list; see [4] for complete details.
Avoid using struct tm fields directly - code that accesses tm_year must be carefully examined. A common error is to print the tm_year field of a struct tm without mod 100 or with the century forced to 19.
Bad example:
(void) fprintf(stderr, "%.2d/%.2d/%.2d ",
(tmp->tm_mon + 1), tmp->tm_mday, tmp->tm_year);
/* FAILS: needs tmp->tm_year % 100 or better yet use strftime(),
/* cftime(), or ascftime().
Bad example:
sprintf(str, "19%2d", now->tm_year);
Good example:
#include <tzfile.h>
sprintf(str, "%4d", now->tm_year + TM_YEAR_BASE);
/* or better yet use strftime(), cftime(), or ascftime().
Code that validates dates must allow years up to 2038.
if(thisyear < 1970 || thisyear > 2000) {
should be:
if(thisyear < 1970 || thisyear > 2037) {
or:
if(thisyear < 1970 || thisyear > 2038) {
if the first days of 2038 are permitted. However, using getdate() or strptime() to input dates is even better.
Any use of the %y format in the strftime(), cftime(), or ascftime() functions and the date command should be examined carefully for strings such as "19%y" that force century; or try to use %Y instead.
The use of %y in the getdate() datemsk file or as an argument to strptime() should be checked to see if year can be changed to four digits by using %Y. %C%y should be replaced by %Y if a four digit date is required.
A locale's appropriate date and time representation is usually preferred and handles year 2000 issues automatically. This is achieved by using locale specific conversions such as %c.
Any code that compares times for timeouts or the like needs to be checked carefully so that the comparison does not break when each time is on a different side of Jan 1, 2000 00:00:00.
Time represented as time_t (number of seconds since the EPOCH) or days since a fixed point in time will usually work in most calculations. However, watch out for overflows when manipulating time_t.
Watch out for time comparisons of a time representation that has a two-digit year field.
Search source code for strings like time, date, tm_year, 19, 1900, 20, %y, strptime, strftime, cftime, ascftime, getdate, ctime, difftime, gettimeofday, gmtime, localtime, mktime, settimeofday, tzset, tzsetwall, and utime. Study the results carefully.
Use a documented and agreed convention to mark source code as "checked", for example, Y2000 checked by <name><date>
When using date with the %y format watch for forcing the century to 19 - date '+%a %H:%M %h %d, 19%y' . Try to avoid two-digit year %y such as date +%y-%m-%d . Use %Y, for example date +%Y-%m-%d if it does not break compatibility.
troff scripts with \n(yr are almost certain violations if not fixed, as yr is years since 1900 and is used as a two-digit year.
For example, in addition to the 19\n(yr problem in bug reports, .ds)Y\n(mo/\n(dy/\n(yr will fail, printing 1/1/100 in year 2000.
Be careful with year 2000 testing!
This list should not be considered complete or exhaustive. It is to be used as a guideline only. Each product/area should be addressed independently.
Leap Year Checks
Hardware Checks
These tests should be applied to applications as well as hardware to verify that there is no hidden hardware interdependence.
Interprocess Communication Questions
If the product uses synchronization protocols to communicate, does it work correctly before, during, and after the roll-over?
If the product uses protocols to communicate and the protocols include date data, does it use the four-digit year format?
If the product accepts date data from another application, does it accept four-digit year data?
Data Integrity Questions
[1] International Standard ISO/IEC 9945-1: Second Edition 1996-07-12 (ANSI/IEEE Std 1003.1 1996 Edition) Information Technology - Portable Operating System Interface (POSIX) - Part 1: System Application Program Interface (API) [C Language] ISBN 1-55937-573-6 Copies may be purchased from Global Engineering Documents, 1-800-854-7179. Last quoted price, $185.00 plus shipping.
[2] X/Open System Interfaces and Headers Issue 5. See http://www.rdg.opengroup.org/public/tech/base/year2000.html
[3] "Year 2000: The Millennium Rollover - Practical advice for users of the Single UNIX Specification" v1.2 1997/06/09. See http://www.rdg.opengroup.org/public/tech/base/year2000.html
[4] "Solaris and the year 2000" available at http://www.sun.com/y2000/y2000-external.html.
[5] "Solaris Internationalization Guide For Developers", for Solaris 2.6, pa rt number 802-5878-10 or 805-0669 (Japan). "Developer's Guide to Internationalization", for Solaris 2.5.1, part number 802-1950-10 or 802-3454 (Japan). Earlier versions are out of print. Both are available from http://sunexpress.usec.sun.com/
[7] International Standard ISO 8601: 1988 as amended by Technical Corrigendum 1. Published 1991-05-01. Data elements and interchange formats - Information interchange - Representation of dates and times. Copies may be purchased from Global Engineering Documents, 1-800-854-7179. Last quoted price, $45.50 plus shipping.
[8] Federal Information Processing Standards Publication FIPS PUB 4-1 1988-01-27. Representation for calendar date and ordinal date for information interchange. Published by the National Institute of Standards and Technology (NIST). See http://www.itl.nist.gov/div897/pubs/fip4-1.htm .
Last Updated: Mon Aug 4 11:09:16 PDT 1997