日付の差をすばやく計算する


84

私はしばしば、次のようないくつかの簡単な日付計算を行いたいです。

  • これら2つの日付の違いは何ですか?
  • 日付は何であるnは、この他の日付以降週間?

私は通常、カレンダーを開いて日数を数えますが、これらの種類の計算を行うために使用できるプログラム/スクリプトがあるはずです。助言がありますか?


3
GNU日付が利用できない場合の日付を減算するUNIXのツールも参照してください。
ジル

回答:


107

「日付後のn週間」はGNU date(1)で簡単です:

$ date -d 'now + 3 weeks'
Tue Dec  6 23:58:04 EST 2011
$ date -d 'Aug 4 + 3 weeks'
Thu Aug 25 00:00:00 EST 2011
$ date -d 'Jan 1 1982 + 11 weeks'
Fri Mar 19 00:00:00 EST 1982

2つの日付の差を計算する簡単な方法は知りませんが、シェル関数を使用してdate(1)の周りに小さなロジックをラップできます。

datediff() {
    d1=$(date -d "$1" +%s)
    d2=$(date -d "$2" +%s)
    echo $(( (d1 - d2) / 86400 )) days
}
$ datediff '1 Nov' '1 Aug'
91 days

スワップd1d2、日付の計算を別の方法で行いたい場合、またはそれを問題にしないように少し手の込んだ方法を取得します。さらに、間隔に非DSTからDSTへの移行がある場合、日のうちの1 つはわずか 23時間です。合計に½日を追加することで補償できます。

echo $(( (((d1-d2) > 0 ? (d1-d2) : (d2-d1)) + 43200) / 86400 )) days

41

ポータブルツールのセットについては、独自のdateutilsを試してください。あなたの2つの例は、ワンライナーに要約されます:

ddiff 2011-11-15 2012-04-11
=>
  148

または数週間と数日で:

ddiff 2011-11-15 2012-04-11 -f '%w %d'
=>
  21 1

そして

dadd 2011-11-15 21w
=>
  2012-04-10

3
ツールを+1します(dateadd -i '%m%d%Y' 01012015 +1d動作しないように見えますが、無期限に停止します...日付の仕様が文字で区切られている場合は動作します...何か問題がありますか?)
don_crissti

2
@don_crisstiパーサーは数字のみの日付と期間を区別できませんでした。現在のマスター(d0008f98)で修正されました
hroptatyr

あなたはdateutilsのウィンドウのバイナリ配布を持っていますか?
モッシュ

@moshいいえ、私は試してみる施設がありません。
hroptatyr

ここではパーティーに遅れていますが、Windowsで使用する必要がある場合、dateutilsはcygwinにあります。
gregb212

30

私が惑星を歩いた日数を計算するためのpythonの例:

$ python
>>> from datetime import date as D
>>> print (D.today() - D(1980, 6, 14)).days
11476

2
インタラクティブなインタープリターを入力する代わりに、誰かがこれを単一のコマンドのように動作させたい場合に備えて: ychaouche@ychaouche-PC ~ $ python -c "from datetime import date as d; print (d.today() - d(1980, 6, 14)).days" 12813 ychaouche@ychaouche-PC ~ $
ychaouche

1
これは、 "dと日時輸入日から、プリント(d.today() - D(2016、1、9))"のpython3 -c私の作品最後の日が必要とされていません
キランK Telukunta

13

私は通常、unix utime形式(70年代が始まったエポックからの秒数、UTC)で時刻/日付を持つことを好みます。そのように、それは常に秒の単純な減算または加算に要約されます。

通常、日付/時刻をこの形式に変換する問題になります。

シェル環境/スクリプトでは、これを取得できます。date '+%s' 執筆時点では、現在の時刻は1321358027です。

2011-11-04(私の誕生日)と比較するにはdate '+%s' -d 2011-11-04、を生成し1320361200ます。減算:秒expr 1321358027 - 1320361200を与えます。996827これはexpr 996827 / 86400= 11日前です。

utime(1320361200形式)から日付への変換は、標準ライブラリを使用して、たとえばC、PHP、またはperlで非常に簡単に実行できます。GNUを使用するdateと、「エポックからの秒数」形式を示すために-d引数を前に付けることができ@ます。


7
GNU日付でdate -d @1234567890は、エポックからの秒数を指定した日付形式に変換します。
ジル

1
@Gilles:それは素晴らしい。マンページでそれを見つけることができませんでした。どこでそれを学びましたか?
マット・ビアンコ

