echo 20171231 | xargs -i date -d "{} +1 day" | xargs -i date -d "{} -1 month"
**Fri Dec 1 00:00:00 PST 2017**
이 경우 날짜 형식 지정 명령을 파이프하면 12월 1일이 됩니다.
echo 20171231 | xargs -i date -d "{} +1day -1 month"
Sat Dec 2 00:00:00 PST 2017
단일 데이터 명령에 날짜 형식이 포함되면 결과는 12월 2일입니다.
위 명령에서는 -1개월이 +1일보다 우선순위가 높습니다.
누군가 이것이 어떻게 작동하는지 이해하도록 도와줄 수 있습니까?
답변1
아니요, 우선순위는 없습니다.
date
아이러니하게도 이 문제는 이번 달 데비안 사용자 메일링 리스트에 갑자기 나타났습니다. 누군가가 사람이 읽을 수 있는 자연어 날짜 조작 명령을 읽는 사람에게는 GNU 도구의 동작이 매우 일관성이 없어 보인다고 지적했습니다 . Vincent Lefèvre는 다음과 같은 예를 제공합니다.
jdebp % date+%Y-%m-%d -d '2003-02-01 - 1개월' 2003-01-01 jdebp % date+%Y-%m-%d -d '2003-02-01 - 31일' 2003-01-01 jdebp % date+%Y-%m-%d -d '2003-02-01 - 31일 + 1개월' 2003-01-29 jdebp % date+%Y-%m-%d -d '2003-02-01 - 1개월 + 1개월' 2003-02-01 jdebp % date+%Y-%m-%d -d '2003-09-01 1일 전 + 1개월' 2003-09-30 jdebp % date+%Y-%m-%d -d '2003-09-01 1일 전' 2003-08-31 jdebp % date+%Y-%m-%d -d '2003-08-31 + 1개월' 2003-10-01 정제수량%
내부적으로 실제로 일어나는 일은 date
계산 중에 음수 값(예: 2003-03-(-30)
. 그럼 그것재정규화이는 C 표준 라이브러리의 함수를 사용한 모든 작업 이후의 유효하지 않은 날짜입니다.
이게 뭐야?아니요현재 진행 중인 작업은 재정규화입니다.모든 단계에서, 인간과 마찬가지로. 따라서 2003-02-01에서 31일을 뺀 날짜는 date
GNU 프로그램에 유효하지 않은 날짜입니다.2월 30일 부정적, 인간적으로 가능한 한 1월의 유효한 날짜가 아닙니다. 한 달을 추가하면 3월의 유효하지 않은 날짜가 되고 여전히 마이너스 30이 됩니다. 물론 -30
0보다 큰 숫자로 조정하면 2월 전체로 돌아가기 때문에 1월의 해당 날짜로 다시 정규화됩니다. 다른 예에서 재정규화가 없는 유효하지 않은 날짜는 2003-10-00
, 2003-09-00
및 입니다 2003-09-31
.
이것을 귀하의 예에 적용하십시오 :
2017-12-31 + 1 day
2017-12-32
예 , 프로그램 출력 에서 .2018-01-01
2018-01-01 - 1 month
2018-00-01
예 , 프로그램 출력 에서 .2017-12-01
2017-12-31 + 1 day - 1 month
2017-11-32
예 , 프로그램 출력 에서 .2017-12-02
당신이 본대로모든 단계에서 재정규화합니다.date
GNU는 여러 변경 사항을 한 번에 적용하기 때문에 모든 변경 사항을 한 번에 적용하는 것과 동일한 결과를 얻을 수 없습니다.모든 단계에서 재정규화 없음.
추가 읽기
- 마이클 스톤(2013-11-21).
/bin/date
: 일관되지 않은 날짜 구문 분석. 데비안 버그 #729952. - 울프 지비스(2017-03-15). 비생산적인 계산 순서
date
. GNU 버그 #26101. - 빈센트 르페브르(2018-02-06).'수정되지 않음' 오류 라벨 관련 정책. 데비안 사용자입니다.
답변2
date
제가 보기 엔 월이 먼저 반환된 다음 날짜가 해당 순서대로 추가되는 것 같습니다 .
파이프라인에서 작업 순서를 변경하면 다른 작업과 동일한 결과를 얻게 됩니다.
$ echo 20171231 | xargs -i date -d "{} -1 month" | xargs -i date -d "{} +1 day"
Sat Dec 2 00:00:00 EET 2017
문제는 12월 31일부터 한 달 전으로 돌아가는 것이 문제라는 것이다. 지난달 같은 날은 11월 31일이었지만 11월은 30일밖에 남지 않았다. 어떤 의미에서는 11월 31일은 12월 1일과 같기 때문에 후자를 주는 논리도 있습니다.
물론 다른 옵션은 12월 31일부터 11월 30일까지이지만, 완전히 문제가 없는 것은 아닙니다. 그렇다면 Nov 30 - 1 month
10월 30일이어야 할까요, 아니면 10월 31일이어야 할까요?
필요한 논리를 수동으로 구현해야 할 수도 있습니다.
답변3
이 상황의 이유는 다음과 같습니다.
$ a=20171231; b=$(date -d "$a -1 month"); echo "<$b>"
<Fri Dec 1 00:00:00 PST 2017>
주문일이 12월 초로 옮겨졌습니다.
1일을 추가하면 day 가 됩니다 2
.
대신 1월 1일이 되면 한 달 전으로 돌아갑니다.
$ a=20180101; b=$(date -d "$a -1 month"); echo "<$b>"
<Fri Dec 1 00:00:00 PST 2017>
이것은 날짜의 내부 특성입니다.
date
주어진 날짜와 동일한 이전 달의 날짜를 반환합니다.
$ a=20171110; b=$(date -d "$a -1 month"); echo "<$b>"
<Tue Oct 10 00:00:00 PST 2017>
즉, 11월에 지정된 날짜는 소급하여 10월로 날짜가 지정될 수 있습니다. 하지만 만약 그 날이 31일이라면 문제가 생길 것입니다. 예를 들어 10월 31일부터 시작하면 9월 31일이 없으므로 10월 1일로 돌아갑니다.
$ a=20171031; b=$(date -d "$a -1 month"); echo "<$b>"
<Sun Oct 1 00:00:00 AST 2017>
월 이동은 날짜가 01인 경우에만 정확합니다. 2월은 특히 홀수 달입니다.
$ a=20170331; b=$(date -d "$a -1 month"); echo "<$b>"
<Fri Mar 3 00:00:00 AST 2017>
2월 31일이 없기 때문이죠.