port the timezone section
The original took whatever was typed and handed it straight to timedatectl. An unknown zone — a typo, a guess at the spelling — fails there, and under `set -e` that takes the whole run down four steps in. Names are now checked against /usr/share/zoneinfo before use, and a bad one just re-asks. It also never showed what the machine was already set to, and defaulted to option 1 (UTC) on Enter, so pressing return on a correctly-configured box silently moved it. Now the current zone is printed, Enter keeps it, and a zone equal to the current one reports nothing to do rather than setting it again. timezone_current reads three sources — timedatectl, /etc/timezone, then the /etc/localtime symlink — because they differ in availability rather than in answer: timedatectl needs systemd, /etc/timezone is Debian's, and the symlink is the one that is always there. timezone_set writes through timedatectl where there is a systemd to talk to and the files directly otherwise, which is what it would have written anyway; that is also the WSL path, where timedatectl exists but does nothing. Europe/Berlin added to the shortlist; TIMEZONE in the environment answers the prompt ahead of time and is validated the same way, failing early with the bad value named. Verified detection (UTC here), validation of four names, and the env-var rejection path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -88,3 +88,49 @@ locale_set() {
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Timezone
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# The shortlist offered at the prompt. Any zone name can be typed instead, so
|
||||
# this is a convenience rather than a limit.
|
||||
TZ_OPTIONS=(UTC Europe/Lisbon Europe/London Europe/Berlin Europe/Stockholm US/Eastern US/Pacific Asia/Tokyo)
|
||||
|
||||
# What the machine is set to now.
|
||||
#
|
||||
# Three sources because they disagree about availability rather than about the
|
||||
# answer: timedatectl is absent without systemd (containers, WSL), /etc/timezone
|
||||
# is Debian-specific, and the /etc/localtime symlink is the one thing that is
|
||||
# always true when any of them are.
|
||||
timezone_current() {
|
||||
if command -v timedatectl &>/dev/null && timedatectl show -p Timezone --value 2>/dev/null | grep -q .; then
|
||||
timedatectl show -p Timezone --value 2>/dev/null
|
||||
elif [[ -r /etc/timezone ]]; then
|
||||
tr -d '[:space:]' </etc/timezone
|
||||
elif [[ -L /etc/localtime ]]; then
|
||||
readlink -f /etc/localtime | sed 's|.*/zoneinfo/||'
|
||||
fi
|
||||
}
|
||||
|
||||
# Checked against the zoneinfo database before it is used. `timedatectl
|
||||
# set-timezone` on a name that does not exist fails, and under `set -e` that
|
||||
# takes the whole run down over a typo.
|
||||
timezone_is_valid() { [[ -f "/usr/share/zoneinfo/$1" ]]; }
|
||||
|
||||
timezone_set() {
|
||||
local tz="$1"
|
||||
case "$PM" in
|
||||
brew) systemsetup -settimezone "$tz" >/dev/null ;;
|
||||
*)
|
||||
# timedatectl where there is a systemd to talk to; the files directly
|
||||
# otherwise, which is the same thing it would have written.
|
||||
if command -v timedatectl &>/dev/null && [[ "$IS_WSL" != true ]]; then
|
||||
timedatectl set-timezone "$tz"
|
||||
else
|
||||
ln -sf "/usr/share/zoneinfo/${tz}" /etc/localtime
|
||||
echo "$tz" >/etc/timezone
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user