简体   繁体   中英

command-line world clock?

Is there a script to display a simple world clock (time in various places around the world) on a *nix terminal?

I was thinking of writing a quick Python script, but I have a feeling that's gonna be more work than I think (eg due to config and output format) - not to mention reinventing the wheel...

I have this bourne shell script:

#!/bin/sh

PT=`env TZ=US/Pacific date`
CT=`env TZ=US/Central date`
AT=`env TZ=Australia/Melbourne date`

echo "Santa Clara    $PT"
echo "Central        $CT"
echo "Melbourne      $AT"

Simple system

Never thought of it, but not dreadfully hard to do.

#!/bin/sh
# Command-line world clock

: ${WORLDCLOCK_ZONES:=$HOME/etc/worldclock.zones}
: ${WORLDCLOCK_FORMAT:='+%Y-%m-%d %H:%M:%S %Z'}

while read zone
do echo $zone '!' $(TZ=$zone date "$WORLDCLOCK_FORMAT")
done < $WORLDCLOCK_ZONES |
awk -F '!' '{ printf "%-20s  %s\n", $1, $2;}'

Given the input file:

US/Pacific
Europe/London
Europe/Paris
Asia/Kolkatta
Africa/Johannesburg
Asia/Tokyo
Asia/Shanghai

I got the output:

US/Pacific             2008-12-15 15:58:57 PST
Europe/London          2008-12-15 23:58:57 GMT
Europe/Paris           2008-12-16 00:58:57 CET
Asia/Kolkatta          2008-12-15 23:58:57 GMT
Africa/Johannesburg    2008-12-16 01:58:57 SAST
Asia/Tokyo             2008-12-16 08:58:57 JST
Asia/Shanghai          2008-12-16 07:58:57 CST

I was fortunate that this took less than a second to run and didn't cross a 1-second boundary.

