두 날짜 간의 날짜 차이를 찾는 방법은 무엇입니까?


82

A = "2002-20-10"
B = "2003-22-11"

두 날짜 간의 날짜 차이를 찾는 방법은 무엇입니까?


5
아래에 설명 된대로 날짜가 잘못되었습니다. 날짜는 yyyy-mm-dd 여야합니다.
Peter Flynn

많은 답변은 (GNU-) date의 -d 옵션을 사용합니다. 나는 이것이 POSIX 날짜의 일부가 아니므로 이식성이 떨어짐을 추가하고 싶습니다. OP가 Solaris와 같은 Unix 배포판에서 작동하지 않고 "일반적인 Linux"에서만 작동하는 한, 그 또는 그녀는 괜찮을 것입니다. 각각의 태그는 imho를 도울 것입니다.
Cadoiz

답변:


33

GNU date가있는 경우 임의의 날짜 표시 ( -d옵션) 를 인쇄 할 수 있습니다 . 이 경우 EPOCH 이후 날짜를 초로 변환하고 빼고 24 * 3600으로 나눕니다.

아니면 휴대용 방법이 필요하십니까?


1
@Tree : 직접 구현하지 않고 날짜를 뺄 수있는 휴대용 방법은 없다고 생각합니다. 그다지 어렵지 않습니다. 유일한 관심사는 윤년입니다. 하지만 요즘은 누구나 날짜를 빼고 싶어합니다.보기에는 unix.stackexchange.com/questions/1825/… :)

14
lazyweb을 위해 user332325가 의미하는 바는 다음과 같습니다.echo "( `date -d $B +%s` - `date -d $A +%s`) / (24*3600)" | bc -l
Pablo Mendes

2
이 맥락에서 휴대용이란 무엇을 의미합니까?
htellez

@htellez 여러 플랫폼 (윈도우, 리눅스 등)에서 작동하는 무언가
Sumudu

이 답변을 기반으로 한 bash one liner의 경우 다음을 참조하십시오. stackoverflow.com/a/49728059/1485527
jschnasse 2018

64

bash 방식-날짜를 % y % m % d 형식으로 변환 한 다음 명령 줄에서 직접 수행 할 수 있습니다.

echo $(( ($(date --date="031122" +%s) - $(date --date="021020" +%s) )/(60*60*24) ))

9
날짜가 반드시 %y%m%d형식 일 필요는 없습니다 . 예를 들어 gnu date는 %Y-%m-%d사용 된 OP 형식 을 수락합니다 . 일반적으로 ISO-8601이 좋은 선택이며 OP의 형식이 그러한 형식 중 하나입니다. 연도가 2 자리 인 형식은 피하는 것이 좋습니다.
mc0e 2015-06-16

2
오늘 과 의 차이를 위해 사용 days_diff=$(( (`date -d $B +%s` - `date -d "00:00" +%s`) / (24*3600) ))하실 수 있습니다 . 음 $days_diff의 정수 (더 소수를 즉 없음) 될 것입니다
줄리앙

1
이것은 date설치된 변형에 따라 다릅니다 . 그것은 GNU에서 작동합니다 date. POSIX에서는 작동하지 않습니다 date. 이것은 대부분의 독자에게 문제가되지 않지만 주목할 가치가 있습니다.
mc0e

POSIX 이식성을 정말로 원한다면 다음을 확인하십시오. unix.stackexchange.com/a/7220/43835
mc0e

1
그냥 전투의 혼란 : OP의 형식은 없습니다 %Y-%m-%d 우리가 소개 될 때까지, August 2.0그리고 October 2.0영업 이익의 형식입니다 %Y-%d-%m. 관련 xkcd : xkcd.com/1179
색종이 조각

22

tl; dr

date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s)) / (60*60*24) ))

조심해! 여기에있는 많은 bash 솔루션은 일광 절약 시간이 시작되는 날짜 (해당되는 경우)에 걸쳐있는 날짜 범위에 대해 손상되었습니다. 이는 $ ((math)) 구문이 결과 값에 대해 'floor'/ truncation 연산을 수행하여 정수만 반환하기 때문입니다. 설명하겠습니다.

DST는 올해 미국에서 3 월 8 일에 시작되었으므로 다음과 같은 기간을 사용하겠습니다.