1
@MattBiancoは、参照info date、特にエポックからの秒ノードを:「あなたは`@」で番号の前にした場合、それは秒数として内部タイムスタンプを表している。」
manatwork

8

グラフィカルツールで問題なければ、私は心からお勧めしますqalculate(単位変換に重点を置いた計算機、GTKおよびKDEインターフェイス、IIRCが付属しています)。そこにあなたは言うことができます

days(1900-05-21, 1900-01-01)

日付間の日数(1900はle年ではないので140)を取得しますが、もちろん時間についても同じことができます:

17:12:45 − 08:45:12

利回り8.4591667時間のか、あなたは、フォーマット時に出力を設定している場合、8:27:33


3
qalculateに CLIがあるため、さらに素晴らしいことです。試してみてくださいqalc、その後、help days
Sparhawk

qcalc例:qalc -t 'days(1900-05-21, 1900-01-01)'-> 140
sierrasdetandil

8

これはdate -d "$death_date - $y years - $m months - $d days"、出生日を取得するために使用するときに発生しました(系図用)。そのコマンドは間違っています。月はすべて同じ長さではありません(date + offset) - offset != date。年齢は、年/月/日で、生年月日から先に進む指標です。

$ date --utc -d 'mar 28 1867 +72years +11months +2days'
Fri Mar  1 00:00:00 UTC 1940

$ date --utc -d 'mar 1 1940 -72years -11months -2days'
Sat Mar 30 00:00:00 UTC 1867
# (2 days later than our starting point)

日付はどちらの場合も正しい出力を提供しますが、2番目の場合は間違った質問をしていました。それは、日を追加/減算する前に、年の11か月間、+ /-11がカバーする重要なものです。例えば:

$ date --utc -d 'mar 31 1939  -1month'
Fri Mar  3 00:00:00 UTC 1939
$ date --utc -d 'mar 31 1940  -1month' # leap year
Sat Mar  2 00:00:00 UTC 1940
$ date --utc -d 'jan 31 1940  +1month' # leap year
Sat Mar  2 00:00:00 UTC 1940

減算を加算の逆演算にするには、演算の順序を逆にする必要があります。追加すると、年、次に月、次に日が追加されます。減算が逆の順序を使用した場合、開始点に戻ります。日付オフセットが異なる長さの月の月の境界を超える場合は、そうではありません。

終了日と年齢からさかのぼって作業する必要がある場合は、の複数の呼び出しで実行できますdate。最初に日、次に月、次に年を減算します。(dateうるう年が2月の長さを変えるため、1回の呼び出しで年と月を組み合わせるのは安全ではないと思います。)


3

日付の計算にはSQLを頻繁に使用します。たとえば、MySQLPostgreSQL、またはSQLite

bash-4.2$ mysql <<< "select datediff(current_date,'1980-06-14')"
datediff(current_date,'1980-06-14')
11477

bash-4.2$ psql <<< "select current_date-'1980-06-14'"
 ?column? 
----------
    11477
(1 row)

bash-4.2$ sqlite2 <<< "select julianday('now')-julianday('1980-06-14');"
11477.3524537035

また、JavaScriptのムードを感じることもあります。たとえば、SpiderMonkeyWebKitSeedまたはNode.js

bash-4.2$ js -e 'print((new Date()-new Date(1980,5,14))/1000/60/60/24)'
11477.477526192131

bash-4.2$ jsc-1 -e 'print((new Date()-new Date(1980,5,14))/1000/60/60/24)'
11477.47757960648

bash-4.2$ seed -e '(new Date()-new Date(1980,5,14))/1000/60/60/24'
11477.4776318287

bash-4.2$ node -pe '(new Date()-new Date(1980,5,14))/1000/60/60/24'
11624.520061481482

(月をJavaScript Dateオブジェクトのコンストラクターに渡すときは注意してください。0で始まります。)


3

同じ暦年の2つの日付の差を計算する別の方法として、これを使用できます。

date_difference.sh
1  #!/bin/bash
2  DATEfirstnum=`date -d "2014/5/14" +"%j"`
3  DATElastnum=`date -d "12/31/14" +"%j"`
4  DAYSdif=$(($DATElastnum - $DATEfirstnum))
5  echo "$DAYSdif"
  • 1行目は、使用するインタープリターをシェルに宣言します。
  • 行2 dateは、変数DATEfirstnumにoutからの値を割り当てます。-dフラグは、この場合は5月14日2014年にタイム形式の文字列を表示し、+"%j"伝えdate年(1〜365)のちょうどその日に出力をフォーマットします。
  • 行3は行2と同じですが、文字列の日付と形式が異なります(2014年12月31日)。
  • 行4 DAYSdifは、2日間の差に値を割り当てます。
  • 行5は、の値を表示しますDAYSdif

これはGNUバージョンdateので動作しますが、PC-BSD / FreeBSDバージョンでは動作しません。coreutilsポートツリーからインストールし、/usr/local/bin/gdate代わりにコマンドを使用しました。


1
このスクリプトは実行されません。最後の行にタイプミスがあり、変数の割り当ての前後にスペースがあるため、bashは2つの引数を持つDATEfirst nameというプログラムを実行しようとしています。これを試してください: DATEfirstnum=$(date -d "$1" +%s) DATElastnum=$(date -d "$2" +%s) また、このスクリプトは2つの異なる年の間の差を計算できません。+%j年の日(001..366)を参照するため、./date_difference.sh 12/31/2001 12/30/2014-1を出力します。他の回答では、両方の日付を1970-01-01 00:00:00 UTC以降の秒に変換する必要があると指摘されています。
6

$内部の算術式は必要ありません:$((DATElastnum - DATEfirstnum))動作します。
ルスラン

3

dannasソリューションの助けを借りて、次のコードを使用してこれを1行で実行できます。

python -c "from datetime import date as d; print(d.today() - d(2016, 7, 26))"

(Python 2.xとPython 3の両方で動作します。)


1
あなたはあなたのポストの代わりに、コメントを編集することができます
スティーブン・ラウフ

3

dateまた、bashは日付の違いを行うことができます(OS Xオプションが表示されます)。後者の日付を最初に配置してください。

echo $((($(date -jf%D "04/03/16" +%s) - $(date -jf%D "03/02/16" +%s)) / 86400))
# 31

1

また、GNU日付と組み合わされたGNUユニットの時間計算もあります。

$ gunits $(gdate +%s)sec-$(gdate +%s -d -1234day)sec 'yr;mo;d;hr;min;s'
        3 yr + 4 mo + 16 d + 12 hr + 37 min + 26.751072 s
$ gunits $(gdate +%s -d '2015-1-2 3:45:00')sec-$(gdate +%s -d '2013-5-6 7:43:21')sec 'yr;mo;d;hr;min;s'
        1 yr + 7 mo + 27 d + 13 hr + 49 min + 26.206759 s

(gunitsはLinuxの単位、gdateは日付)


1

github:gistのdatediff.sh

#!/bin/bash
#Simplest calculator two dates difference. By default in days

# Usage:
# ./datediff.sh first_date second_date [-(s|m|h|d) | --(seconds|minutes|hours|days)]

first_date=$(date -d "$1" "+%s")
second_date=$(date -d "$2" "+%s")

case "$3" in
"--seconds" | "-s") period=1;;
"--minutes" | "-m") period=60;;
"--hours" | "-h") period=$((60*60));;
"--days" | "-d" | "") period=$((60*60*24));;
esac

datediff=$(( ($first_date - $second_date)/($period) ))
echo $datediff

1

camhの答えがその大部分を処理しますが、丸め、タイムゾーンなどに対処するように改善できます。さらに、精度を高め、ユニットを選択する機能を取得できます。

datediff() {
#convert dates to decimal seconds since 1970-01-01 00:00:00 UTC
date1seconds=$(date +%s.%N -d "$date1")
date2seconds=$(date +%s.%N -d "$date2")

#Calculate time difference in various time units
timeseconds=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)"))
timeminutes=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/60"))
  timehours=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/3600"))
   timedays=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/86400"))
  timeweeks=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/604800"))
}

-ddate変換する日時を指定していることを伝えます。 +%s.%NUTCの1970-01-01 00:00:00からdate.timeをseconds.nanosecondsに変更します。 bc2つの数値の差を計算し、除算係数により異なる単位を取得します。 printf必要に応じて小数点の前に0を追加し(必要でbcはない)、丸めが最も近いことを確認します(bc切り捨てます)。を使用することもできますawk

ファンキーなテストケースでこれを実行してみましょう。

date1='Tue Jul  9 10:18:04.031 PST 2020'
date2='Wed May  8 15:19:34.447 CDT 2019'
datediff "$date1" "$date2"

echo $timeseconds seconds
-36971909.584000000 seconds

echo $timeminutes minutes
-616198.493066667 minutes

echo $timehours hours
-10269.974884444 hours

echo $timedays days
-427.915620185 days

echo $timeweeks weeks
-61.130802884 weeks

月または年の長さが常に同じではないため、ここでは単一の「正しい」答えはありませんが、最近では365.24日を合理的な近似として使用できます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.