読者です 読者をやめる 読者になる 読者になる

ひよっこPGのブログ

主に、技術メモや英語たまにギター関連のことも書いているブログです。

Javaで 日付の差 差分日数を取得する際に間違えたこと

Java

日付関連のユーティリティクラスとして DateUtilsクラスを作っている時に書いたメモです。

まず初めにソースを貼ります。

import java.util.Calendar;
import java.util.Date;

public class Test {
	public static void main(String args[]){
		Calendar cal1 = Calendar.getInstance();
		cal1.set(2014, 0, 1);
		Date dateFrom = cal1.getTime();
		Calendar cal2 = Calendar.getInstance();
		cal2.set(2014, 0, 2);
		Date dateTo   = cal2.getTime();
		int result = diffDays(dateFrom, dateTo);
		System.out.println(result);
	}
	/**
	* 日付の差分日数を取得.
	*
	* 参考: http://javatechnology.net/java/date-diff-days/
	*     : http://sattontanabe.blog86.fc2.com/blog-entry-88.html
	* @param dateFrom 開始日付
	* @param dateTo   終了日付
	* @return int 差分日数
	*/
	public static int diffDays(Date dateFrom, Date dateTo){
		// 日付をlong値に変換
		long dateTimeFrom = dateFrom.getTime();
		long dateTimeTo   = dateTo.getTime();

		// 差分の日数を計算
		final int DAY_MILLISECONDS = (1000 * 60 * 60 * 24 );
		int diff = (int)( dateTimeTo - dateTimeFrom );
		int dayDiff = diff / DAY_MILLISECONDS;

		return dayDiff;
	}
}

f:id:buzzword111:20140430104042p:plain
WEB上でコンパイル出来る ideoneでの実行画面

ソースを見ていただけるとわかると思うのですが
2014年1月1日と2014年1月2日の差分日数を求めています。

ですが、差分日数が30日になるよう下記に変更してテストしたところ・・・。

Calendar cal2 = Calendar.getInstance();
cal2.set(2014, 0, 31);

f:id:buzzword111:20140430104658p:plain

なぜマイナス!!!

いろいろ調べたところ原因は

int diff = (int)( dateTimeTo - dateTimeFrom );

この部分でした。

Date型から.getTime()して取得できる値は
1970年1月1日午前0時(GMT)から現在までの経過秒数なので
2014年1月1日の場合は : 138,854,114,035秒になります。

ここで自分が忘れていたことは int型の最大値・・・。
参考 : Java の Short, Integer, Long, Float, Double 型の最大値 / 最小値 & それぞれの値を漢数字表記すると - #侍ズム
int型の最大値は : 2,147,483,647

1日の秒数は 86,400,000。これはプログラム中にfinal int DAY_MILLISECONDSとして定義しています。
ということは、int型が扱える日数は
2,147,483,647 / 86,400,000 = 24.85513..... = 24日

原因だった (int)(dateTimeTo - dateTimeFrom)は
差分日数を秒数で計算しているので
1日~24日までは計算できるが 25日以上になるとオーバーフローしてしまいエラーになってしまう。

理由が分かったので、解決方法を書くと
型を int⇒longに変更するだけでOK。
int型の最大値: 2,147,483,647
long型の最大値: 9,223,372,036,854,775,807
なのでlong型だと安心出来ますね。
long型で許容できる日数を計算すると
約292471208年分ほど格納できるみたいです。