( I didn't notice that Kolkatta failed and defaulted to GMT. Maybe my system still has Asia/Calcutta as the entry for India. )


Fixing typos

Eleven years later, I'm told that I misspelt Kolkata with two t's where there should only be one; thank you, @ jbg . I've also added two extra entries to the data file — America/St_Johns (Newfoundland) and Asia/Katmandu which have a half-hour and three-quarter hour offset from UTC respectively (Kolkata also has a half-hour offset). That produces, for example:

US/Pacific             2020-01-09 06:17:40 PST
Europe/London          2020-01-09 14:17:40 GMT
Europe/Paris           2020-01-09 15:17:40 CET
Asia/Kolkata           2020-01-09 19:47:40 IST
Africa/Johannesburg    2020-01-09 16:17:40 SAST
Asia/Tokyo             2020-01-09 23:17:40 JST
Asia/Shanghai          2020-01-09 22:17:40 CST
America/St_Johns       2020-01-09 10:47:40 NST
Asia/Katmandu          2020-01-09 20:02:40 +0545

Note that US/Pacific is an ancient time zone name that is not preferred; it should be America/Los_Angeles .

It might be sensible to sort the zones into order. Add sort -b -r -k2,2 -k3,3 to list the zones in the order with the time zones furthest ahead of UTC listed first and those farthest behind listed last. The -b option (to ignore leading blanks on fields) is important. Adding three more zones ( Pacific/Honolulu , Pacific/Kwajalein , Pacific/Kiritimati ) and that gives:

Pacific/Kiritimati     2020-01-10 04:33:25 +14
Pacific/Kwajalein      2020-01-10 02:33:25 +12
Asia/Tokyo             2020-01-09 23:33:25 JST
Asia/Shanghai          2020-01-09 22:33:25 CST
Asia/Katmandu          2020-01-09 20:18:25 +0545
Asia/Kolkata           2020-01-09 20:03:25 IST
Africa/Johannesburg    2020-01-09 16:33:25 SAST
Europe/Paris           2020-01-09 15:33:25 CET
Europe/London          2020-01-09 14:33:25 GMT
America/St_Johns       2020-01-09 11:03:25 NST
US/Pacific             2020-01-09 06:33:25 PST
Pacific/Honolulu       2020-01-09 04:33:25 HST

Note that the time in Kiritimati and Honolulu is the same, but the date is one day apart. The sorting should be in the script, of course:

#!/bin/sh
# Command-line world clock

: ${WORLDCLOCK_ZONES:=$HOME/etc/worldclock.zones}
: ${WORLDCLOCK_FORMAT:='+%Y-%m-%d %H:%M:%S %Z'}

while read zone
do echo $zone '!' $(TZ=$zone date "$WORLDCLOCK_FORMAT")
done < $WORLDCLOCK_ZONES |
awk -F '!' '{ printf "%-20s  %s\n", $1, $2;}' |
sort -b -r -k2,2 -k3,3

And the worldclock.zones file contains:

US/Pacific
Europe/London
Europe/Paris
Asia/Kolkata
Africa/Johannesburg
Asia/Tokyo
Asia/Shanghai
America/St_Johns
Asia/Katmandu
Pacific/Honolulu
Pacific/Kwajalein
Pacific/Kiritimati
Pacific/Pago_Pago
UTC-12

Kiritimati has the most positive offset from UTC at UTC+14. Pacific/Pago_Pago is one of the places with the most negative offset from UTC at UTC-11. If you go to World Time Zone , they list two uninhabited islands that would, if inhabited, probably be in UTC-12. However, the Olson database doesn't record time zone information for places uninhabited since its cutoff date of 1970-01-01, so they're not listed.

Around the world in 26 time zones

For entertainment (simple minds are easily side-tracked), here's a list of time zone names with one name from most of the time zone offsets around the world. If there are any other fractional-hour offsets in use (Australia?), please let me know. Beware of standard vs daylight saving time — some entries for the southern hemisphere may be in daylight saving time. In January 2020, the list generates all the integral-hour offsets, but it might not do so in June 2020.

The list includes two made up zone names: FarEast-12 and FarWest+12 , which are at UTC+12 and UTC-12 respectively. This conflict between positive and negative arises because there are conflicting standards. ISO 8601 specifies that places east of UTC (the Greenwich Meridian, more or less) use positive offsets from UTC, and those west of UTC use negative offsets. Meanwhile, POSIX (aka ISO 9045), specifies the opposite convention — places west of UTC use a positive offset and those east use a negative offset. Those two names are POSIX time zone names for use with the TZ environment variable and are specified with an offset and no daylight saving rule. They are subject to the POSIX offset rules. Why the discrepancy? Fundamentally, POSIX followed the conventions of Unix — it couldn't change them without breaking a lot of code. ISO 8601 was independent of POSIX and derived the rules from first principles and came up with a sensible system — but the converse of POSIX.

List of zone names:

US/Pacific
Europe/London
Europe/Paris
Asia/Kolkata
Africa/Johannesburg
Asia/Tokyo
Asia/Shanghai
America/St_Johns
Asia/Katmandu
Pacific/Honolulu
Pacific/Kwajalein
Pacific/Kiritimati
Pacific/Pago_Pago
FarEast-12
FarWest+12
US/Eastern
US/Central
US/Mountain
US/Alaska
Asia/Vladivostok
Pacific/Noumea
Pacific/Enderbury
Asia/Bangkok
Asia/Thimphu
Asia/Aqtau
Asia/Dubai
Africa/Addis_Ababa
Atlantic/Cape_Verde
Atlantic/South_Georgia
America/Santiago
America/Halifax

Sample output from modified script (with sort in place):

Pacific/Kiritimati        2020-01-10 05:24:10 +14
Pacific/Enderbury         2020-01-10 04:24:10 +13
Pacific/Kwajalein         2020-01-10 03:24:10 +12
FarEast-12                2020-01-10 03:24:10 FarEast
Pacific/Noumea            2020-01-10 02:24:10 +11
Asia/Vladivostok          2020-01-10 01:24:10 +10
Asia/Tokyo                2020-01-10 00:24:10 JST
Asia/Shanghai             2020-01-09 23:24:10 CST
Asia/Bangkok              2020-01-09 22:24:10 +07
Asia/Thimphu              2020-01-09 21:24:10 +06
Asia/Katmandu             2020-01-09 21:09:10 +0545
Asia/Kolkata              2020-01-09 20:54:10 IST
Asia/Aqtau                2020-01-09 20:24:10 +05
Asia/Dubai                2020-01-09 19:24:10 +04
Africa/Addis_Ababa        2020-01-09 18:24:10 EAT
Africa/Johannesburg       2020-01-09 17:24:10 SAST
Europe/Paris              2020-01-09 16:24:10 CET
Europe/London             2020-01-09 15:24:10 GMT
Atlantic/Cape_Verde       2020-01-09 14:24:10 -01
Atlantic/South_Georgia    2020-01-09 13:24:10 -02
America/Santiago          2020-01-09 12:24:10 -03
America/St_Johns          2020-01-09 11:54:10 NST
America/Halifax           2020-01-09 11:24:10 AST
US/Eastern                2020-01-09 10:24:10 EST
US/Central                2020-01-09 09:24:10 CST
US/Mountain               2020-01-09 08:24:10 MST
US/Pacific                2020-01-09 07:24:10 PST
US/Alaska                 2020-01-09 06:24:10 AKST
Pacific/Honolulu          2020-01-09 05:24:10 HST
Pacific/Pago_Pago         2020-01-09 04:24:10 SST
FarWest+12                2020-01-09 03:24:10 FarWest

Time passes; it is now after midnight in Tokyo.

I use this, which is basically the same as the other suggestions, except it filters on specific zones you want to see:

#!/bin/sh

# Show date and time in other time zones

search=$1

zoneinfo=/usr/share/zoneinfo/posix/
format='%a %F %T'

find -L $zoneinfo -type f \
    | grep -i "$search" \
    | while read z
      do
          d=$(TZ=$z date +"$format")
          printf "%-34s %23s\n" ${z#$zoneinfo} "$d"
      done

Sample output:

$ /usr/local/bin/wdate bang
Africa/Bangui                      Fri 2009-03-06 11:04:24
Asia/Bangkok                       Fri 2009-03-06 17:04:24

Update:

On current systems with systemd , there is timedatectl list-timezones to replace searching through the file system to get the timezone names.

So a simpler version of that script could now be:

#!/bin/sh

# Show date and time in other time zones

search=$1
format='%a %F %T'

timedatectl list-timezones \
| grep -i "$search"        \
| while read z
  do
      d=$(TZ=$z date +"$format")
      printf "%-34s %23s\n" "$z" "$d"
  done

Or a full version which falls back to find if the timedatectl command is not available :

#!/bin/sh

# Show date and time in other time zones

search=$1

zoneinfo=/usr/share/zoneinfo/posix/
format='%a %F %T'

if command -v timedatectl >/dev/null; then
    tzlist=$(timedatectl list-timezones)
else
    tzlist=$(find -L $zoneinfo -type f)
fi


grep -i "$search" <<< "$tzlist" \
| while read z
  do
      d=$(TZ=$z date +"$format")
      printf "%-34s %23s\n" ${z#$zoneinfo} "$d"
  done

There is ./cpython-2.7/Demo/curses/tclock.py that is a port of tclock.c -- 1994 ASCII analog/digital clock for curses , from ncurses-examples. Usage:

$ TZ=Europe/Paris python tclock.py

Here's video .

If you do still want to write it in Python, consider Pytz:

http://pytz.sourceforge.net/

Their front page shows you many simple ways to accomplish what you're looking for.

That said, I'm sure if you spent a few minutes on Google you'd find tons of scripts, some that even launch graphical programs for *nix. The first list of results for "python world clock" seem to suggest this alone.

I created asimple shell script that you can call to print the location and date/time in that given location. Its logic at this moment in time:

TIME_ZONES="Europe/Amsterdam America/Los_Angeles Europe/Dublin"
OUTPUT=""

for loc in $TIME_ZONES; do
    CITY=`echo $loc | sed 's/\// /g' | awk '{ print $2 }'`
    CUR_TIME=`TZ=${loc} date | awk '{ print $2 " " $3 " " $5 }'`
    TEMP=`awk -v l="$CITY" -v t="$CUR_TIME" 'BEGIN { print l "\t" t }'`
    OUTPUT="${OUTPUT}\n${TEMP}"
done

echo $OUTPUT | column -t

Returns:

Amsterdam    1   Nov  01:03:30
Los_Angeles  31  Oct  17:03:30
Dublin       1   Nov  00:03:30

I like the script mivk provided. As I want to be able to specify multiple zones without regex, I adapted the script to use bash when I couldn't get bourne shell to deal with arrays. Anyway, enjoy and thanks for a great forum:

#!/usr/bin/env bash                                                             

# Show date and time in other time zones, with multiple args                                        


elements=$@

zoneinfo=/usr/share/zoneinfo
format='%a %F %T'

for search in ${elements[@]}; do

  find $zoneinfo -type f \
      | grep -i "$search" \
      | while read z
        do
            d=$(TZ=$z date +"$format")
            printf "%-34s %23s\n" ${z#$zoneinfo} "$d"
        done
done

Sample output:

/usr/local/bin/wdate Sydney Stockholm /Australia/Sydney Fri 2015-08-14 05:54:26 /Europe/Stockholm Thu 2015-08-13 21:54:26

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM