linux date 명령으로 ISO8601 날짜를 구문 분석하는 방법


15

date 명령을 사용하여 date 명령 자체가 해석 할 수있는 파일 타임 스탬프를 생성하려고합니다. 그러나 date 명령은 자체 출력을 좋아하지 않는 것이므로이 문제를 해결하는 방법을 모르겠습니다. 지목 사항:

sh-4.2$ date
Fri Jan  3 14:22:19 PST 2014
sh-4.2$ date +%Y%m%dT%H%M
20140103T1422
sh-4.2$ date -d "20140103T1422"
Thu Jan  2 23:22:00 PST 2014

날짜가 15 시간 오프셋으로 문자열을 해석하는 것으로 보입니다. 이에 대한 알려진 해결 방법이 있습니까?

편집 : 이것은 표시 문제가 아닙니다.

sh-4.2$ date +%s
1388791096
sh-4.2$ date +%Y%m%dT%H%M
20140103T1518
sh-4.2$ date -d 20140103T1518 +%s
1388737080
sh-4.2$ python
Python 3.3.3 (default, Nov 26 2013, 13:33:18) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 1388737080 - 1388791096
-54016
>>> 54016/3600
15.004444444444445
>>> 

유닉스 타임 스탬프로 표시 될 때 여전히 15 시간까지 꺼져 있습니다.

편집 # 1

어쩌면 나는이 질문을 조금 다르게 바꿔야 할 수도 있습니다. 다음 형식의 ISO8601 기본 타임 스탬프 목록이 있다고 가정합니다.

  • YYYYMMDDThhmm
  • YYYYMMDDThhmmss

해당 Unix 타임 스탬프로 변환하는 가장 간단한 방법은 무엇입니까?

예를 들면 다음과 같습니다.

- 20140103T1422   = 1388787720
- 20140103T142233 = 1388787753

1
@drewbenn 타임 스탬프에 특수 문자를 사용할 수 없습니다. 숫자와 문자 만 그래서 안타깝게도 그렇게 할 수 없습니다.
alex.forencich

@sim TZ가 설정되지 않았지만 / etc / localtime이 연결되었습니다.
alex.forencich

당신은 나를 죽이고 있어요, 이것이 당신의 마지막 질문입니까? 8-)
slm

20140103T1518는 유효하지 않습니다 ISO 8601, 그것은 시간대 부분을 그리워합니다
Ferrybig

답변:


9

"알려진 해결 방법"을 요청합니다. 다음은 간단한 것입니다.

$ date -d "$(echo 20140103T1422 | sed 's/T/ /')"
Fri Jan  3 14:22:00 PST 2014

sed"T"를 공백으로 바꾸는 데 사용 합니다. 결과는 date이해 하는 형식입니다 .

ISO8601 날짜에 초를 추가하면 date더 많은 변경이 필요합니다.

$ date -d "$(echo 20140103T142211 | sed -r 's/(.*)T(..)(..)(..)/\1 \2:\3:\4/')"
Fri Jan  3 14:22:11 PST 2014

sed의 "T"를 공백으로 바꾸고 HHMMSS를 HH : MM : SS로 분리합니다.


+가 삭제되면 저에게 효과적입니다. 그러나 두 번째 정밀 타임 스탬프에는 작동하지 않으며 미세한 정밀도 만 작동합니다.
alex.forencich

@ alex.forencich 답변은 초 정밀도로 업데이트되었습니다. 내가 선택한 초 형식이 필요한 형식이 아닌 경우 알려주십시오.
John1024

8

로 coreutils 정보 문서는 ISO 8601 "확장 형식"지원되는 것을 말한다.

하이픈, 콜론 및를 추가해야 +%z작동합니다.

$ date +"%Y-%m-%dT%H:%M:%S%z"
2014-01-03T16:08:23-0800
$ date -d 2014-01-03T16:08:23-0800
Fri Jan  3 16:08:23 PST 2014

질문의 두 번째 부분에 대답하려면 ...

