Programming For the Year 2000 HP-UX Standard C Libraries White Paper

LEGAL NOTICES

The information in this document is subject to change without notice. Hewlett-Packard makes no warranty of any kind with regard to this manual, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose.

Hewlett-Packard shall not be held liable for errors contained herein or direct, indirect, special, incidental or consequential damages in connection with the furnishing, performance, or use of this material.

Warranty. A copy of the specific warranty terms applicable to your Hewlett-Packard product and replacement parts can be obtained from your local Sales and Service Office.

Restricted Rights Legend. Use, duplication, or disclosure by the U.S. Government Department is subject to restrictions as set forth in subparagraph (c) (1) (ii) of the Rights in Technical Data and Computer Software clause at DFARS 252.227-7013 for DOD agencies, and subparagraphs (c) (1) and (c) (2) of the Commercial Computer Software Restricted Rights clause at FAR 52.227-19 for other agencies.

HEWLETT-PACKARD COMPANY
3000 Hanover Street
Palo Alto, California 94304 U.S.A.

Copyright Notices. (C)copyright 1996 Hewlett-Packard Company, all rights reserved.

Reproduction, adaptation, or translation of this document without prior written permission is prohibited, except as allowed under the copyright laws.

Trademark Notices. UNIX is a registered trademark in the United States and other countries, licensed exclusively through X/Open Company Limited. X/Open is a trademark of X/Open Company Limited in the UK and other countries.

First Edition: December 1996 (1.1)
Second Edition: January 1997 (1.4)
Third Edition: February 1997 (1.5)
Fourth Edition: February 1997 (1.9)

 

Contents


1. Overview

1.1. Executive Summary

1.2. Terminology

2. Changes for the Year 2000 in the Standard C Libraries

2.1. Overview of the changes

2.2. How to Tell if You Are Impacted by the Changes

2.3. Comparison of the Old vs. Year 2000 behavior

3. Creating Year 2000 Safe Software

3.1. Building Year 2000 Safe Software

3.2 Obtaining the Year 2000 Behavior in Release 10.30

3.3. Obtaining the Year 2000 Behavior in Releases Prior to 10.30

3.4. Moving Your Pre-10.30 Year 2000 Safe Software Forward

3.5. Interoperability warning

3.6. Special Considerations for Libraries

3.7. Special Considerations for Locales

3.8. Testing Your Software

3.9. Requirements for Year 2000 Safe Software

3.10. Recommendations for Applications

4. Handling of Dates Past the Year 2037

4.1. Overview of the Problem (the time_t issue)

4.2. Future Directions for 64-bit Systems

4.3. Future Directions for 32-bit Systems


1. Overview

1.1. Executive Summary

Changes were made in HP-UX 10.30 to enable HP-UX to support dates beyond the year 2000. This white paper is intended to aid the reader in determining if their software has a dependency upon any of the changes made to the Standard C Library (libc), and to provide guidelines for making your software ready for the year 2000 with respect to libc. Note that other changes have been made to HP-UX (commands, applications, etc.) other than these libc changes, and you should consult the appropriate documentation for these changes.

Many pieces of software indicate a year by using only the two least significant digits of year; the interpretation of 2-digit years as always indicating dates in the 20th century has worked for most applications. When we have to deal with years in the 21st century, this assumption is no longer makes sense. The changes to libc pertain to the interpretation of 2-digit year specifiers.

If you have already made changes to your software in response to prior information about the changes in libc (e.g., the HP-UX 10.30 Release Notes), then you have probably already addressed the coding issues mentioned in this document. However, you may want to look at this document for information on patches, and for information on potential interactions between components using different interpretations for two-digit years.

If you have dependencies upon the new behavior, or wish to ship software which is ready for the year 2000 on releases prior to 10.30, you should look at section 3.3 information on coding to the pre-10.30 2000 Rollover patches for libc.

If you wish to develop year 2000 safe applications for any revision of the HP-UX operating system, you should read this paper. This paper is also intended for software developers who are releasing software which has been recompiled on release 10.30 of HP-UX, since the year 2000 changes are the default behavior on release 10.30.

This paper contains technical descriptions of the behavior of the Standard C Libraries for HP-UX year 2000 changes. Previous versions of this document may have contained information about design alternatives which were not needed in the implementation and are not supported. This paper describes the functionality currently supported in the year 2000 safe releases of HP-UX.

1.2. Terminology

Year 2000 Safe:

Software which is "year 2000 safe" will operate in a well-defined, predictable manner when operating with dates beyond the year 2000, and will not contain defects related to the year 2000 rollover. Please see the year 2000 documentation for a more detailed definition of the year 2000 safe requirements.

Year 2000 Compliant:

A complete system (or a network of systems) is "Year 2000 Compliant" if all the software which is installed on the system is year 2000 safe Please see the year 2000 documentation for a more detailed definition of the year 2000 safe requirements.

Note that the term "year 2000 safe" applies to software components, and the term "Year 2000 Compliant" applies to systems (or networks of systems).

2. Changes for the Year 2000 in the Standard C Libraries

2.1. Overview of the Changes

Currently released implementations of getdate(3c) and strptime(3c) handled the input of the two-digit year in slightly different manners, which presents a problem for applications manipulating dates beyond the year 2000. Changes to getdate(3c) and strptime(3c) routines occur in release 10.30 to address these concerns.

The behavior of getdate(3c) and strptime(3c) are changing in a manner which may affect binary, source code, and data compatibility for binaries recompiling in release 10.30.

These two calls were determined by X/Open to be ambiguous with respect to handling the 2-digit year input. When X/Open reviewed getdate(3c) and strptime(3c), they decided upon a method of handling the input of the 2-digit year for the strptime(3c) and getdate(3c) calls. Hewlett Packard has adopted this strategy, which is summarized as follows:

Define %y 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(1) command.

See the white paper from the X/Open Base Working Group entitled "Year 2000: The Millennium Rollover (Practical Advice for Users of the Single Unix(r) Specification)", available from X/Open's web page at http://www.xopen.org/public/tech/base/year2000.html.

This behavior is also available in the form of patches for releases 10.01, 10.10, and 10.20. Patches are not available for release 10.00. Further information on the patches is given in section 3.3 of this document.

2.2. How to Tell if You Are Affected by the Changes

This is a behavior change which affects binary, source code, and data compatibility. The changes may affect executables which read input dates with 2-digit year specifications for dates between 00 and 68 using the getdate(3c) and strptime(3c) calls. Even if you don't call either of these routines, you may depend on other software which does.

It is very important that code which uses 2-digit year specifications to the getdate(3c) or strptime(3c) calls make plans for this change occurring in release 10.30, or your software may behave improperly due to these behavior changes. Even if you are not planning to run on 10.30 now, you should be aware that your software may behave unexpectedly when dealing with dates beyond the year 2000, due to the problems addressed in 10.30 and the year 2000 patches.

It is also very important to review your use of data which represents dates as two digits, particularly if more than one executable or machine can access that data (e.g., shared data accessed by machines which may be running different vendor's operating systems, or different versions of the HP-UX operating system. Be especially careful of that data which is read via the getdate(3c) and strptime(3c) calls, or other applications, functions, or libraries which depend upon these calls.

The changes will be picked up when software is recompiled on the 10.30 version of HP-UX and automatically picks up the new shared libraries. Software running on pre-10.30 systems will need to take specific steps to obtain this new behavior; this is outlined in a later section of this paper. Executables and dependent non-system shared libraries which were compiled on systems prior to 10.30 and are brought forward from the original release as a group will continue to experience the old behavior, in order to maintain binary compatibility. If any of the dependent shared libraries are recompiled on 10.30, undefined behavior may occur when trying to move the executable forward without recompilation and revision of source code to handle the new getdate(3c) and strptime(3c) behavior.

Performing the grep(1) command on your source code for the strings "getdate", and "strptime" will determine whether you need to perform a more detailed investigation. If you find occurrences of either string, then perform a grep on your getdate "template" files looking for the string "%y", "%D", "%c", or "%x", and perform grep on your source code looking for directives to strptime(3c) of the form "%y", "%D", "%c", "%x", "%Ec", "%Ex", "%Ey", or "%Oy". If you find any of these directives you will be affected if you read two-digit years in the range 00-68. If you only have binaries available, use nm(1) on the binary, and look for the symbols "getdate" or "strptime". If you do find these symbols, contact the binary provider for more information.

If you pass two-digit year specifications between modules, applications, or over the network, or if you store them in files, or rely upon only handling dates in the 20th century, you may also be affected by software which handles 2-digit year specifications differently.

If you depend upon libraries (shared or archive) which call getdate(3) or strptime(3) you may be affected. To determine if the libraries you depend upon are affected, perform the nm(1) command on the library and look for the symbols "getdate" and "strptime". If the libraries reference these symbols, you need to contact the library creators to determine if they are ready for the year 2000.

2.3. Comparison of the Old vs. Year 2000 behavior

Pre-10.30 versions of getdate(3c) either disallowed 2-digit year specifiers less than 69 (in pre-10.10 systems), or relied upon the value of the system clock to determine which century the 2-digit year was in (10.10, 10.20). Former versions of strptime(3c) always assumed the 20th century.

Note that the range of the dates which are processed by the getdate(3c) call are limited to the range of the time_t data type, which is typedef'ed as a 32-bit signed quantity on 32-bit machines. Therefore, the operating range of getdate(3c) and strptime(3c) is from December 13, 1901 to January 19, 2038.

Prior to installing the patches to obtain the year 2000 behavior, the behavior of getdate(3c) is as follows:

On systems with the year 2000 patches installed, or on releases 10.30 and later, both getdate(3c) and strptime(3c) have changed to adopt the following interpretation for 2-digit year input (YY) when the century has not been otherwise specified:

69-99 <maps to ---> 1969-1999
00-68 <maps to ---> 2000-2068

This information on the old behavior vs. year 2000 safe behavior for two digit year specifiers is summarized in the following table, which uses the inputs '03' and '99' as examples of input in each category (INV indicates that the conversion is invalid):

API/Release

Old behavior system clock 1900's

Old behavior systems clock 2000's

New behavior 10.30 and patches (not dependent upon system clock)

Getdate (3c) release 10.01 and prior

"99" -> 1999
"03" -> INV
"99" -> 2099
"03" -> 1903
"99" -> 1999
"03" -> 2003

Getdate (3c) release 10.10 and 10.20

"99" -> 1999
"03" -> 1903
"99" -> 2099
"03" -> 2003
"99" -> 1999
"03" -> 2003

strptime(3c) releases 10.01, 10.10, and 10.20

"99" -> 1999
"03" -> 1903
"99" -> 2099
"03" -> 1903
"99" -> 1999
"03" -> 2003

 

3. Creating Year 2000 Safe Software

3.1. Building Year 2000 Safe Software

Writing software which is year 2000 safe consists of two aspects. The first is to design and code in such a way as to have no hidden assumptions about the century or dependencies upon other software which may be changing to support dates beyond the year 2000; this information is covered in other year 2000 documentation. The second aspect, which is addressed in this section of the paper, is how to code and build for the specific changes in the standard C library.

To make your software year 2000 safe from a libc perspective, you must determine your dependencies upon the getdate(3c) and strptime(3c) calls (covered in section 2.2). If you have dependencies on the behavior, modify your code to accommodate the behavior changes in the getdate(3c) and strptime(3c) routines. Ensure that all software and libraries which you depend upon are also year 2000 safe; the supplier of the library or software should be able to demonstrate whether the software is year 2000 safe or not. Then follow the rest of the guidelines in section 3 of this paper. Remember also to check with the year 2000 documentation for other year 2000 safe concerns.

3.2. Obtaining the Year 2000 Behavior in Release 10.30

When you recompile your application on a 10.30 system, you will automatically link against the 10.30 version of libc which contains the new behavior. If you run your application on a 10.30 (or later) system you will get the new behavior (Remember, compiling an application on a given release and running it on a prior release is *not* supported).

If you call strptime(3c) or getdate(3c), you should inspect your source code for dependencies upon the behavior of these calls with respect to two-digit year specifications. If you use 2-digit year specifications for these calls, you should requalify your software when you recompile for 10.30. If you intend to be year 2000 safe, you should follow all the guidelines in this document as well as in the other year 2000 documents.

Executables and dependent non-system shared libraries which were compiled on systems prior to 10.30 and are brought forward from the original release as a group will *NOT* get the new behavior, but will continue to experience the old (binary compatible) behavior. Remember, however, that software brought forward like this is NOT year 2000 safe, and therefore the system upon which it is running is not year 2000 compliant.

3.3. Obtaining the Year 2000 Behavior in Releases Prior to 10.30

There are several HP-UX products which are delivering patches with 2000 rollover functionality for several pre-10.30 releases (10.01, 10.10, 10.20). Patches are not available for release 10.00 or for the 9.x releases. In order to obtain the year 2000 safe behavior, you must install all of the applicable year 2000 patches. This section addresses the technical details concerning the year 2000 patches for the Standard C Libraries for HP-UX product.

When you install the libc 2000 rollover patches for either of the patched releases (10.01, 10.10, or 10.20), your applications will get the old libc behavior by default. This allows existing applications to maintain binary compatibility. The libc patch installs the /usr/lib/year2000.o file in addition to the standard libc variants. You need to create your software with this patch installed; you also may need year 2000 safe patches which your product depends upon.

If you want to get the new behavior for your software, you will be required to link against the file /usr/lib/year2000.o, in addition to compiling and linking against the patched libraries. If you don't link against the year2000.o file, the patches will assume you wish to get the old behavior, and your application will not be year 2000 safe with respect to these routines.

You should follow the following suggestions for linking with the year2000.o object file to obtain the new behavior. It is strongly recommended that you link your application shared; archive-bound applications are susceptible to more problems, and if you do not follow the suggestions given here exactly, you risk introducing obscure bugs which break year 2000 readiness if your application calls setlocale(3c) or iconv(3c), or other routines which dynamically load shared libraries (see the 10.30 Release Notes for more details). Specifically, if you don't export all the symbols in your archive-bound application (e.g., by using the -E flag to the linker), invocations of strptime(3c) in any locale will not have the year 2000 behavior, and your software will not be year 2000 safe.

3.4. Moving Your Pre-10.30 Year 2000 Safe Software Forward

Year 2000 safe binaries for pre-10.30 systems will operate fine in 10.30 and beyond, and will continue to be year 2000 safe on subsequent releases.

Modifications made to pre-10.30 software to conform to the new interpretations of the 2-digit year specifiers for the getdate(3c) and strptime(3c) will of course continue to be valid for 10.30 and beyond.

If you are making changes to your source code for 10.30 (or a subsequent release), it is highly recommended that you remove the year2000.o file from your link line, as the year2000.o file is deprecated in 10.30 and beyond, and will not be supported in the future. Removal of the year2000.o file from your link line will not affect year 2000 safety for 10.30 and beyond, since it is only needed on releases prior to 10.30.

3.5. Interoperability warning

If any objects, executables, or libraries use getdate(3c) or strptime(3c) to interpret two-digit year data, or if two-digit year data is passed between these modules, then all objects, executables, and libraries using getdate(3c) or strptime(3c) that your product depends upon must support this behavior change in a consistent manner. This will help to ensure that all components have the same interpretation for two digit years.

This may be an issue for software which stores two-digit year data in files. This may also be an issue for distributed software which sends two-digit year data over a network to systems which may be running Unix(tm) supplied by other vendors, or which may be running previous versions of HP-UX which do not have the 2000 rollover support.

3.6. Special Considerations for Libraries

If you are shipping a library which calls strptime(3c) or getdate(3c), you must be able to work with either behavior, or must version your library. This is because both year 2000 safe applications and applications expecting compatible behavior may be calling your library. This is a concern for both 10.30 and pre-10.30 software.

The best way to work with either behavior is to never parse 2-digit years, so that you're not dependent upon which behavior of strptime(3c) or getdate(3c) you get. Dealing with two digit years has always been problematic. If you must handle data which contains 2-digit specifications, you can simply pre-process the data into 4-digit year specifications and then parse the year using strptime(3c) or getdate(3c) (this assumes that the interpretation of that 2-digit data is well defined; if not, there are larger year 2000 issues here).

3.7. Special Considerations for Locales

Locales with custom strptime methods will have to handle dates beyond the year 2000 in a consistent way. HP-UX does not supply locales with custom strptime methods, so the handling of dates with respect to locales with custom strptime methods is up to the locale supplier.

3.8. Testing Your Software

The following tests are recommended for applications with a dependency on strptime(3c) or getdate(3c).

You should run tests with dates in the 1970-1999 range, as well as in the 2000-2037 range.

For each of these tests, run them with the system clock set once to a date before the year 2000, and once with the system clock set to a date past the year 2000.

Furthermore, if you are an application which is linked archive and operate within different locales on releases prior to 10.30, you should perform all of the above tests after invoking setlocale(3c) on a locale other than the default, to make sure that you have built the software with the proper symbol export options.

3.9. Requirements for Year 2000 Safe Software

In addition to meeting your other requirements for year 2000 readiness, application software which uses the standard C libraries MUST link against the /usr/lib/year2000.o file to be qualified as year 2000 safe on pre-10.30 systems (this is NOT an issue for year 2000 safe applications on 10.30).

If you are claiming that your software is year 2000 safe on the 10.01, 10.10, or 10.20 release, you must inform your customers to install the year 2000 patches for that particular release (10.30 is already year 2000 safe) as a condition for year 2000 compliancy.

3.10. Recommendations for Applications

If you are shipping an application which requires the specific functionality changes for getdate(3c) or strptime(3c) for correct operation, it is highly recommended that you check programmatically in your application to see if the year 2000 patches for libc have been installed, and exit with an error message if they are not. This will prevent your application from exhibiting erroneous behavior on misconfigured systems. If you linked shared, you can simply invoke strptime(3c) with a "%y" format specifier and check the dates 55 and 04 to see that 55 is invalid, and 04 is 2004. If you linked archive, you must also use setlocale(3c) to set the current locale to a non-default locale, and then invoke strptime(3c) with the same tests.

4. Handling of Dates Past the Year 2037

4.1. Overview of the Problem (the time_t issue)

Note that although changes were made to support dates beyond the year 2000, these and other libc date routines have other limitations. Most routines, including mktime(3c), strptime(3c), and other routines which return a time_t data type or accept a time_t data type as a parameter, are effective and accurate only for dates within the range representable by the time_t data type. The routines for which the time_t limitation applies are asctime(3c), ctime(3c), getdate(3c), localtime(3c), gmtime(3c), mktime(3c), nl_ctime(3c), nl_cxtime(3c), and strptime(3c). The range represented by a time_t data type on 32-bit machines is December 13, 1901 to January 19, 2038. HP-UX on 64-bit machines will address this problem.

4.2. Future Directions for 64-bit Systems

On 64-bit systems, the 2037 problem will be addressed by the increase in the size of the time_t data type, which will provide an expanded range of dates. This solution will be available for 64-bit software running on 64-bit systems only. Details will be available in future documentation for our 64-bit system software.

4.3. Future Directions for 32-bit Systems

HP-UX has no plans for supporting increases in the size of time_t for 32-bit systems. Instead, we recommend that software which needs to manipulate dates beyond the year 2037 should manage those situations by devising your own alternatives to the routines in the Standard C Library which are limited by the size of the time_t data type.

A common problem has to do with loan amortizations. Applications sometimes use time_t values to calculate amortization schedules. The most logical unit for such calculations are usually months, days, or hours(very few loans are compounded every second). So the use of the time_t, a second-based time quantity, is primarily because it is convenient.

Applications can instead use integer quantities to calculate amortization based on days, for example, and avoid the dependency upon the time_t data type. Simple algorithms are available for calculating the day of the week, etc. The strftime(3c) is still useful for printing out locale-sensitive date / time strings, given that a properly filled out tm structure is available. The application can fill in the relevant fields of the tm struct and call strftime(3c) to do any date output needed.