지정된 시간(예: 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]})%이십사))
또한 구문 오류를 수정하고 변경하세요.
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
.