해결책

해결책

GNU Date는 현재 날짜에서 시간을 빼면 직관적으로 작동합니다.

date '+%F %R'; date '+%F %R' --date='- 1 hour'
2021-04-19 15:35
2021-04-19 14:35

그러나 날짜를 피연산자로 사용하면 결과가 예상치 못한 결과가 됩니다.

$ date '+%F %R' --date='2000/1/2 03:04:05 - 1 hour'
2000-01-02 06:04

$ date '+%F %R' --date='2000/1/2 03:04:05 + 1 hour ago'
2000-01-02 02:04

date이 표현을 어떻게 해석해야 할까요 $date - 1 hour?

답변1

간단히 말해서, --date시간대를 지정하지 않으면 제공한 날짜는 현지 시간이 되며 비슷한 날짜는 +/- NNN시간대로 처리됩니다. 그 이후에는 hour단지 상대 수식어로 취급 되더라도 마찬가지입니다 . 따라서 - 1 hour주어진 시간에서 1시간을 빼는 대신 UTC-01 시간대로 시간을 지정합니다.다음에 추가한 시간이면 충분합니다.


나는 그것이 당신이 시도하고 있는 것에 효과가 있을 것이라고 생각합니다. 오프셋 앞에 시간대를 명시적으로 제공하거나 오프셋을 넣어야 합니다.첫 번째따라서 시간대와 혼동할 수 없습니다.

여기서는 중앙 유럽 서머타임 시간대(CEST)와 오늘 날짜를 사용하고 %Z출력에 추가하여 시간대를 표시합니다. ( %z출력 숫자 시간대 또는 여기를 사용할 수도 있습니다 +0200.)

$ date +'%F %T %Z' -d '2021-04-19 12:00:00 CEST + 5 hours'
2021-04-19 17:00:00 CEST
$ date +'%F %T %Z' -d '+ 5 hours 2021-04-19 12:00:00'
2021-04-19 17:00:00 CEST

물론, 문제의 1월 날짜에는 CEST와 같은 여름 시간대가 유효하지 않습니다. 그러나 두 가지를 다시 정렬하는 것은 여전히 ​​​​작동하며 제공하는 시간은 해당 시간의 현지 시간과 같습니다.

$ date +'%F %T %Z' -d '+ 5 hours 2021-01-01 12:00:00'
2021-01-01 17:00:00 CET

( 2021-10-31 02:30:00CET에도 그 시간이 있었음에도 불구하고 CET를 받았기 때문에...)

(바라보다구 버전다양한 입력을 해석하는 방법에 대한 추가 예는 이 답변을 참조하세요. )


~에 따르면다른 질문에 대한 @muru의 답변--debug, 이 옵션을 사용하여 프로그램이 실제로 수행한 작업을 알려주도록 할 수도 있습니다 . 두 번째와 세 번째 줄을 참고하세요.

$ date --debug +'%F %T %Z' -d '2021-04-19 12:00:00 - 1시간'
날짜: 파싱된 날짜 부분: (YMD) 2021-04-19
날짜:구문 분석 시간 부분: 12:00:00 TZ=-01:00
날짜:관련 부분 구문 분석: +1시간
날짜: 입력 시간대: -01:00(구문 분석된 날짜/시간 문자열에서 설정)
날짜: 지정된 시간을 시작 값으로 사용: '12:00:00'
날짜: 시작 날짜/시간: '(YMD) 2021-04-19 12:00:00 TZ=-01:00'
날짜: '(YMD) 2021-04-19 12:00:00 TZ=-01:00' = 1618837200 epoch 초
날짜: 조정된 시간(+1시간, +0분, +0초, +0나노초),
날짜: 새 시간 = 1618840800 epoch 초
날짜: 출력 시간대: +01:00 (TZ="Europe/Berlin" 환경 값에서 설정)
날짜: 최종: 1618840800.000000000(에포크 초)
날짜: 최종: (YMD) 2021-04-19 14:00:00 (UTC0)
날짜: 최종: (YMD) 2021-04-19 16:00:00 (출력 시간대 TZ=+01:00)
2021-04-19 16:00:00 중앙 유럽 서머타임

매뉴얼 페이지에는 다음과 같이 나와 있습니다.

날짜 문자열 형식은 여기에 쉽게 문서화할 수 있는 것보다 더 복잡합니다 [...]