날짜 형식에는 숫자와 기호 만 포함되므로 각 기호를 고유 문자로 바꿀 수 있습니다 (예 : tr

$ ts="$(date +"%Y-%m-%dT%H:%M:%S%z" | tr -- '-:+' 'hcp')"; echo "$ts"
2014h01h03T16c18c04h0800
$ date -d "$(echo "$ts" | tr -- 'hcp' '-:+')"
Fri Jan  3 16:18:04 PST 2014

아니면 사용하여 분석 할 수있는 T과를 -+예를 들어 분리기로 쉘 사용 ${var%word}${var#word}확장을

$ ts="$(date +"%Y%m%dT%H%M%S%z")"; echo "$ts"
20140103T162228-0800
$ date=${ts%T*}; time=${ts#*T}
etc.    

또는 bash정규식 일치를 사용하여

$ ts="$(date +"%Y%m%dT%H%M%S%z")"; echo "$ts"
20140103T165611-0800
$ [[ "$ts" =~ (.*)(..)(..)T(..)(..)(..)(.....) ]]
$ match=("${BASH_REMATCH[@]}")
$ Y=${match[1]}; m=${match[2]}; d=${match[3]}; H=${match[4]}; M=${match[5]}; S=${match[6]}; z=${match[7]}
$ date -d "$Y-$m-$d"T"$H:$M:$S$z"
Fri Jan  3 16:56:11 PST 2014

또는 Perl, Python 등


타임 스탬프에는 특수 문자를 사용할 수 없습니다. 자동으로 다시 추가하는 좋은 방법을 알고 있습니까?
alex.forencich

6

GNU coreutils는 버전 8.13 이후 (2011-09-08에 릴리스 된) ISO 8601 날짜 만 입력으로 지원했습니다 . 이전 버전을 사용해야합니다.

이전 버전에서는 T공백 으로 대체해야 합니다. 그렇지 않으면 미군 시간대 로 해석됩니다 .

최근 버전에서도 숫자와 T중간에 숫자 만있는 기본 형식이 아니라 완전히 문장 부호가있는 형식 만 인식됩니다 .

# Given a possibly abbreviated ISO date $iso_date...
date_part=${iso_date%%T*}
if [ "$date_part" != "$iso_date" ]; then
  time_part=${abbreviated_iso_date#*T}
  case ${iso_date#*T} in
    [!0-9]*) :;;
    [0-9]|[0-9][0-9]) time_part=${time_part}:00;;
    *)
      hour=${time_part%${time_part#??}}
      minute=${time_part%${time_part#????}}; minute=${minute#??}
      time_part=${hour}:${minute}:${time_part#????};;
  esac
else
  time_part=
fi
date -d "$date_part $time_part"

2

에 대한 맨 페이지에서이 메모를 확인했습니다 date.

DATE STRING
      The --date=STRING is a mostly free format human readable date string
      such as "Sun, 29 Feb 2004 16:21:42 -0800"  or  "2004-02-29
      16:21:42"  or  even  "next Thursday".  A date string may contain 
      items indicating calendar date, time of day, time zone, day of
      week, relative time, relative date, and numbers.  An empty string 
      indicates the beginning of the day.  The date  string  format
      is more complex than is easily documented here but is fully described 
      in the info documentation.

결정적이지는 않지만 T[ISO 8601]에 대해 시도한대로 시간 형식 문자열을 명시 적으로 표시하지는 않습니다 . @Gilles의 답변에서 알 수 있듯이 GNU CoreUtils에서 ISO 8601 의 지원 은 비교적 새로운 것입니다.

문자열 재 포맷

Perl을 사용하여 문자열을 재구성 할 수 있습니다.

예:

$ date -d "$(perl -pe 's/(.*)T(\d{2})(\d{2})(\d{2})/$1 $2:$3:$4/' \
    <<<"20140103T142233")"
Fri Jan  3 14:22:33 EST 2014

초가 포함 된 문자열과 그렇지 않은 문자열을 모두 처리 할 수 ​​있습니다.

20140103T1422 :

$ date -d "$(perl -pe 's/^(.*)T(\d{2})(\d{2})(\d{2})$/$1 $2:$3:$4/ || \
     s/^(.*)T(\d{2})(\d{2})$/$1 $2:$3:00/' <<<"20140103T1422")"
Fri Jan  3 14:22:00 EST 2014

20140103T142233 :

$ date -d "$(perl -pe 's/^(.*)T(\d{2})(\d{2})(\d{2})$/$1 $2:$3:$4/ || \
     s/^(.*)T(\d{2})(\d{2})$/$1 $2:$3:00/' <<<"20140103T142233")"
Fri Jan  3 14:22:33 EST 2014

@ alex.forencich-두 시간 형식을 모두 처리하는 대체 명령입니다. 더 이상 관련이없는 위의 의견을 부탁드립니다.
slm

1

날짜 매뉴얼 페이지에 따르면, 출력하는 형식이 date입력으로 예상되는 형식과 다릅니다 . 다음은 매뉴얼 페이지의 내용입니다.

date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]

따라서 다음과 같이 할 수 있습니다.

# date +%m%d%H%M%Y
010402052014
# date 010402052014
Sat Jan  4 02:05:00 EAT 2014

출력 문자열을 정의하는 데 사용되는 변수에서 +%m%d%H%M%Y입력으로 예상되는 것과 동일하기 때문입니다.


그런 다음 ISO8601 형식 날짜를 필요한 날짜에 매핑하는 명령을 제공 할 수 있습니까? 실제 저장된 타임 스탬프는 날짜별로 정렬 할 수 있도록 ISO8601 형식이어야합니다.
alex.forencich
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.