shell相关:指令篇 基础篇 脚本欣赏 编程实例 shell问问 shell视频教程 技巧篇 水平测试 E文资料 vi编辑器 高级Bash脚本编程指南
其他:mysql perl c语言
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 [ "$1" = "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", $1, $2 }'
) | more
exit 0
else
region="$(dirname $1)"
zone="$(basename $1)"
# 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 \"$1\" 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 \"$1\". 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.
Note 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.