start_ts=$(date -d "2015-03-05" '+%s')
end_ts=$(date -d "2015-03-11" '+%s')

이중 괄호로 무엇을 얻었는지 봅시다 :

echo $(( ( end_ts - start_ts )/(60*60*24) ))

'5'를 반환합니다.

'bc'를 더 정확하게 사용하면 다른 결과를 얻을 수 있습니다.

echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc

'5.95'를 반환합니다. 누락 된 0.05는 DST 전환으로 인한 손실 시간입니다.

그렇다면 이것이 어떻게 올바르게 수행되어야합니까?
대신 이것을 사용하는 것이 좋습니다.

printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc)

여기서 'printf'는 'bc'로 계산 된 더 정확한 결과를 반올림하여 정확한 날짜 범위 '6'을 제공합니다.

편집 : 최근에 사용하고있는 @ hank-schultz의 의견에서 답변을 강조 표시합니다.

date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s) )/(60*60*24) ))

윤초는 차이에 더해지기 때문에 항상 나중 날짜에서 이전 날짜를 빼는 한 윤초는 안전해야합니다. 잘림은 올바른 결과로 효과적으로 반올림됩니다.


6
대신 시작과 끝 모두의 시간대를 지정하고 (동일한 지 확인) 다음과 같이 더 이상이 문제가 발생하지 않습니다. echo $(( ($(date --date="2015-03-11 UTC" +%s) - $(date --date="2015-03-05 UTC" +%s) )/(60*60*24) )), 5 대신 6을 반환합니다.
Hank Schultz

1
아, 응답자 중 한 명이 다른 변종에 의해 반복되는 기본 솔루션의 부정확성에 대해 생각했습니다. 좋아요! 윤초는 어떻습니까? 윤초에 안전합니까? 소프트웨어 가 특정 시간에 실행되면 하루 단위로 결과를 반환하는 선례 가 있으며 윤초와 관련된 ref 문제가 있습니다 .
Stéphane Gourichon 2015

예를 들어 "잘못된"계산이 여기에 올바르게 표시됩니다 (Ubuntu 15.04 AMD64, GNU 날짜 버전 8.23). 아마도 귀하의 예는 시간대에 따라 달라질 수 있습니까? 제 시간대는 "Europe / Paris"입니다.
Stéphane Gourichon 2015

동일한 시간대의 MSYS에서 GNU 날짜 2.0을 사용한 "잘못된"계산에 대한 동일한 좋은 결과입니다.
Stéphane Gourichon 2015

1
@ StéphaneGourichon, 2015 년 3 월 29 일에 시간대의 일광 절약 시간이 변경된 것으로 보입니다. 포함 된 날짜 범위를 사용해보세요.
evan_b

20

그리고 파이썬에서

$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398

2
@mouviciel 정말 아닙니다. 파이썬이 항상 존재하는 것은 아닙니다.
mc0e

1
그 맥락에서 @ mc0e, 항상 존재하는 것은 없습니다
Sumudu

5
@Anubis OP는 태그를 bash및 로 지정 shell했으므로 * nix 시스템에 대해 이야기하고 있다고 가정 할 수 있습니다. 이러한 시스템 내에서, echo그리고 date안정적으로 존재하지만 파이썬은 없습니다.
mc0e

2
@ mc0e 맞아요. 비록 python2는 대부분의 * nix 시스템에서 사용할 수 있지만, 저가형 장치 (임베디드 등)의 경우 기본 도구로만 살아남 아야합니다.
Sumudu

11

이것은 나를 위해 작동합니다.

A="2002-10-20"
B="2003-11-22"
echo $(( ($(date -d $B +%s) - $(date -d $A +%s)) / 86400 )) days

인쇄물

398 days

무슨 일이야?

  1. AB 에 유효한 시간 문자열을 제공하십시오.
  2. 사용 date -d처리 시간 문자열로
  3. date %s1970 년 이후의 시간 문자열을 초로 변환하는 데 사용 합니다 (unix epoche).
  4. bash 매개 변수 확장 을 사용 하여 초를 뺍니다.
  5. 하루에 초로 나누기 (86400 = 60 * 60 * 24)
  6. ! DST 는 고려되지 않습니다! unix.stackexchange 에서이 답변을 참조하십시오 !

7

