Unix and time zones, part 2 (Time as we compute it)

UNIX IN THE ENTERPRISE --- 11/13/2003

Sandra Henry-Stocker

Many terms are used to describe regional time. Some are part of the common vocabulary, like "Eastern Standard Time", and easily understood. Others are less generally used and understood but equally important to understanding how time works around the planet.

Since early times, the apparent motion of the sun in the sky has been used to define time. The hour angle between the current position of the sun and the highest point above the horizon that the sun reached each day corresponding to noon. The idea of time zones was not considered until the late 1800s.

UTC, or Coordinated Universal Time, also known as Greenwich Mean Time (GMT), now forms the basis for clock time throughout the world. Local times can be reported with respect to UTC with phrases such as UTC+5 or GMT-2, though most people are probably unaware of how much their local time actually differs from UTC - especially when it changes twice a year.

DST, Daylight Savings Time, moves time ahead an hour or half-an-hour to make daylight hours more useful. Originally started as a measure to conserve energy, Daylight Savings Time effectively moves an hour of sunlight from the morning to the evening, extending the useful part of the day.

Standard Time has no meaning except in relationship to DST. In a time zone in which a portion of the year is spent in DST, the remainder of the year is referred to as Standard Time.

Local Mean Time is simply solar time at some particular location. To fully define a time zone, therefore, we need to record both the offset from UTC (expressed in hours) and, if DST is observed, the date and time at which the transitions between Daylight Savings Time and Standard Time occur. We also need to record the various names associated with the time zone. Time on the EastCoast of the United States, for example, is referred to as "EST" (Eastern standard Time), "US/Eastern" and "America/New York". This is the kind of information that is stored in the TZ database. Since 1986 or so, Arthur David Olson and various volunteers have maintained a site that defines time zones and provides code for using this data in time calculations. This TZ database is the source of time zone information on most versions of Unix today. The zoneinfo directory: /usr/share/lib/zoneinfo on Solaris /usr/share/zoneinfo on Mac OS X /usr/share/zoneinfo on RedHat Linux contains a series of directories and files that correlate to the time zones that we use in date/time calculations. The time zone referred to as "US/Eastern", for example, corresponds to the /usr/share/zoneinfo/US/Eastern file on Mac OS X.

Further, it should come as no surprise that this file is hard-linked to /usr/share/zoneinfo/America/New_York. The strings "US/Eastern" and "America/New_York" are interchangeable references to the same time zone. Since this particular time zone observes Daylight Savings Time, however, the offset from GMT depends on the date. To see how this works, try the following command (amend the zone file to reflect your own time zone and path to reflect your operating system):

% zdump -v /usr/share/zoneinfo/US/Eastern | grep 2004 /usr/share/zoneinfo/US/Eastern Sun Apr 4 06:59:59 2004 GMT = Sun Apr 4 01:59:59 2004 EST isdst=0 /usr/share/zoneinfo/US/Eastern Sun Apr 4 07:00:00 2004 GMT = Sun Apr 4 03:00:00 2004 EDT isdst=1 /usr/share/zoneinfo/US/Eastern Sun Oct 31 05:59:59 2004 GMT = Sun Oct 31 01:59:59 2004 EDT isdst=1 /usr/share/zoneinfo/US/Eastern Sun Oct 31 06:00:00 2004 GMT = Sun Oct 31 01:00:00 2004 EST isdst=0

The first line of output above reports the current date and time. The following four lines comprise two sets of two lines each. The first set says that one second before 2 AM on April 6, 2004 is the same as one second before 7 AM on April 6, 2004 GMT. Up to and including this time, the local time and GMT are 5 hours apart. The local time is, then, GMT-5. The second line of the first set then goes on to say that precisely 3 AM on April 6, 2004 is defined as 7 AM on April 6, 2004 GMT. This is the point at which everyone on the Eastern shore of the US should wake up and push his or her clock ahead one hour. The local time then becomes GMT-4. Daylight savings will be in effect and the sun will go down roughly one hour later in the evening.

The second set of lines defines the transition from Daylight Savings Time to Standard Time. At 2 AM in the morning of October 31, 2004, everyone on the East Coast of the US should be waking up to push his or her clock back one hour and then settling back down for an extra hour of sleep. The local time will then go back to being GMT-5. The sun will set earlier in the evening, but many of the East Coast residents will find themselves driving to work in the sunshine again.

Using Time Zones

You can use the time zone variable, TZ, to determine the time zone in another region. In bash or a related shell, for example, the following command will tell you what time it is in Japan:

> TZ=Japan date
Mon Nov 3 03:46:14 JST 2003 

To generate a listing of the time zones available on your system, try this command:

> cd $PATH/zoneinfo; find * -type f -print 

To determine your offset from UTC, try the following command:

> expr `TZ=GMT date +%H` - `date +%H`
5 

This command will only work, however, if it is still today in Greenwich, England. If the result is negative, add 24 to it.

And, if date commands such as the one below don't give you tomorrow's date (this command will not work for some time zones):

TZ=$TZ-24 date +%Y-%m-%d 

try a script that calculates and employs your offset like this one:

------------------------------- cut here ------------------------------- 

#!/bin/bash 

# -- calculate time using GMT --
Uday=`TZ=GMT date +%d` Uhr=`TZ=GMT date +%H` Lday=`date +%d` Lhr=`date +%H` 

if [ $Lday = $Uday ]; then
Offset=`expr $Uhr - $Lhr` else Offset=`expr $Uhr + 24 - $Lhr` fi 

Diff=`expr 24 + $Offset`
echo -n "yesterday was " TZ=GMT+$Diff date +%Y-%m-%d 

Diff=`expr 24 - $Offset`
echo -n "tomorrow will be " TZ=GMT-$Diff date +%Y-%m-%d 

------------------------------- cut here ------------------------------- 

This script, though a bit bulky, employs a reliable calculation based on your offset from UTC.

Similarly, you can use the following snippet to run commands on the last day of the month. The script determines that today is the last day of the month by verifying that tomorrow is the first.

------------------------------- cut here ------------------------------- 

tomorrow=`TZ=GMT-$Diff date +%d` 

if [ $tomorrow -eq "01" ]; then
echo Today is the last day of the month else echo Not today fi 

------------------------------- cut here ------------------------------- 

While these scripts are very similar to those offered two weeks ago, they should work reliably in any time zone.

Sandra Henry-Stocker has been administering Unix systems for nearly 18 years. She describes herself as "USL" (Unix as a second language) but remembers enough English to write books and buy groceries. She currently works for TeleCommunication Systems, a wireless communications company, in Annapolis, Maryland, where no one else necessarily shares any of her opinions. She lives with her second family on a small farm on Maryland's Eastern Shore. Send comments and suggestions to mailto:sstocker@itworld.com.