SE 네트워크의 다른 모든 질문에는 now
(묻다) 또는 날짜만 지정하는 경우(묻다).
내가 원하는 것은 날짜와 시간을 제공한 다음 거기에서 시간을 빼는 것입니다.
이것이 내가 먼저 시도한 것입니다.
date -d "2018-12-10 00:00:00 - 5 hours - 20 minutes - 5 seconds"
결과는 2018-12-10 06:39:55
- 7시간이 추가되었습니다. 그런 다음 20:05분을 뺍니다.
man
및 info
페이지를 읽은 후 date
문제를 해결한 것 같습니다.
date -d "2018-12-10T00:00:00 - 5 hours - 20 minutes - 5 seconds"
그러나 결과는 동일합니다. 7시간은 어디서 오는가?
그 날 윤초가 7200초일지도 모른다고 생각해서 다른 날짜도 시도해 봤는데, 하하. 그러나 결과는 같습니다.
다음은 몇 가지 추가 예입니다.
$ date -d "2018-12-16T00:00:00 - 24 hours" +%Y-%m-%d_%H:%M:%S
2018-12-17_02:00:00
$ date -d "2019-01-19T05:00:00 - 2 hours - 5 minutes" +%Y-%m-%d_%H:%M:%S
2019-01-19_08:55:00
그러나 여기서 상황이 흥미로워집니다. 입력 시간을 생략하면 정상적으로 작동합니다.
$ date -d "2018-12-16 - 24 hours" +%Y-%m-%d_%H:%M:%S
2018-12-15_00:00:00
$ date -d "2019-01-19 - 2 hours - 5 minutes" +%Y-%m-%d_%H:%M:%S
2019-01-18_21:55:00
$ date --version
date (GNU coreutils) 8.30
내가 무엇을 놓치고 있나요?
고쳐 쓰다:Z
끝에 하나를 추가하고 동작이 변경되었습니다.
$ date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S
2019-01-19_04:00:00
하지만 나는 여전히 혼란스러워요. 이 지역에는 별로 없어요GNU 정보 페이지날짜에 대해서.
시간대 문제인 것 같지만 인용하자면달력 위키존재하다ISO 8601:
시간 표현과 함께 UTC 관계 정보가 제공되지 않으면 시간은 현지 시간으로 간주됩니다.
이것이 내가 원하는거야. 현지 시간도 올바르게 설정되어 있습니다. 날짜/시간을 제공하고 그로부터 무언가를 빼려는 간단한 경우에 날짜가 시간대와 혼동되는 이유가 무엇인지 잘 모르겠습니다. 먼저 날짜 문자열에서 시간을 빼면 안 되나요? 먼저 날짜로 변환한 다음 빼더라도 빼기를 생략하면 원하는 결과를 얻을 수 있습니다.
$ date -d "2019-01-19T05:00:00" +%Y-%m-%d_%H:%M:%S
2019-01-19_05:00:00
그래서만약에이것은 실제로 시간대 문제입니다. 이 광기는 어디에서 오는 것입니까?
답변1
이 마지막 예에서는 다음 사항을 명확히 했습니다.시간대.
$ TZ=UTC date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S
2019-01-19_03:00:00
$ TZ=Asia/Colombo date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S
2019-01-19_08:30:00
출력은 시간대에 따라 분명히 다르기 때문에 시간대를 지정하지 않고 시간 문자열에 일부 불분명한 기본값이 적용되는 것으로 의심됩니다. 여러 값을 테스트한 결과UTC-05:00, 그게 뭔지는 모르겠지만요.
$ TZ=UTC date -d "2019-01-19T05:00:00 - 2 hours" +%Y-%m-%d_%H:%M:%S%Z
2019-01-19_08:00:00UTC
$ TZ=UTC date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S%Z
2019-01-19_03:00:00UTC
$ TZ=UTC date -d "2019-01-19T05:00:00" +%Y-%m-%d_%H:%M:%S%Z
2019-01-19_05:00:00UTC
날짜 연산을 수행할 때만 사용됩니다.
여기서 문제 - 2 hours
가 있는 것 같습니다아니요산술적으로 취급되지만시간대 지정자:
# TZ=UTC date -d "2019-01-19T05:00:00 - 2 hours" +%Y-%m-%d_%H:%M:%S%Z --debug
date: parsed datetime part: (Y-M-D) 2019-01-19 05:00:00 UTC-02
date: parsed relative part: +1 hour(s)
date: input timezone: parsed date/time string (-02)
date: using specified time as starting value: '05:00:00'
date: starting date/time: '(Y-M-D) 2019-01-19 05:00:00 TZ=-02'
date: '(Y-M-D) 2019-01-19 05:00:00 TZ=-02' = 1547881200 epoch-seconds
date: after time adjustment (+1 hours, +0 minutes, +0 seconds, +0 ns),
date: new time = 1547884800 epoch-seconds
date: timezone: TZ="UTC" environment value
date: final: 1547884800.000000000 (epoch-seconds)
date: final: (Y-M-D) 2019-01-19 08:00:00 (UTC)
date: final: (Y-M-D) 2019-01-19 08:00:00 (UTC+00)
2019-01-19_08:00:00UTC
따라서 연산이 수행되지 않을 뿐만 아니라 일광 절약 시간제 에 따라 시간이 1시간 조정된 것처럼 나타나서 우리 시간이 다소 우스꽝스럽습니다.
이는 추가에도 적용됩니다.
# TZ=UTC date -d "2019-01-19T05:00:00 + 5:30 hours" +%Y-%m-%d_%H:%M:%S%Z --debug
date: parsed datetime part: (Y-M-D) 2019-01-19 05:00:00 UTC+05:30
date: parsed relative part: +1 hour(s)
date: input timezone: parsed date/time string (+05:30)
date: using specified time as starting value: '05:00:00'
date: starting date/time: '(Y-M-D) 2019-01-19 05:00:00 TZ=+05:30'
date: '(Y-M-D) 2019-01-19 05:00:00 TZ=+05:30' = 1547854200 epoch-seconds
date: after time adjustment (+1 hours, +0 minutes, +0 seconds, +0 ns),
date: new time = 1547857800 epoch-seconds
date: timezone: TZ="UTC" environment value
date: final: 1547857800.000000000 (epoch-seconds)
date: final: (Y-M-D) 2019-01-19 00:30:00 (UTC)
date: final: (Y-M-D) 2019-01-19 00:30:00 (UTC+00)
2019-01-19_00:30:00UTC
추가로 디버깅하면 구문 분석은 (시간대) 및 ( 2019-01-19T05:00:00 - 2
=1시간)이며 암시적으로 추가됩니다. 대신 분을 사용하면 확인하기가 더 쉽습니다.-2
hours
# TZ=UTC date -d "2019-01-19T05:00:00 - 2 minutes" +%Y-%m-%d_%H:%M:%S%Z --debug
date: parsed datetime part: (Y-M-D) 2019-01-19 05:00:00 UTC-02
date: parsed relative part: +1 minutes
date: input timezone: parsed date/time string (-02)
date: using specified time as starting value: '05:00:00'
date: starting date/time: '(Y-M-D) 2019-01-19 05:00:00 TZ=-02'
date: '(Y-M-D) 2019-01-19 05:00:00 TZ=-02' = 1547881200 epoch-seconds
date: after time adjustment (+0 hours, +1 minutes, +0 seconds, +0 ns),
date: new time = 1547881260 epoch-seconds
date: timezone: TZ="UTC" environment value
date: final: 1547881260.000000000 (epoch-seconds)
date: final: (Y-M-D) 2019-01-19 07:01:00 (UTC)
date: final: (Y-M-D) 2019-01-19 07:01:00 (UTC+00)
2019-01-19_07:01:00UTC
따라서 날짜 산술이 수행되고 있지만 우리가 요청한 것은 아닙니다.  ̄\(ツ)/ ̄
답변2
입력 날짜를 ISO 8601로 처음 변환하면 정상적으로 작동합니다.
$ date -d "$(date -Iseconds -d "2018-12-10 00:00:00") - 5 hours - 20 minutes - 5 seconds"
So 9. Dez 18:39:55 CET 2018
답변3
GNU는 date
간단한 날짜 산술을 지원하지만 @sudodus의 답변에 표시된 신기원 시간 계산이 때로는 더 깨끗하고 이식성이 뛰어납니다.
타임스탬프에 시간대가 지정되지 않은 경우 +/-를 사용하면 다른 콘텐츠를 구문 분석하기 전에 시간대를 일치시키려는 후속 시도가 트리거됩니다.
"-" 대신 "ago"를 사용하여 이를 수행하는 방법은 다음과 같습니다.
$ date -d "2018-12-10 00:00:00 5 hours ago 20 minutes ago 5 seconds ago"
Sun Dec 9 18:39:55 GMT 2018
또는
$ date -d "2018-12-10 00:00:00Z -5 hours -20 minutes -5 seconds"
Sun Dec 9 18:39:55 GMT 2018
("Z"를 임의로 사용할 수는 없지만 내 영역에서는 작동하지만 UTC/GMT 영역 타임스탬프가 됩니다. 자체 영역을 사용하거나 ${TZ:-$(date +%z)}
타임스탬프에 추가하여 %z/%Z 를 바꾸세요.)
시간을 조정하려면 다음과 같은 형태의 추가 시간 항목을 추가하세요.
- "5시간 전" - 5시간
- "4시간"은 (암묵적으로) 4시간을 더합니다.
- "3시간 후"는 (명시적으로) 3시간을 추가합니다(이전 버전에서는 지원되지 않음).
어떤 순서로든 많은 복잡한 조정을 사용할 수 있습니다("지난 월요일 이후 14주"와 같은 상대적이고 가변적인 용어는 문제를 야기하지만 ;-)
(여기에 또 다른 문제가 있습니다. date
유효한 날짜는 항상 제공되므로 date -d "2019-01-31 1 month"
"다음 달"과 같이 2019-03-03이 제공됩니다.)
지원되는 시간 및 날짜 형식이 다양하기 때문에 시간대 구문 분석은 필연적으로 엉성합니다. 단일 또는 다중 문자 접미사, 시간 또는 시:분 오프셋, 이름 "America/Denver"(또는 파일 이름)일 수 있습니다. 변수에서 TZ
).
"T"는 단지 구분 기호일 뿐이고 시간대가 아니기 때문에 버전 2018-12-10T00:00:00
이 작동하지 않습니다. 끝에 "Z"를 추가하면 예상대로 작동합니다(선택한 구역의 정확성에 따라 다름).
바라보다: https://www.gnu.org/software/tar/manual/html_node/Date-input-formats.html 특히 섹션 7.7.
답변4
이 솔루션은 이해하기 쉽지만 약간 더 복잡하므로 쉘스크립트로 보여드리겠습니다.
- "1970-01-01 00:00:00 UTC 이후의 초"로 변환
- 차이를 더하거나 빼세요
date
최종 명령줄을 사용하여 사람이 읽을 수 있는 형식으로 다시 변환
쉘 스크립트:
#!/bin/bash
startdate="2018-12-10 00:00:00"
ddif="0" # days
diff="-5:-20:-5" # hours:minutes:seconds
#-----------------------------------------------------------------------------
ss1970in=$(date -d "$startdate" "+%s") # seconds since 1970-01-01 00:00:00 UTC
printf "%11s\n" "$ss1970in"
h=${diff%%:*}
m=${diff#*:}
m=${m%:*}
s=${diff##*:}
difs=$(( (((ddif*24+h)*60)+m)*60+s ))
printf "%11s\n" "$difs"
ss1970ut=$((ss1970in + difs)) # add/subtract the time difference
printf "%11s\n" "$ss1970ut"
date -d "@$ss1970ut" "+%Y-%m-%d %H:%M:%S"