Javaで日時を扱う（Java7まで）

Java8では、日時を扱うクラス群が様変わりしてしまいました。これを機に、日時の扱いをまとめてみたいと思います。今回は、Java7までの日時、[次回](http://qiita.com/kurukurupapa@github/items/f55395758eba03d749c9)は、Java8での日時を書きたいと思います。

Java7までは、主に、Dateクラス、Calendarクラスを使いますね。Apache Commons LangのDateUtils、DateFormatUtilsも使えると便利。

Apache Commons Lang について

* https://commons.apache.org/proper/commons-lang/
* バージョン3.2では、Java6以上が必要。
* バージョン3.0では、Java5以上が必要。
* バージョン2.xは、Java1.4で使用可能。 

# 現在/指定日時の作成
Dateクラスの現在/指定日時を作成する。

```java
// 現在日時
Date nowDate1 = new Date();
// 文字列→Date
DateFormat dateTimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date1 = dateTimeFormat.parse("2016/5/2 15:00:00");
// 文字列→Date（Apache Commons Lang）
// ※Java5から、書式引数を可変長引数として記述できるようになった。
Date date1b = DateUtils.parseDate("2016/5/2 15:00:00", "yyyy/MM/dd HH:mm:ss");
Date date1c = DateUtils.parseDate("2016-5-2 15:00:00", "yyyy/MM/dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss");
// Calendar→Date
Date date2 = new GregorianCalendar(2016, 5 - 1, 2, 15, 0, 0).getTime();
// long→Date
Date date3 = new Date(System.currentTimeMillis());
```

Calendarクラスの現在/指定日時を作成する。

```java
// 現在日時
Calendar nowCal1 = Calendar.getInstance();
// 指定日時
Calendar cal1 = new GregorianCalendar(2016, 5 - 1, 2, 15, 0, 0);
// Date→Calendar
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date1);
// Date→Calendar（Apache Commons Lang）
Calendar cal2b = DateUtils.toCalendar(date1);
// long→Calendar
Calendar cal3 = Calendar.getInstance();
cal3.setTimeInMillis(System.currentTimeMillis());
```

long型（ミリ秒）の現在/指定日時を作成する。

```java
// 現在日時
long nowMsec1 = System.currentTimeMillis();
// 指定日時
long msec1 = System.currentTimeMillis() - 24 * 60 * 60 * 1000;
// Date→long
long msec2 = date1.getTime();
// Calendar→long
long msec3 = cal1.getTimeInMillis();
```

文字列の現在/指定日時を作成する。

```java
// Date→文字列
DateFormat timestampFormat1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
String str1 = timestampFormat1.format(date1);
// Date→文字列（Apache Commons Lang）
String str1b = DateFormatUtils.format(date1, "yyyy/MM/dd HH:mm:ss.SSS");
// Calendar→文字列
String str2 = format.format(cal1.getTime());
// long→文字列
String str3 = format.format(new Date(msec1));
```

# 日時から日付の取り出し

```java
// Date 日時→日付（時刻ゼロ）
Calendar tmpCal1 = Calendar.getInstance();
tmpCal1.setTime(date1);
Calendar tmpCal2 = new GregorianCalendar(tmpCal1.get(Calendar.YEAR), tmpCal1.get(Calendar.MONTH),
		tmpCal1.get(Calendar.DATE));
Date ymdDate1 = tmpCal2.getTime();

// Calendar 日時→日付（時刻ゼロ）
Calendar ymdCal1 = new GregorianCalendar(cal1.get(Calendar.YEAR), cal1.get(Calendar.MONTH),
		cal1.get(Calendar.DATE));

// Date 日時→日付（時刻ゼロ）（Apache Commons Lang）
Date ymdDate2 = DateUtils.truncate(date1, Calendar.DATE);
// Calendar 日時→日付（時刻ゼロ）（Apache Commons Lang）
Calendar ymdCal2 = DateUtils.truncate(cal1, Calendar.DATE);

// 上記以外に、書式"yyyy/MM/dd"のフォーマットで文字列として取得することも可能。
```

# 日時から時刻の取り出し

```java
// 時刻のみを取り出すことは出来ない模様。
// 必要なら、書式"HH:mm:ss"のフォーマットで文字列として取得する（？）
```

# 曜日の取得

```java
// Dateから曜日取得
// ※ロケールによって曜日の表記が変わる。
DateFormat weekFormat1 = new SimpleDateFormat("E", Locale.JAPANESE);
DateFormat weekFormat2 = new SimpleDateFormat("EEEE", Locale.JAPANESE);
String weekStr1 = weekFormat1.format(date1);
String weekStr2 = weekFormat2.format(date1);

// Calendarから曜日取得
int weekInt1 = cal1.get(Calendar.DAY_OF_WEEK);
String[] weekNames = new String[] { "日", "月", "火", "水", "木", "金", "土" };
String weekStr3 = weekNames[weekInt1 - 1];

// Java6では、Calendar.getDisplayNameメソッドが使える。
String weekStr4 = cal1.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, Locale.JAPANESE);
String weekStr5 = cal1.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.JAPANESE);

// Dateから曜日取得（Apache Commons Lang）
// ※ロケールによって曜日の表記が変わる。
String weekStr6 = DateFormatUtils.format(date1, "E", Locale.JAPANESE);
String weekStr7 = DateFormatUtils.format(date1, "EEEE", Locale.JAPANESE);
// Calendarから曜日取得（Apache Commons Lang）
// ※ロケールによって曜日の表記が変わる。
String weekStr8 = DateFormatUtils.format(cal1, "E", Locale.JAPANESE);
String weekStr9 = DateFormatUtils.format(cal1, "EEEE", Locale.JAPANESE);
```

# 日時計算
加算/減算

```java
// Date 1秒後、1日後
// ※Java5では、TimeUnitが使えるようになった。
Date nextSecDate = new Date(msec1 + TimeUnit.SECONDS.toMillis(1));
Date nextDayDate = new Date(msec1 + TimeUnit.DAYS.toMillis(1));

// Calendar 1秒後、1日後、１ヶ月後
Calendar nextSecCal = (Calendar) cal1.clone();
nextSecCal.add(Calendar.SECOND, 1);
Calendar nextDayCal = (Calendar) cal1.clone();
nextDayCal.add(Calendar.DATE, 1);
Calendar nextMonthCal = (Calendar) cal1.clone();
nextMonthCal.add(Calendar.MONTH, 1);

// Date 1秒後、1日後（Apache Commons Lang）
Date nextSecDate2 = DateUtils.addSeconds(date1, 1);
Date nextDayDate2 = DateUtils.addDays(date1, 1);
Date nextMonthDate2 = DateUtils.addMonths(date1, 1);
```

月初/月末を求める。

```java
// Calendar 月初、月末
Calendar monthBeginning = (Calendar) cal1.clone();
monthBeginning.set(Calendar.DATE, 1);
Calendar monthEnd = (Calendar) cal1.clone();
monthEnd.set(Calendar.DATE, cal1.getActualMaximum(Calendar.DATE));
```

差を求める。

```java
// Date 日時の差 ミリ秒単位、日数単位（切り捨て）
// ※日付の差がほしいときは、日時→日付のみに変換して、上記を計算する。
long dateDiffMsec = nextDayDate.getTime() - date1.getTime();
long dateDiffDays = (nextDayDate.getTime() - date1.getTime()) / TimeUnit.DAYS.toMillis(1);
// Calendar 日時の差 ミリ秒単位、日数単位（切り捨て）
// ※日付の差がほしいときは、日時→日付のみに変換して、上記を計算する。
long calDiffMsec = nextDayCal.getTimeInMillis() - cal1.getTimeInMillis();
long calDiffDays = (nextDayCal.getTimeInMillis() - cal1.getTimeInMillis()) / TimeUnit.DAYS.toMillis(1);

// Date 日付の差（Apache Commons Lang）
long dateDiffDays2 = (DateUtils.truncate(nextDayDate, Calendar.DATE).getTime()
	- DateUtils.truncate(date1, Calendar.DATE).getTime()) / TimeUnit.DAYS.toMillis(1);
// Calendar 日付の差（Apache Commons Lang）
long calDiffDays2 = (DateUtils.truncate(nextDayCal, Calendar.DATE).getTimeInMillis()
	- DateUtils.truncate(cal1, Calendar.DATE).getTimeInMillis()) / TimeUnit.DAYS.toMillis(1);
```

比較する。

```java
// Dateの前後比較
boolean dateBeforeFlag = date1.before(nextDayDate);
boolean dateAfterFlag = nextDayDate.after(date1);
// Calendarの前後比較
boolean calBeforeFlag = cal1.before(nextDayCal);
boolean calAfterFlag = nextDayCal.after(cal1);

// Date 日付一致確認（Apache Commons Lang）
// ※時刻は無視して、日付のみ比較される。
boolean dateSameFlag = DateUtils.isSameDay(date1, nextSecDate);
// Calendar 日付一致確認（Apache Commons Lang）
// ※時刻は無視して、日付のみ比較される。
boolean calSameFlag = DateUtils.isSameDay(cal1, nextSecCal);
```

# おまけ：スリープ
Java5のTimeUnitを使うと、好きな時間単位でスリープ時間を書きやすい。

```java
TimeUnit.SECONDS.sleep(1);
```

# 参考

* Java日付処理メモ(Hishidama's Java Date Memo) http://www.ne.jp/asahi/hishidama/home/tech/java/date.html
* 日時に関する情報を取得する(get) - Calendarクラス http://www.javadrive.jp/start/calendar/index2.html