`date` 명령에 ISO-8601 주 형식 입력 옵션이 없습니까?

`date` 명령에 ISO-8601 주 형식 입력 옵션이 없습니까?

나는 때때로 이 date명령을 사용하여 ISO-8601 요일 달력을 기반으로 현재 또는 미래 날짜의 주 번호를 확인합니다. 이를 수행하려면 다음을 사용하면 됩니다. date +%V현재 ISO 주 번호를 확인하고 date -d "2021-12-25" +%V다른 날짜(이 경우 크리스마스)의 ISO 주 번호를 확인합니다.

그러나 이를 반대로 하는 것은 불가능해 보입니다. 즉, "주 번호" 형식의 날짜가 주어지면 "월-날짜" 형식의 날짜를 가져옵니다. 예를 들어 를 실행하면 date -d "2021-W50-3"해당 형식이 지원되지 않는다는 오류가 발생합니다. 왜 안 돼? 이 형식을 사용하여 날짜를 입력하거나 저장할 수 있는 방법이 있습니까?

답변1

GNU에는 date비표준 옵션이 있으며 (및 온라인 -d에 문서화된) 제한된 날짜/시간 형식 세트만 지원합니다.info date 'Date input formats'여기).

date더 많은 날짜 형식(참조하는 형식 포함)을 지원하는 구현 의 경우 from 구현을 사용할 수 있습니다( dateGNU 와 같은 ast-open입력 날짜 에서도 작동함).-ddate

(그러나 그런 경우는 거의 없음)의 일부로 빌드된 경우 dateksh93 쉘의 내장 일 수도 있고 ast-open대신 내장(항상 포함됨) 및 지정자( 시간은 없지만 구문 분석된 부분은 복사됨)를 date사용할 수 있습니다 . :printf%Tbash

$ builtin date
$ date -d '2021-W50-3' +%F
2021-12-15
$ printf '%(%F)T\n' 2021-W50-3
2021-12-15

bash쉘(또는 다른 쉘) 에서는 언제든지 다음을 수행할 수 있습니다.

$ ksh93 -c '"${@:0}"' printf '%(%F)T\n' 2021-W50-3
2021-12-15

그러나 시스템에 따라 ksh93은 호출되거나(또는 Solaris 11+에서와 같이, There라고도 함) 전혀 호출되지 않을 수 있습니다 ksh. ksh2020ksh93 sh( ksh예: bash 또는 zsh) 시스템은 기본적으로 설치되지 않습니다. 모든 시스템에서.

참고하시기 바랍니다.기준strftime()이 표준 형식의 날짜는 사양 %G-%V-%u및 해당 표준 기능 에 따라 생성될 수 있습니다.분석하다타임스탬프(strptime())는 지원하지도 않으며 %G지원 %V하지도 않습니다.표준 유닉스getdate()).

GNU는 strptime()현재 이를 표준에 대한 확장으로 이해하지만 무시하도록 문서화되어 있습니다(참조info libc strptime).FreeBSDstrptime()동일한 지시문이 지원된다고 문서화되어 있지만 FreeBSD 12.2( 내장 strftime()사용)에 대한 테스트에서는 작동하지 않는 것 같습니다.zshstrftime -r

그러나 POSIX, GNU 및 freebsd는 strptime()이를 지원합니다 %W.

  • zsh:

    $ strftime -rs t %Y-W%W-%u 2021-W50-3 && strftime %F $t
    2021-12-15
    
  • busybox:

    $ busybox date -D %Y-W%W-%u -d 2021-W50-3 +%F
    2021-12-15
    

%Y-%W동일하지는 않지만 %G-%V이 경우에는 우연의 일치입니다. %W1월 1일은 00이며 월요일인 경우에는 01입니다. 그리고 %V(ISO 주 번호)는 해당 주의 일수가 전년도 또는 올해에 더 있는지에 따라 해당 연도의 첫 번째 주(01) 또는 전년도의 마지막 주(52 또는 53)입니다.

답변2

정확한 ISO 주 날짜(이전 또는 다음 해로의 롤오버 포함)는 두 가지 실행을 사용하여 얻을 수 있습니다 date. 하나는 알려진 날짜(저는 6월 1일을 선택했습니다)로 보정하고 다른 하나는 ISO 주/일 차이를 숫자별로 조정합니다. 일. 이는 윤년의 영향을 받지 않습니다. 이것이 월 대신 ISO 주를 사용하는 요점입니다.

이 함수는 2021-W50-3 형식을 2021-12-15로 변환하고 연도 반전을 표시하는 테스트를 수행합니다.

#! /bin/bash

isoDate () {

    declare -a dR   #.. Required date
    declare -a dC   #.. Calibration date.
    printf 1>&2 '\nAsked %s\n' "${1}"   #debug
    IFS='-' read -a dR <<<"${1}"
    IFS='-' read -a dC <<<"$( date -d "${dR[0]}-06-01" '+%G-W%V-%u' )"
    dR[1]=${dR[1]#W}; dR[1]=${dR[1]#0}
    dC[1]=${dC[1]#W}; dC[1]=${dC[1]#0}
    declare Adj=$(( 7 * (${dR[1]} - ${dC[1]}) + ${dR[2]} - ${dC[2]} ))
    date -d "${dR[0]}-06-01 + ${Adj} days" '+%Y-%m-%d'
}

    Ymd=$( isoDate '2021-W50-3' )
    printf 'Found %s\n' "${Ymd}"
    date -d "${Ymd}" '+Check %G-W%V-%u'

    Ymd=$( isoDate '2020-W01-1' )
    printf 'Found %s\n' "${Ymd}"
    date -d "${Ymd}" '+Check %G-W%V-%u'

    Ymd=$( isoDate '2011-W52-7' )
    printf 'Found %s\n' "${Ymd}"
    date -d "${Ymd}" '+Check %G-W%V-%u'

결과:

$ ./isoDate

Asked 2021-W50-3
Found 2021-12-15
Check 2021-W50-3

Asked 2020-W01-1
Found 2019-12-30
Check 2020-W01-1

Asked 2011-W52-7
Found 2012-01-01
Check 2011-W52-7
$ 

관련 정보