Command-line script for displaying world clocks, allows zonefiles or zone names inputs.
Forked from Gist, which was from an Stackoverflow answer.
Heavily modified by Yu-Jie Lin.
Command-line script for displaying world clocks, allows zonefiles or zone names inputs.
Forked from Gist, which was from an Stackoverflow answer.
Heavily modified by Yu-Jie Lin.
#!/bin/sh | |
# Command-line world clock | |
# Taken from http://stackoverflow.com/questions/370075/command-line-world-clock | |
# Modified by Yu-Jie Lin | |
# usage: | |
# cliclock.sh [[zonefile|zonename] ...] | |
# | |
# zonename can be full or partial, e.g. America/New_York or 'new york' | |
# | |
# default ~/.worldclock.zones and zonefile looks like: | |
# US/Pacific | |
# Europe/Berlin | |
# Chile/Continental | |
# new york | |
# Los Angeles | |
: ${WORLDCLOCK_FORMAT:='%Y-%m-%d %H:%M:%S %Z'} | |
if (( $# == 0 )); then | |
: ${WORLDCLOCK_ZONES:=$HOME/.worldclock.zones} | |
if [[ ! -f $WORLDCLOCK_ZONES ]]; then | |
echo 'no zones to display' >&2 | |
exit 1 | |
fi | |
OLDIFS="$IFS" | |
IFS=$'\n' | |
WORLDCLOCK_ZONES=($(cat "$WORLDCLOCK_ZONES")) | |
IFS="$OLDIFS" | |
else | |
while (( $# > 0)); do | |
if [[ -f "$1" ]]; then | |
OLDIFS="$IFS" | |
IFS=$'\n' | |
WORLDCLOCK_ZONES=("${WORLDCLOCK_ZONES[@]}" $(cat "$1")) | |
IFS="$OLDIFS" | |
else | |
WORLDCLOCK_ZONES=("${WORLDCLOCK_ZONES[@]}" "$1") | |
fi | |
shift | |
done | |
fi | |
ZONEINFO='/usr/share/zoneinfo/' | |
VALID_ZONES=($(find "$ZONEINFO" -path '*/right' -prune -o -type f | sed "s|^$ZONEINFO||")) | |
shopt -s nocasematch | |
# Checking zones and set the max length | |
check_zone() { | |
local zone z | |
ret= | |
z="*${1// /?}*" | |
for zone in "${VALID_ZONES[@]}"; do | |
if [[ $zone == $z ]]; then | |
ret="$zone" | |
return | |
fi | |
# match first zone with $zone as substring | |
if [[ ! -z $ret ]] && [[ $zone == $z ]]; then | |
ret="$zone" | |
fi | |
done | |
} | |
zones=() | |
MAX_ZONE_LEN=0 | |
for zone in "${WORLDCLOCK_ZONES[@]}"; do | |
check_zone "$zone" | |
if [[ -z $ret ]]; then | |
echo invalid zone $zone >&2 | |
continue | |
fi | |
zone="$ret" | |
zones=("${zones[@]}" "$zone") | |
(( ${#zone} > MAX_ZONE_LEN )) && MAX_ZONE_LEN=${#zone} | |
done | |
unset VALID_ZONES | |
if (( ${#zones[@]} == 0 )); then | |
echo 'no zones to display' >&2 | |
exit 1 | |
fi | |
# Some zones are invalid, keep error message for 3 seconds | |
(( ${#zones[@]} != ${#WORLDCLOCK_ZONES[@]} )) && sleep 3 | |
unset WORLDCLOCK_ZONES | |
while :; do | |
clear | |
printf -v now '%(%s)T' -1 | |
for zone in "${zones[@]}"; do | |
TZ=$zone printf "%-${MAX_ZONE_LEN}s %($WORLDCLOCK_FORMAT)T\n" "$zone" "$now" | |
done | |
# Allow to elegantly quit this script | |
if read -n 1 -t 1 -s; then | |
case "$REPLY" in | |
q|Q) | |
break | |
;; | |
esac | |
fi | |
done |