Book HomePHP CookbookSearch this book

Chapter 3. Dates and Times

Contents:

Introduction
Finding the Current Date and Time
Converting Time and Date Parts to an Epoch Timestamp
Converting an Epoch Timestamp to Time and Date Parts
Printing a Date or Time in a Specified Format
Finding the Difference of Two Dates
Finding the Difference of Two Dates with Julian Days
Finding the Day in a Week, Month, Year, or the Week Number in a Year
Validating a Date
Parsing Dates and Times from Strings
Adding to or Subtracting from a Date
Calculating Time with Time Zones
Accounting for Daylight Saving Time
Generating a High-Precision Time
Generating Time Ranges
Using Non-Gregorian Calendars
Program: Calendar

3.1. Introduction

Displaying and manipulating dates and times seems simple at first but gets more difficult depending on how diverse and complicated your users are. Do your users span more than one time zone? Probably so, unless you are building an intranet or a site with a very specific geographical audience. Is your audience frightened away by timestamps that look like "2002-07-20 14:56:34 EDT" or do they need to be calmed with familiar representations like "Saturday July 20, 2000 (2:56 P.M.)." Calculating the number of hours between today at 10 A.M. and today at 7 P.M. is pretty easy. How about between today at 3 A.M. and noon on the first day of next month? Finding the difference between dates is discussed in Recipe 3.6 and Recipe 3.7.

These calculations and manipulations are made even more hectic by daylight saving (or summer) time (DST). Thanks to DST, there are times that don't exist (in most of the United States, 2 A.M. to 3 A.M. on the first Sunday in April) and times that exist twice (in most of the United States, 1 A.M. to 2 A.M. on the last Sunday in October). Some of your users may live in places that observe DST, some may not. Recipe 3.12 and Recipe 3.13 provide ways to work with time zones and DST.

Programmatic time handling is made much easier by two conventions. First, treat time internally as Coordinated Universal Time (abbreviated UTC and also known as GMT, Greenwich Mean Time), the patriarch of the time-zone family with no DST or summer time observance. This is the time zone at 0 degrees longitude, and all other time zones are expressed as offsets (either positive or negative) from it. Second, treat time not as an array of different values for month, day, year, minute, second, etc., but as seconds elapsed since the Unix epoch: midnight on January 1, 1970 (UTC, of course). This makes calculating intervals much easier, and PHP has plenty of functions to help you move easily between epoch timestamps and human-readable time representations.

The function mktime( ) produces epoch timestamps from a given set of time parts, while date( ) , given an epoch timestamp, returns a formatted time string. You can use these functions, for example, to find on what day of the week New Year's Day 1986 occurred:

$stamp = mktime(0,0,0,1,1,1986);
print date('l',$stamp);
Wednesday

This use of mktime( ) returns the epoch timestamp at midnight on January 1, 1986. The l format character to date( ) tells it to return the full name of the day of the week that corresponds to the given epoch timestamp. Recipe 3.5 details the many format characters available to date( ).

In this book, the phrase epoch timestamp refers to a count of seconds since the Unix epoch. Time parts (or date parts or time and date parts) means an array or group of time and date components such as day, month, year, hour, minute, and second. Formatted time string (or formatted date string, etc.) means a string that contains some particular grouping of time and date parts, for example "2002-03-12," "Wednesday, 11:23 A.M.," or "February 25."

If you used epoch timestamps as your internal time representation, you avoided any Y2K issues, because the difference between 946702799 (1999-12-31 23:59:59 UTC) and 946702800 (2000-01-01 00:00:00 UTC) is treated just like the difference between any other two timestamps. You may, however, run into a Y2038 problem. January 19, 2038 at 3:14:07 A.M. (UTC) is 2147483647 seconds after midnight January 1, 1970. What's special about 2147483647? It's 231 - 1, which is the largest integer expressible when 32 bits represent a signed integer. (The 32nd bit is used for the sign.)

The solution? At some point before January 19, 2038, make sure you trade up to hardware that uses, say, a 64-bit quantity for time storage. This buys you about another 292 billion years. (Just 39 bits would be enough to last you until about 10680, well after the impact of the Y10K bug has leveled the Earth's cold fusion factories and faster-than-light travel stations.) 2038 might seem far off right now, but so did 2000 to COBOL programmers in the 1950s and 1960s. Don't repeat their mistake!



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.