이것이 적절해 보입니다. 보다 포괄적인 문서는 정보 페이지나 온라인에 있습니다.https://www.gnu.org/software/coreutils/manual/html_node/Date-input-formats.html

답변2

-디

예, -d 값이 단순하면 그 효과를 이해하기 쉽습니다.
예, -d '- 1 hour'시간을 1시간 뒤로 이동합니다.

$ date ; date -d '- 1 hour'
Mon 19 Apr 2021 07:58:52 AM EDT
Mon 19 Apr 2021 06:58:52 AM EDT

시간대

결과 문자열은 date"특정 시점"을 지정합니다.
기본적으로 "시점"은 현지 시간으로 기록됩니다. 그러나 UTC0으로 작성할 수도 있습니다.

$ date ; date -u
Mon 19 Apr 2021 12:43:04 PM WAT
Mon 19 Apr 2021 11:43:04 AM UTC

귀하의 현지 시간이 WAT - 서아프리카 표준시(WAT)라고 가정합니다.

물론 다른 시간대에서도 동일한 "시점"이 발생할 수 있습니다.

$ TZ=Asia/Kolkata date -d "Mon 19 Apr 2021 12:43:04 PM WAT"
Mon 19 Apr 2021 05:13:04 PM IST

이 값에 포함된 내용은 -d위에 인쇄된 날짜입니다.

이는 시간대가 포함된 경우에만 "특정 시점"이 완료됨을 의미합니다.

그렇기 때문에 날짜를 추가 %z하거나 추가 하여 인쇄하는 것이 좋습니다 . %Z이런 의미에서 형식이 %F %R불완전하므로 를 사용하는 것이 좋습니다 +'%F %R %z'.

날짜 문자열

날짜를 사용할 때는 2000/1/2 03:04:05시간대를 지정하지 않습니다.
이것이 바로 명령이 date다음으로 - 1시간대를 나타내는 이유입니다.

$ date -u -d '2000/1/2 03:04:05'; date -u -d '2000/1/2 03:04:05 - 1'
Sun 02 Jan 2000 03:04:05 AM WAT
Sun 02 Jan 2000 05:04:05 AM WAT

현지 시간이 WAT(DST로 인해 변경되지 않고 일광 절약 시간이 적용되지 않음)라고 가정합니다. %zNor 를 사용하지 않으시기 때문에 말씀드릴 수 없습니다 %Z. 시간대를 변경하면 -d값이 +1(WAT) 에서 -12시간 차이로 변경됩니다.

또한 hour그 후에 당신은 한 시간이 더 걸렸다고 썼습니다.

$ date -d '2000/1/2 03:04:05'; date -d '2000/1/2 03:04:05 - 1 hour'
Sun 02 Jan 2000 03:04:05 AM WAT
Sun 02 Jan 2000 06:04:05 AM WAT

결과를 확인하세요.

마지막으로 +1:

$ date -d '2000/1/2 03:04:05 - 1 hour'; date -d '2000/1/2 03:04:05 + 1 hour ago'
Sun 02 Jan 2000 06:04:05 AM WAT
Sun 02 Jan 2000 02:04:05 AM WAT

시간 값은 변경 되지 않지만 +1(WAT에 있거나 이미 +1이기 때문에) hour ago시간은 변경 됩니다.1한 시간 전(3시~2시)으로 돌아갑니다.

해결책

시간대를 -d시간 값에 넣습니다.
또는 관련 부분을 먼저 배치하세요.- 1 hour

$ date -d '2000/1/2 03:04:05 +0100 - 1 hour'
  Sun 02 Jan 2000 02:04:05 AM WAT


$ date -d '-1 hour 2000/1/2 03:04:05'
  Sun 02 Jan 2000 02:04:05 AM WAT

답변3

다른 많은 날짜 처리 도구는 구문 분석 및 날짜 산술을 별도의 단계로 수행합니다. Perl을 예로 들어보겠습니다.

perl -sE '
    use Time::Piece;
    use Time::Seconds;

    $t = Time::Piece->strptime($timestamp, $format);
    say $t->cdate;

    $s = $t + ONE_HOUR;
    say $s->cdate;

    $s = $t - ONE_HOUR;
    say $s->cdate;
' -- -timestamp='2000/1/2 03:04:05' -format='%Y/%m/%d %T'
Sun Jan  2 03:04:05 2000
Sun Jan  2 04:04:05 2000
Sun Jan  2 02:04:05 2000

관련 정보