-d 옵션이 시스템에서 작동하는 경우 다른 방법이 있습니다. 1 년 365 일을 고려했기 때문에 윤년을 설명하지 않을 것이라는 경고가 있습니다.

date1yrs=`date -d "20100209" +%Y`
date1days=`date -d "20100209" +%j`
date2yrs=`date +%Y`
date2days=`date +%j`
diffyr=`expr $date2yrs - $date1yrs`
diffyr2days=`expr $diffyr \* 365`
diffdays=`expr $date2days - $date1days`
echo `expr $diffyr2days + $diffdays`

7

편의를 위해 MAC OS X 버전이 있습니다.

$ A="2002-20-10"; B="2003-22-11";
$ echo $(((`date -jf %Y-%d-%m $B +%s` - `date -jf %Y-%d-%m $A +%s`)/86400))

nJoy!


1
-bash : (-) / 86400 : 구문 오류 : 피연산자 예상 (오류 토큰은 ") / 86400")
cavalcade

1
@cavalcade - 당신이하지 않은 때문이다A="2002-20-10"; B="2003-22-11"
RAM237

감사합니다.이 특별한 경우에도 작동하지만을 사용하는 것이 좋습니다 echo $(((`date -jf "%Y-%d-%m" "$B" +%s` - `date -jf "%Y-%d-%m" "$A" +%s`)/86400)). 즉, 형식과 변수를 큰 따옴표로 묶거나 다른 날짜 형식 (예 : %b %d, %Y/ Jul 5, 2017) 에서 실패 할 수 있습니다.
RAM237

@ RAM237 그게 내가 관심을 기울이지 않아 얻는 것입니다 headsmack 잘 발견, 감사합니다
cavalcade

5

GNU 날짜가 없더라도 Perl이 설치되어있을 것입니다.

use Time::Local;
sub to_epoch {
  my ($t) = @_; 
  my ($y, $d, $m) = ($t =~ /(\d{4})-(\d{2})-(\d{2})/);
  return timelocal(0, 0, 0, $d+0, $m-1, $y-1900);
}
sub diff_days {
  my ($t1, $t2) = @_; 
  return (abs(to_epoch($t2) - to_epoch($t1))) / 86400;
}
print diff_days("2002-20-10", "2003-22-11"), "\n";

398.041666666667일광 절약으로 인해 398 일 1 시간 이 반환 됩니다.


내 피드에 질문이 다시 나타났습니다. 다음은 Perl 번들 모듈을 사용하는보다 간결한 방법입니다.

