2つの日付の日数の違いを見つける方法は?


84

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

2つの日付の日数の違いを見つける方法は?


5
以下で説明するように、しかしあなたの日付は間違った方法です:それらはyyyy-mm-ddである必要があります
Peter Flynn

多くの回答は(GNU-)dateの-dオプションを使用しています。これはPOSIX日付の一部ではないため、移植性が低いことを付け加えたいと思います。OPがSolarisのようなUnixディストリビューションではなく、「一般的なLinux」でのみ機能している限り、彼または彼女は優れているはずです。それぞれのタグは私見に役立ちます。
カドイズ

回答:


34

GNUdateを使用している場合は、任意の日付の表現を印刷できます(-dオプション)。この場合、日付をEPOCHからの秒数に変換し、24 * 3600で減算して除算します。

または、ポータブルな方法が必要ですか?


1
@Tree:自分で実装する以外に、日付を減算する移植可能な方法はないと思います。それほど難しくはありません。関心があるのはうるう年だけです。しかし、今日では、誰もが日付を減算したいと思っています。unix.stackexchange.com/ questions / 1825 /…:)

15
lazywebのために、これがuser332325の意味だと思います。– echo "( `date -d $B +%s` - `date -d $A +%s`) / (24*3600)" | bc -l
Pablo Mendes

2
この文脈でポータブルとはどういう意味ですか?
htellez 2016

@htellez複数のプラットフォーム(Windows、Linuxなど)で動作するもの
Sumudu 2018

この回答に基づく
bashone

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の形式はそのような形式の1つです)。2桁の年の形式は避けた方がよいでしょう。
mc0e 2015年

2
今日との違いについては、を使用することをお勧めしますdays_diff=$(( (`date -d $B +%s` - `date -d "00:00" +%s`) / (24*3600) ))$days_diff整数になることに注意してください(つまり、小数はありません)
Julien

1
これは、dateインストールされているバリアントによって異なります。GNUで動作しますdate。POSIXでは動作しませんdate。これはおそらくほとんどの読者にとって問題ではありませんが、注目に値します。
mc0e

POSIXの移植性が本当に必要な場合は、次を確認してください: unix.stackexchange.com/a/7220/43835
mc0e

1
混乱と戦うためだけに:OPのフォーマットは、紹介してOPのフォーマットがになるまではありません 。関連するxkcd:xkcd.com/1179%Y-%m-%dAugust 2.0October 2.0%Y-%d-%m
紙吹雪

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」/切り捨て操作を実行し、整数のみを返すためです。説明させてください:

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) ))、6を返すのではなく、5
ハンク・シュルツ

1
ああ、回答者の1人は、他の人がバリアントで繰り返した基本的な解決策の不正確さについて考えました。いいぞ!うるう秒はどうですか?うるう秒で安全ですか?うるう秒に関連する問題を参照して、特定の時間に実行された場合に1ごとの結果を返すソフトウェアの前例があります。
ステフェイン・グーリッホン

うわー、あなたが例として与える「間違った」計算はここで正しく6を返します(Ubuntu 15.04 AMD64、GNU日付バージョン8.23)。おそらくあなたの例はタイムゾーンに依存していますか?私のタイムゾーンは「ヨーロッパ/パリ」です。
ステフェイン・グーリッホン

同じタイムゾーンのMSYSでGNU日付2.0を使用した「間違った」計算でも同じ良い結果が得られます。
ステフェイン・グーリッホン

1
@StéphaneGourichon、タ​​イムゾーンの夏時間の変更は2015年3月29日に行われたようです。そのため、それを含む日付範囲を試してください。
evan_b 2015

21

そしてPythonで

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

2
@mouvicielはそうではありません。Pythonは常に存在するとは限りません。
mc0e 2015年

1
その文脈では@ mc0e、常に何も存在しません
Sumudu

5
@Anubis OPはタグをbashととして指定しているshellので、* nixシステムについて話していると推測できます。そのようなシステム内で、echoそしてdate確実に存在しますが、pythonは存在しません。
mc0e

2
@ mc0eええそれは理にかなっています。たとえpython2はほとんどの* nixシステムで利用可能ですが、ローエンドデバイス(組み込みなど)に関しては、主要なツールでのみ生き残る必要があります。
スムドゥ

13

これは私のために働きます:

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. 1日あたりの秒数(86400 = 60 * 60 * 24)で除算して、日数として差を求めます
  6. DSTは考慮されません!unix.stackexchangeでこの回答を参照してください!

7

オプション-dがシステムで機能する場合は、別の方法があります。年間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

これがあなたの便宜のためのMACOSXバージョンです。

$ 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 2016年

1
@ cavalcade-それはあなたがしていないからですA="2002-20-10"; B="2003-22-11"
RAM237 2017

おかげで、この特定のケースでは機能しますが、を使用することをお勧めしますecho $(((`date -jf "%Y-%d-%m" "$B" +%s` - `date -jf "%Y-%d-%m" "$A" +%s`)/86400))。つまり、形式と変数の両方を二重引用符で囲みます。そうしないと、異なる日付形式(例%b %d, %Y/ Jul 5, 2017)で失敗する可能性があります
RAM237 2017

@ RAM237それは私がヘッドスマックに注意を払わなかったために得たものですよく発見されました、ありがとう
cavalcade 2018年

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

これは私がcentos7で作業することができた最も簡単なものです:

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

基本的に、strftimereverse(-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 2012年

2
シェル自体でそれを行うポータブルな方法はありません。すべての選択肢は特定の外部プログラム(つまり、GNUdateまたはいくつかのスクリプト言語)を使用しており、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

UNIXでは、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

OracleDBバックアップを3次ディスクに手動でrsyncするとします。次に、そのディスク上の古いバックアップを削除します。だからここに小さな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

ニーズに合わせて、dirと保持期間(「30日」)を変更します。


Oracleは、「YYYY_MM_DD」のような形式を使用してバックアップセットをフラッシュリカバリ領域に配置するため、「date -d」に渡すためのアンダースコアを削除します
Alex

0

MacOS sierra(おそらくMac OS X yosemateから)の場合、

ファイルからエポックタイム(1970年からの秒数)を取得し、それをvarに保存するには: old_dt=`date -j -r YOUR_FILE "+%s"`

現在の時間のエポック時間を取得するには new_dt=`date -j "+%s"`

上記の2つのエポック時間の差を計算するには (( diff = new_dt - old_dt ))

差分が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.