리눅스에서 bash로 어제 날짜 가져 오기, DST 안전


158

Linux에서 실행되는 쉘 스크립트가 있으며이 호출을 사용하여 어제 날짜를 YYYY-MM-DD형식으로 가져옵니다 .

date -d "1 day ago" '+%Y-%m-%d'

대부분의 시간에 작동하지만 스크립트가 어제 아침에 실행되었을 때 대신에 2013-03-11 0:35 CDT반환 "2013-03-09"되었습니다 "2013-03-10".

아마도 일광 절약 시간제 (어제 시작)는 책임이 있습니다. 나는 방법은 추측하고있어 "1 day ago"그 전에 24 시간 24 시간을 뺀 구현 2013-03-11 0:35 CDT했다 2013-03-09 23:35 CST의 결과에지도하는 "2013-03-09".

그렇다면 리눅스의 bash에서 어제 날짜를 얻는 좋은 DST 안전 방법은 무엇입니까?


항상 동시에 실행합니까, 반복해서 실행합니까?
tink

@tink 매일 00:35에 실행
Ike Walker

답변:


267

얼마나 자주 그리고 언제 실행하는지에 관계없이 이것이 작동해야한다고 생각합니다 ...

date -d "yesterday 13:00" '+%Y-%m-%d'

1
나중에 사용하기 위해 이것을 변수에 어떻게 할당 하시겠습니까?
null

6
@null-다른 쉘 명령의 출력을 할당하는 것과 같은 방법입니다. variable = $ (date -d "어제 13:00" '+ % Y- % m- % d') ...
Julk

GNU-date의 경우 :date -d yesterday 13:00 -I
gogstad

이것은 올바르게 이해한다면 여름과 겨울 시간 사이의 전환이 밤 동안 항상 수행된다는 사실에 의존합니다.
Nicolas Raoul

2
@NicolasRaoul : 보장되지 않습니다. 그러나 이것을 이른 아침으로 예약하는 것은 널리 따르는 협약입니다. 다른 한편으로, 현지 정오 근처에서 스위치가 발생할 장소는 IIRC가 없습니다. 따라서 "1300J는 절대 DST 경계에 있지 않습니다"는 합리적인 가정 입니다.
Piskvor는 건물을

56

Mac OSX의 날짜는 약간 다릅니다.

어제

date -v-1d +%F

지난주

date -v-1w +%F

8
OSX에서 GNU 스타일을 사용하는 데 관심이 있다면 gdatehomebrew의 coreutils패키지 내에서 사용할 수도 있습니다 .
user456584

11
당신 date은 다르다는 것을 의미 합니다.
augurar

12

이것은 또한 작동해야하지만 너무 많을 수도 있습니다.

date -d @$(( $(date +"%s") - 86400)) +"%Y-%m-%d"

구문을 date지원하지 않는 Mac OS X를 다룰 필요가 있다면 이와 같은 yesterday
것들이 필요

7

스크립트가 하루 중 첫 시간에 실행된다고 확신하는 경우 간단히

  date -d "12 hours ago" '+%Y-%m-%d'

BTW, 스크립트가 매일 00:35 (크론 탭을 통해)에 실행되면 DST 변경이 그 시간에 속하는 경우 어떻게 될지 스스로에게 문의해야합니다. 스크립트를 실행할 수 없거나 경우에 따라 두 번 실행할 수 없습니다. 현대 구현 cron되어 아주 똑똑 하지만,이 점이다.


5

당신이 사용할 수있는

date -d "30 days ago" +"%d/%m/%Y"

30 일 전에 날짜를 얻으려면 마찬가지로 30 일을 x 일로 바꿀 수 있습니다


%Y%m%d질문과 일치하도록 형식을 변경해야합니다 . 어쨌든 제대로 작동하면서 나는 upvoted.
isapir

4

여기에 Solaris 및 AIX에서도 작동하는 솔루션이 있습니다.

시간대를 조작하면 몇 시간 동안 시계를 변경할 수 있습니다. 일광 절약 시간 제로 인해 24 시간 전이 오늘 또는 전날이 될 수 있습니다.

어제는 20 시간 또는 30 시간 전입니다. 어느 것? 글쎄, 오늘이 아닌 가장 최근의 것.

echo -e "$(TZ=GMT+30 date +%Y-%m-%d)\n$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1

echo 명령에 사용 된 -e 매개 변수는 bash와 함께 필요하지만 ksh에서는 작동하지 않습니다. ksh에서는 -e 플래그없이 동일한 명령을 사용할 수 있습니다.

다른 환경에서 스크립트를 사용하는 경우 #! / bin / ksh 또는 #! / bin / bash로 스크립트를 시작할 수 있습니다. \ n을 줄 바꿈으로 바꿀 수도 있습니다.