days=$(perl -MDateTime -le '
    sub parse_date { 
        @f = split /-/, shift;
        return DateTime->new(year=>$f[0], month=>$f[2], day=>$f[1]); 
    }
    print parse_date(shift)->delta_days(parse_date(shift))->in_units("days");
' $A $B)
echo $days   # => 398

2

이것은 centos 7에서 작업 할 수있는 가장 간단한 방법입니다.

OLDDATE="2018-12-31"
TODAY=$(date -d $(date +%Y-%m-%d) '+%s')
LINUXDATE=$(date -d "$OLDDATE" '+%s')
DIFFDAYS=$(( ($TODAY - $LINUXDATE) / (60*60*24) ))

echo $DIFFDAYS

2

다음은 zsh를 사용한 작업 방식입니다. OSX에서 테스트 :

# Calculation dates
## A random old date
START_DATE="2015-11-15"
## Today's date
TODAY=$(date +%Y-%m-%d)

# Import zsh date mod
zmodload zsh/datetime

# Calculate number of days
DIFF=$(( ( $(strftime -r %Y-%m-%d $TODAY) - $(strftime -r %Y-%m-%d $START_DATE) ) / 86400 ))
echo "Your value: " $DIFF

결과:

Your value:  1577

기본적으로 strftime역 ( -r) 기능을 사용 하여 날짜 문자열을 타임 스탬프로 다시 변환 한 다음 계산합니다.


1

Ruby로 가능한 또 다른 해결책을 제출하겠습니다. 지금까지 가장 작고 깨끗해 보이는 것 같습니다.

A=2003-12-11
B=2002-10-10
DIFF=$(ruby -rdate -e "puts Date.parse('$A') - Date.parse('$B')")
echo $DIFF

2
그는 bash에서 방법을 찾고 있습니다.
Cojones 2011 년

2
쉘 자체에서이를 수행 할 수있는 휴대용 방법은 없습니다. 모든 대안은 특정 외부 프로그램 (예 : GNU date또는 일부 스크립팅 언어)을 사용하며 저는 솔직히 Ruby가 여기에 좋은 방법 이라고 생각합니다 . 이 솔루션은 매우 짧으며 비표준 라이브러리 또는 기타 종속성을 사용하지 않습니다. 사실, GNU 날짜를 설치하는 것보다 Ruby를 설치할 가능성이 더 높다고 생각합니다.
GreyCat 2012 년

1

다른 Python 버전 :

python -c "from datetime import date; print date(2003, 11, 22).toordinal() - date(2002, 10, 20).toordinal()"



1

유닉스에서는 GNU 날짜가 설치되어 있어야합니다. bash에서 벗어날 필요가 없습니다. 여기에 단계를 보여주기 위해 며칠을 고려한 해결 방법이 있습니다. 단순화하고 전체 날짜로 확장 할 수 있습니다.

DATE=$(echo `date`)
DATENOW=$(echo `date -d "$DATE" +%j`)
DATECOMING=$(echo `date -d "20131220" +%j`)
THEDAY=$(echo `expr $DATECOMING - $DATENOW`)

echo $THEDAY 

1

이것은 한 달이 1 년의 1/12라고 가정합니다.

#!/usr/bin/awk -f
function mktm(datespec) {
  split(datespec, q, "-")
  return q[1] * 365.25 + q[3] * 365.25 / 12 + q[2]
}
BEGIN {
  printf "%d\n", mktm(ARGV[2]) - mktm(ARGV[1])
}


0

Oracle DB 백업을 3 차 디스크에 수동으로 재 동기화한다고 가정합니다. 그런 다음 해당 디스크에서 이전 백업을 삭제하려고합니다. 여기에 작은 bash 스크립트가 있습니다.

#!/bin/sh

for backup_dir in {'/backup/cmsprd/local/backupset','/backup/cmsprd/local/autobackup','/backup/cfprd/backupset','/backup/cfprd/autobackup'}
do

    for f in `find $backup_dir -type d -regex '.*_.*_.*' -printf "%f\n"`
    do

        f2=`echo $f | sed -e 's/_//g'`
        days=$(((`date "+%s"` - `date -d "${f2}" "+%s"`)/86400))

        if [ $days -gt 30 ]; then
            rm -rf $backup_dir/$f
        fi

    done

done

필요에 맞게 디렉토리와 보존 기간 ( "30 일")을 수정하십시오.


Oracle은 'YYYY_MM_DD'와 같은 형식을 사용하여 백업 세트를 플래시 복구 영역에 저장하므로 'date -d'로 전달하기 위해 밑줄을 삭제합니다
Alex Cherkas

0

MacOS sierra의 경우 (Mac OS X yosemate에서 제공),

파일에서 epoch 시간 (1970 년 초)을 가져 와서 var에 저장하려면 : old_dt=`date -j -r YOUR_FILE "+%s"`

현재 시간의 epoch 시간을 얻으려면 new_dt=`date -j "+%s"`

위의 두 epoch 시간의 차이를 계산하려면 (( diff = new_dt - old_dt ))

diff가 23 일 이상인지 확인하려면 (( new_dt - old_dt > (23*86400) )) && echo Is more than 23 days


0
echo $(date +%d/%h/%y) date_today
echo " The other date is 1970/01/01"
TODAY_DATE="1970-01-01"
BEFORE_DATE=$(date +%d%h%y)
echo "THE DIFFERNS IS " $(( ($(date -d $BEFORE_DATE +%s) - $(date -d $TODAY_DATE +%s)) )) SECOUND

그것을 사용하여 오늘 날짜와 원하는 날짜 이후의 초를 얻으십시오. 날짜로 원하는 경우 86400으로 나누십시오.

echo $(date +%d/%h/%y) date_today
echo " The other date is 1970/01/01"
TODAY_DATE="1970-01-01"
BEFORE_DATE=$(date +%d%h%y)
echo "THE DIFFERNS IS " $(( ($(date -d $BEFORE_DATE +%s) - $(date -d $TODAY_DATE +%s))/ 86400)) SECOUND
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.