22 Displaying the Time in Different Time Zones

#22 Displaying the Time in Different Time Zones

The most fundamental requirement for a working date command is that it display the date and time in your time zone. But what if you have users across multiple time zones? Or, more likely, what if you have friends and colleagues in different locations, and you're always confused about what time it is in, say, Casablanca, Vatican City, or Sydney?

It turns out that most modern Unixes have a date command built atop an amazing time zone database. Usually stored in /usr/share/zoneinfo , this database lists over 250 different regions and knows how to ascertain the appropriate time zone for each. Because the date command pays attention to the TZ time zone variable, and because that variable can be set to any known region, the core functionality can be demonstrated as follows :

 $  TZ="Africa/Casablanca" date  Mon Dec 2 16:31:01 WET 2002 

However, using a shell script, we can create a more user -friendly front end to the time zone database: Specifying temporary environment variable settings isn't something most system users are comfortable doing!

The Code

 #!/bin/sh # timein - Shows the current time in the specified time zone or #   geographic zone. Without any argument, shows UTC/GMT. Use #   the word "list" to see a list of known geographic regions. #   Note that it's possible to match zone directories (regions), #   but that only time zone files (cities) are valid specifications. #   Time zone database ref: http://www.twinsun.com/tz/tz-link.htm zonedir="/usr/share/zoneinfo" if [ ! -d $zonedir ] ; then   echo "No time zone database at $zonedir." >&2 ; exit 1 fi if [ -d "$zonedir/posix" ] ; then   zonedir=$zonedir/posix        # modern Linux systems fi if [ $# -eq 0 ] ; then   timezone="UTC"   mixedzone="UTC" elif [ "" = "list" ] ; then   ( echo "All known time zones and regions defined on this system:"     cd $zonedir     find * -type f -print  xargs -n 2  \       awk '{ printf " %-38s %-38s\n", ,  }'   )  more   exit 0 else   region="$(dirname )"   zone="$(basename )"   # Is it a direct match? If so, we're good to go. Otherwise we need   # to dig around a bit to find things. Start by just counting matches.   matchcnt="$(find $zonedir -name $zone -type f -print          wc -l  sed 's/[^[:digit:]]//g')"   if [ "$matchcnt" -gt 0 ] ; then       # at least one file matches     if [ $matchcnt -gt 1 ] ; then       # more than one file matches       echo "\"$zone\" matches more than one possible time zone record." >&2       echo "Please use 'list' to see all known regions and time zones" >&2       exit 1     fi     match="$(find $zonedir -name $zone -type f -print)"     mixedzone="$zone"   else     # First letter capitalized, rest of word lowercase for region + zone     mixedregion="$(echo ${region%${region#?}}  tr '[[:lower:]]' '[[:upper:]]')\ $(echo ${region#?}  tr '[[:upper:]]' '[[:lower:]]')"     mixedzone="$(echo ${zone%${zone#?}}  tr '[[:lower:]]' '[[:upper:]]')\ $(echo ${zone#?}  tr '[[:upper:]]' '[[:lower:]]')"     if [ "$mixedregion" != "." ] ; then       # Only look for specified zone in specified region       # to let users specify unique matches when there's more than one       # possibility (e.g., "Atlantic")       match="$(find $zonedir/$mixedregion -type f -name $mixedzone -print)"     else       match="$(find $zonedir -name $mixedzone -type f -print)"     fi     if [ -z "$match" ] ; then # no file matches specified pattern       if [ ! -z $(find $zonedir -name $mixedzone -type d -print) ] ; then         echo \     "The region \"\" has more than one time zone. Please use 'list'" >&2       else  #  just not a match at all         echo "Can't find an exact match for \"\". Please use 'list'" >&2       fi       echo "to see all known regions and time zones." >&2       exit 1     fi   fi   timezone="$match" fi nicetz=$(echo $timezone  sed "s$zonedir/g")     # pretty up the output echo It\'s $(TZ=$timezone date '+%A, %B %e, %Y, at %l:%M %p') in $nicetz exit 0 

How It Works

This script exploits the ability of the date command to show the date and time for a specified time zone, regardless of your physical location. In fact, the entire script is all about identifying a valid time zone name so that the date command will work when invoked at the very end.

Most of the complexity of this script comes from trying to anticipate names of world regions entered by users that do not match the names of regions in the time zone database. The time zone database is laid out with timezonename and region/locationname columns , and the script tries to display useful error messages for typical input problems.

For example, although TZ="Casablanca" date would fail to find a matching region, and the date command would instead display GMT (Greenwich Mean Time, more properly known as Universal Time Coordinated), the city Casablanca does exist in the time zone database. The proper region name, Africa/Casablanca, was shown in the introduction to this script. And this script can find Casablanca in the Africa directory and identify the zone accurately. Specify "Africa," on the other hand, and the script knows that there are subregions and specifies that the information is insufficient to uniquely identify a specific time zone.

Finally, you can also use a time zone name (e.g., UTC or WET) as an argument to this script to see a subset of time zones that are defined.


An excellent reference to the time zone database can be found online, at http://www.twinsun.com/tz/tz-link.htm

Running the Script

To find the time in a specified region or city, specify the region or city name as the argument to the command. If you know both the region and the city, you can specify them as region/city, as in Pacific/Yap . Without any arguments, timein shows Greenwich Mean Time/Universal Time Coordinated (GMT/UTC).

The Results

 $  timein  It's Friday, March 28, 2003, at 2:58 AM in UTC $  timein London  It's Friday, March 28, 2003, at 2:58 AM in Europe/London $  timein Brazil  The region "Brazil" has more than one time zone. Please use 'list' to see all known regions and time zones. $  timein Pacific/Honolulu  It's Thursday, March 27, 2003, at 4:58 PM in Pacific/Honolulu $  timein WET  It's Friday, March 28, 2003, at 3:58 AM in WET $  timein mycloset  Can't find an exact match for "mycloset". Please use 'list' to see all known regions and time zones. 

Wicked Cool Shell Scripts. 101 Scripts for Linux, Mac OS X, and Unix Systems
Wicked Cool Shell Scripts
ISBN: 1593270127
EAN: 2147483647
Year: 2004
Pages: 150
Authors: Dave Taylor

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net