22 23 00 01과 같이 24시간 주기로 정렬하는 방법

22 23 00 01과 같이 24시간 주기로 정렬하는 방법

지정된 시간(예: 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번역을 위해 환경 변수를 사용할 수도 있습니다. TZGNU 날짜는 여기에서 사용됩니다:

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.

관련 정보