顯示不同時區的時間 一個日期命令最基本的需求就是顯示你所在時區的日期和時間。但是如果你有使用者是跨時區的呢?或者,如果你有朋友或是同事時在不同的地區呢?你就會一直搞不清楚那兒現在到底是個什麼日子了,比如卡薩布蘭卡、梵蒂岡或是雪梨。 現在大部分的Unix系統都有一個date命令,它的後台是一個時區資料庫。它的位置一般是在目錄/usr/share/zoneinfo下,它列出了超過250個不同的地區,並且可以明確表示出各個不同地區的時間。因為date命令注重的是時間變數TZ,該變數可以被設定為不同的已知地區,那麼核心的功能可以通過如下表示:TZ="Africa/Casablanca" date 通過一個shell指令碼,我們可以建立一個對使用者介面友好的時區資料庫:要知道,大部分系統使用者並不喜歡臨時設定環境變數 代碼: 01#!/bin/sh02 03 # timein.sh -- 顯示特定時區或是地區的時間.04 # 如果沒有提供任何參數,就顯示 UTC/GMT.05 # 使用單詞"list"來查看已知地區列表06 # 注意:有可能匹配到地區,但只有時區是合法的。07 08 # 09 10 zonedir="/usr/share/zoneinfo"11 12 if [ ! -d $zonedir ]; then13 echo "No time zone database at $zonedir." >&214 exit 115 fi16 17 if [ -d "$zonedir/posix" ]; then18 zonedir=$zonedir/posix # 現代Linux系統19 fi20 21 if [ $# -eq 0 ]; then22 timezone="UTC"23 mixedzone="UTC"24 elif [ "$1" = "list" ]; then25 (echo "All known time zones and regions defined on this system:"26 cd $zonedir27 find * -type f -print | xargs -n 2 | \28 awk '{printf "%-38s %-38s\n", $1, $2}' 29 ) | more30 exit 031 else32 region="$(dirname $1)" # 如果參數格式是 Asia/Beijing,那region是Asia33 zone="$(basename $1)" # 如果參數格式是 Beijing,那region就是個點34 35 # 恰好可以匹配?非常好。否則我們需要探索一番。36 # 從計算匹配的個數開始。37 38 matchcnt="$(find $zonedir/$region -name $zone -type f -print |39 wc -l | sed 's/[^[:digit:]]//g')" #上面的尋找路徑,應該加上$region,否則尋找的不精確。書中沒有。40 #比如給出形如 Asia/Beijing 的參數,如果路徑中沒有Asia,那永遠也查不到北京41 42 if [ "$matchcnt" -gt 0 ]; then # 至少一個檔案匹配43 if [ "$matchcnt" -gt 1 ]; then # 超過一個檔案匹配44 echo "\"$zone\" matches more than one possible time zone record." >&245 echo "Please use 'list' to see all known regions and time zones." >&246 exit 147 fi48 match="$(find $zonedir -name $zone -type f -print)"49 mixedzone="$zone"50 else51 # 第一個字母大寫,其餘單詞小寫: region + zone52 mixedregion="$(echo ${region%${region#?}} | tr '[[:lower:]]' '[[:upper:]]')\53 $(echo ${region#?} | tr '[[:upper:]]' '[[:lower:]]')" #行頭千萬別留下空格或者定位字元54 mixedzone="$(echo ${zone%${zone#?}} | tr '[[:lower:]]' '[[:upper:]]')\55 $(echo ${zone#?} | tr '[[:upper:]]' '[[:lower:]]')" #行頭千萬別留下空格或者定位字元56 57 if [ "$mixedregion" != "." ]; then58 # 只查特定地方59 # 當有多種可能性時,讓使用者指定唯一匹配項(比如"Atlantic")60 match="$(find $zonedir/$mixedregion -name $mixedzone -type f -print)"61 else62 match="$(find $zonedir -name $mixedzone -type f -print)"63 fi64 65 if [ -z "$match" ]; then66 if [ ! -z "$(find $zonedir -name $mixedzone -type d -print)" ]; then67 echo \68 "The region \"$1\" has more than one time zone. Please use 'list'" >&269 else # 沒有一個匹配70 echo "Can't find an exact match for \"$1\". Please use 'list'" >&271 fi72 echo "to see all known regions and time zones." >&273 exit 174 fi75 fi76 timezone="$match"77 fi78 79 nicetz=$(echo $timezone | sed "s|$zonedir/||g")80 81 echo It\'s $(TZ=$timezone date '+%A, %B %e, %Y, at %l:%M %p') in $nicetz82 83 exit 0指令碼如何工作: 這個指令碼利用的就是date命令來顯示日期和時間。事實上,這整個指令碼關注的就是要確認好你給的時區名,這樣在指令碼的最後才能如期運行好。這個指令碼最複雜的地方來自預測由使用者輸入的,不匹配時區資料庫中的任一個名字的地區名。時區資料庫會按照時區名按地區列排好,在有典型的輸入問題時,指令碼也會試圖報有用的錯誤資訊。 比如,雖然TZ="Casablanca"並不嫩成功的尋找到一個匹配的地區,而date命令會示範GMT,城市Casablanca確實是存在於地區資料庫中的。可能的名字,Africa/Casablanca,就會被提供給這個指令碼。指令碼會找到非洲目錄下的卡薩布蘭卡,然後正確的確認這個地區。指定"Africa",從另一面來說,指令碼知道有分區,只提供那些資訊不足以唯一指定一個時區。最後,你同樣可以使用一個時區名(比如,UTC、WET)作為指令碼參數來查看定義好的時區的子集。註:UTC是國際標準時間(Universal Time Coordinated)英文縮寫,北京時間比UTC時間早8小時。GMT(Greenwich Mean Time)是格林尼治平時。 運行指令碼: 01./timein.sh02 It's 星期一, 十二月 24, 2012, at 12:19 上午 in UTC03 04 ./timein.sh London05 It's 星期一, 十二月 24, 2012, at 12:19 上午 in Europe/London06 07 ./timein.sh Brazil08 The region "Brazil" has more than one time zone. Please use 'list'09 to see all known regions and time zones.10 11 ./timein.sh Pacific/Honolulu12 It's 星期日, 十二月 23, 2012, at 2:21 下午 in Pacific/Honolulu13 14 ./timein.sh WET15 It's 星期一, 十二月 24, 2012, at 12:21 上午 in WET16 17 ./timein.sh mycloset18 Can't find an exact match for "mycloset". Please use 'list'19 to see all known regions and time zones.