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 Section 3.6
and Section 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. Section 3.12 and Section 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. Section 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!