指定された時間(8時間など)のみを出力し、UTCタイムゾーンの変更に応じて時間を移動する必要があります。
私が見たい結果は次のとおりです。
Athens 15 16 17 18 19 20 21 22 (+2)
Hong_Kong 21 22 23 00 01 02 03 04 (+8)
date
私は命令で遊んで発見しました。SuperUserのこの興味深いコード。私には学ぶことがたくさんあります。私はそれを自分のニーズに合わせて調整しました。しかし、タイムゾーンの変更で論理的な問題を発見しました。ループが24時間の範囲を超えて継続時間を増やすことです。したがって、上記の例ではなく、次のように印刷されます。
Athens 15 16 17 18 19 20 21 22 (+2)
Hong_Kong 21 22 23 24 25 26 27 28 (+8)
これは明らかに間違っています。
コードはソートでネストされたループを使用します。生涯にわたって時間範囲を24桁に制限する方法はわかりません。
これは、作者のコードで何が起こっているのかについてのおおよそのアイデアです。 24時間以上屋根を防ぎ、23時から00時まで屋根をする方法は?
#!/bin/bash
timezones="2" #In the actual script this is a variable generated by a provided array of cities.
workday="08 20" #This specifies the displayed range of hours e.g working hours
for tz in `seq $timezones`
do
printf "City-$tz " # Just a placeholder, instead of an actual city from timezone file
timediff[$tz]=6. # This is a simplified command. IN the actual script time difference calculated from deducting my local time from enquiring city time zone
for h in `seq $workday` #loop hours
do
printf "%02d " $(($h++${timediff[$tz]}))
done
printf " \n"
done
出力
%
City-1 14 15 16 17 18 19 20 21 22 23 24 25 26
City-2 14 15 16 17 18 19 20 21 22 23 24 25 26
PS上記の例では、タイムラインのタイムゾーンの変更は表示されません。私はそれを実行する方法を知りません。
答え1
timediff[$tz]=6.
整数演算のみをサポートするBashでは、ドット入力が機能しないため、スクリプトは実行されません。
とにかく、数列を22、23、0、1、...にするには、概念はモジュラー算術であり、C系列言語の演算子は%
。例えば
for i in 1 2 3 4 5; do
echo $(( i % 3 ))
done
印刷1 2 0 1 2
。% 24
もちろん、使う時間と同じです。もちろん、ユーザーは表示された時間がどの日かを知る必要があります。たとえば、UTC+0200からUTC+1200に変換されます。
mytz=2 othertz=12
for h in {8..16}; do
printf "%02d ($mytz) == %02d ($othertz)\n" "$h" "$(( (h - mytz + othertz) % 24))";
done
08 (+2) == 18 (+12)
などを与える
タイムゾーンの正しいファイル名がわかっている場合は、date
翻訳に環境変数を使用することもできます。TZ
GNUの日付はここで使用されます:
hour=08
tz=Asia/Hong_Kong
printf "local: %s\nother: %s\n" "$(date +"%F %T %Z (%z)" -d "@$ts")" "$(TZ=$tz date +"%F %T %Z (%z)" -d "@$ts")"
出力:
local: 2021-12-08 08:00:00 EET (+0200)
other: 2021-12-08 14:00:00 HKT (+0800)
答え2
実際のタイムゾーンのリストを取得できる場合は、次のことができます(GNU仮定date
)。
#!/bin/bash
timezones=("Europe/Athens" "Asia/Hong_Kong");
workday="08 20" #This specifies the displayed range of hours e.g working hours
printf '%-30s' "Here"
for myHour in $(seq $workday); do
printf '%02d ' "$myHour"
done
printf '\n'
for tz in "${timezones[@]}"; do
printf '%-30s' "$tz"
for myHour in $(seq $workday); do
theirHour=$(TZ="$tz" date -d "@$(date -d "$myHour" +%s)" +%H);
printf '%02d ' "$theirHour"
done
printf '\n'
done
次を生成します。
$ foo.sh
Here 08 09 10 11 12 13 14 15 16 17 18 19 20
Europe/Athens 10 11 12 13 14 15 16 17 18 19 20 21 22
Asia/Hong_Kong 16 17 18 19 20 21 22 23 00 01 02 03 04
タイムゾーンを取得できず、自分のタイムゾーンに基づいてオフセットを使用する必要があり、質問に正確な出力を表示するには、次のことを試してください。
#!/bin/bash
offsets=("2" "8");
workday="08 20" #This specifies the displayed range of hours e.g working hours
for offset in "${offsets[@]}"; do
for myHour in $(seq $workday); do
theirHour=$(date -d "@$(date -d "$myHour + $offset hours" +%s)" +%H)
printf '%s ' "$theirHour"
done
printf '(+%s)\n' "$offset"
done
次を生成します。
$ foo.sh
10 11 12 13 14 15 16 17 18 19 20 21 22 (+2)
16 17 18 19 20 21 22 23 00 01 02 03 04 (+8)
答え3
すでに良い答えがありますが、コードを少し変更して、24時間で時間を再び00にリセットする必要があると思いました。結果をモジュロ24にインポートします。
printf "%02d " $(((($h++${timediff[$tz]})%24))
また、構文エラーを修正して変更してください。
timediff[$tz]=6.
到着
timediff[$tz]=6
Bashは浮動小数点演算を理解していないので、6.
有効な数値ではありません。
答え4
次のbash
スクリプトは、コマンドラインから複数のタイムゾーンを取得し、現在の時刻から8時間後にそのタイムゾーンの時刻を印刷します。
スクリプトがオプションの-t
オプション引数としてUnixタイムスタンプを指定した場合は、現在の時間ではなくその時間をオフセットに使用します。
スクリプトはローカルタイムゾーンを探し、最初の行に出力します。
スクリプトを実行します。
$ ./script UTC Europe/Zurich Asia/Kabul Africa/Harare
CET 20:39 21:39 22:39 23:39 00:39 01:39 02:39 03:39 (+0100)
UTC 19:39 20:39 21:39 22:39 23:39 00:39 01:39 02:39 (+0000)
Europe/Zurich 20:39 21:39 22:39 23:39 00:39 01:39 02:39 03:39 (+0100)
Asia/Kabul 00:09 01:09 02:09 03:09 04:09 05:09 06:09 07:09 (+0430)
Africa/Harare 21:39 22:39 23:39 00:39 01:39 02:39 03:39 04:39 (+0200)
GNUを使用してdate
現地時間(今日)08:00のタイムスタンプを取得します。
$ ./script -t "$(date -d '08:00' +%s)" UTC Europe/Zurich Asia/Kabul Africa/Harare
CET 08:00 09:00 10:00 11:00 12:00 13:00 14:00 15:00 (+0100)
UTC 07:00 08:00 09:00 10:00 11:00 12:00 13:00 14:00 (+0000)
Europe/Zurich 08:00 09:00 10:00 11:00 12:00 13:00 14:00 15:00 (+0100)
Asia/Kabul 11:30 12:30 13:30 14:30 15:30 16:30 17:30 18:30 (+0430)
Africa/Harare 09:00 10:00 11:00 12:00 13:00 14:00 15:00 16:00 (+0200)
スクリプト:
#!/bin/bash
unset -v t0
while getopts t: opt; do
case $opt in
t) t0=$OPTARG ;;
*) echo 'Error' >&2; exit 1
esac
done
shift "$(( OPTIND - 1 ))"
# Use current time if t0 is still unset.
if [ "${t0:+set}" != set ]; then
printf -v t0 '%(%s)T' -1
fi
# Try to figure out local time zone.
printf -v local_zone '%(%Z)T' "$t0"
# Prepend local time zone to list if set.
set -- ${local_zone:+"$local_zone"} "$@"
export TZ
for TZ do
{
printf '%s\n' "$TZ"
for (( offset = 0; offset < 8; ++offset )); do
printf '%(%H:%M)T\n' "$(( t0 + 3600*offset ))"
done
printf '(%(%z)T)\n' "$t0"
} | paste -s -
done | column -t
このスクリプトはprintf
フォーマット%(...)T
文字列を使用してタイムスタンプ形式を指定します。このフォーマット文字列はbash
バージョン4.2で導入されました。これにより、GNUを持たないシステムでもスクリプトを使用できますdate
。
タイムゾーン別の環境変数を順番に設定して、TZ
希望のタイムゾーンのタイムスタンプを出力できます。内部ループは現在の時間(または与えられた時間)と次の8時間を繰り返して、別の行にフォーマットされた時間を出力します。次に、を使用して行全体に整理し、次に「paste
Format to Table」を使用しますcolumn
。