echo "$(TZ=GMT+30 date +%Y-%m-%d)
$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1

0

사용 date하고 신뢰할 수있는 초 만 사용하십시오 .

올바르게 지적했듯이 영어 시간 산술에 의존하면 기본 계산에 대한 많은 세부 정보가 숨겨집니다. 예를 들어 -d yesterday, -d 1 day ago다른 행동을 할 것입니다.

대신, 유닉스 시대 UTC 이후 (정확하게 문서화 된) 초와 bash 산술에 의존하여 원하는 순간을 얻을 수 있습니다.

date -d @$(( $(date +"%s") - 24*3600)) +"%Y-%m-%d"

이것은 또 다른 대답 에서 지적되었습니다 . 이 형식은 다른 date명령 줄 플래그가있는 플랫폼에서보다 이식성이 뛰어나고 언어에 독립적이며 (예 : 프랑스어 로케일의 "어제"대 "계층") 솔직히 (장기적으로) 기억하기 쉬울 것입니다. 이미 알고 있습니다. 그렇지 않으면 자신을 물어 유지 될 수 있습니다 "그것이 -d 2 hours ago-d 2 hour ago다시?" 또는 " 그렇 -d yesterday거나 -d 1 day ago원하는가?"). 여기서 가장 까다로운 부분은 @입니다.

배쉬로 무장하고 다른 것은 없습니다.

배쉬에만 배쉬하면 printf 내장을 통해 어제 시간을 얻을 수도 있습니다.

 %(datefmt)T
     causes printf to output the date-time string resulting from using
     datefmt as a format string for strftime(3).  The  corresponding  argu
     ment  is an integer representing the number of seconds since the
     epoch.  Two special argument values may be used: -1 represents the
     current time, and -2 represents the time the shell was invoked.
     If no argument is specified, conversion behaves as if -1 had
     been  given.
     This is an exception to the usual printf behavior.

그래서,

# inner printf gets you the current unix time in seconds
# outer printf spits it out according to the format
printf "%(%Y-%m-%d)T\n" $(( $(printf "%(%s)T" -1) - 24*3600 ))

또는 temp 변수와 동일합니다 (외부 서브 쉘은 선택 사항이지만 환경 변수를 깨끗하게 유지합니다).

(
  now=$(printf "%(%s)T" -1);
  printf "%(%Y-%m-%d)T\n" $((now - 24*3600));
)

참고 : 맨 페이지에 %()T포맷터에 대한 인수가 기본값 을 사용하지 않는다는 내용이 -1있지만 대신 0을 얻는 것 같습니다 (감사합니다, bash 매뉴얼 버전 4.3.48).


0
date -d "yesterday" '+%Y-%m-%d'

나중에 이것을 사용하려면 :

date=$(date -d "yesterday" '+%Y-%m-%d')

2
이 코드는 OP 문제를 해결할 수 있지만 코드가 OP 문제를 해결하는 방법에 대한 설명을 포함하는 것이 좋습니다. 이렇게하면 미래의 방문자가 게시물에서 배우고 자신의 코드에 적용 할 수 있습니다. SO는 코딩 서비스가 아니라 지식을위한 리소스입니다. 고품질의 완전한 답변은이 아이디어를 강화 시키며 더 많이지지 될 가능성이 높습니다. 이러한 기능과 모든 게시물이 독립적이어야한다는 요구 사항은 포럼과 차별화되는 플랫폼으로서 SO의 강점입니다. 추가 정보를 추가하거나 소스 문서로 설명을 보충하도록 편집 할 수 있습니다.
SherylHohman

0

당신이 사용할 수있는:

date -d "yesterday 13:55" '+%Y-%m-%d'

또는 당신이 검색하고자하는 시간은 bash에 의해 검색됩니다.

달 :

date -d "30 days ago" '+%Y-%m-%d'

0

이 질문은 태그로 "DST 안전"

그리고 포크를 사용하여 date지연을 암시하면 순수한 bash 내장을 사용하는 간단하고 효율적인 방법 이 있습니다.

printf -v tznow '%(%z %s)T' -1
TZ=${tznow% *} printf -v yesterday '%(%Y-%m-%d)T' $(( ${tznow#* } - 86400 ))
echo $yesterday

이것은 포크 하는 것보다 시스템 친 화성이 훨씬 빠릅니다 date.

에서 V> = 5.0 , 새로운 변수가 있습니다$EPOCHSECONDS

printf -v tz '%(%z)T' -1
TZ=$tz printf -v yesterday '%(%Y-%m-%d)T' $(( EPOCHSECONDS - 86400 ))
echo $yesterday
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.