Joda-Timeを使った日付処理まとめ

# 概要

Joda-Timeを使った日付処理のまとめです。
(なおJava8であればTime APIがあるのでJoda-Timeを使用する必要はありません)

**環境**

下記の環境で動作確認を行いました。

* Windows7 (64bit)
* Java 1.8.0_45
* [Joda-Time] (http://www.joda.org/joda-time/) 2.8.1

**参考**

下記のサイトを参考にさせて頂きました。

Joda

* [Joda-Time 2.8.1 API] (http://www.joda.org/joda-time/apidocs/overview-summary.html)

blog

* [Javaで面倒くさい日付の扱いを簡単にするライブラリ「Joda-Time」 期間編] (http://shinsuke789.hatenablog.jp/entry/2013/08/06/195436)

Stack Overflow

* [PeriodFormatter not showing days] (http://stackoverflow.com/questions/26291271/periodformatter-not-showing-days)

その他

* [Joda-Time - IBM developerWorks 日本語版] (http://www.ibm.com/developerworks/jp/java/library/j-jodatime.html)
* [JSR 310 JavaのDate/Time API - InfoQ] (http://www.infoq.com/jp/news/2010/03/jsr-310)
* [Java 8 Date/Time API Tutorial - Examples Java Code Geeks] (http://examples.javacodegeeks.com/core-java/java-8-datetime-api-tutorial/)


## DateTimeを使った日付処理

`DateTime`はUTCからのオフセットやタイムゾーンを持つ日時を表すクラスです。似た名前の`LocalDateTime`はUTCからのオフセットやタイムゾーンを持ちません。


**サンプルコードの日付フォーマットについて**

以降のサンプルコードで使用する日付フォーマットは下記の通りです。とくに断りが無い場合は日付をこのフォーマットで文字列にします。

```java:datetime_formatter
DateTimeFormatter DEF_FMT = DateTimeFormat.forPattern("G yyyy-MM-dd(E) aHH:mm:ss.SSS ZZ.");
```

これも以降のサンプルコードで使用する期間用フォーマットです。

```java:Period_formatter
PeriodFormatter PERIOD_FMT = new PeriodFormatterBuilder()
  .printZeroAlways()
  .appendYears().appendSuffix(" year ", " years ")
  .appendMonths().appendSuffix(" month ", " months ")
  .appendWeeks().appendSuffix(" week ", " weeks ")
  .appendDays().appendSuffix(" day ", " days ")
  .appendHours().appendSuffix(" hour ", " hours ")
  .appendMinutes().appendSuffix(" minutes ")
  .appendSeconds().appendSuffix(" seconds ")
  .toFormatter();
```

### インスタンスの生成

#### コンストラクタ

```java:constructor
DateTime dt1 = new DateTime();
System.out.println(DEF_FMT.print(dt1));
// ⇒ 西暦 2015-07-08(水) 午後21:52:23.897 +09:00.
```

```java:constructor
DateTime dt2 = new DateTime(2006, 1, 2, 15, 4);
DateTime dt3 = new DateTime(2006, 1, 2, 15, 4, 5);
DateTime dt4 = new DateTime(2006, 1, 2, 15, 4, 5, 666);

System.out.println(DEF_FMT.print(dt2));
// ⇒ 西暦 2006-01-02(月) 午後15:04:00.000 +09:00.
System.out.println(DEF_FMT.print(dt3));
// ⇒ 西暦 2006-01-02(月) 午後15:04:05.000 +09:00.
System.out.println(DEF_FMT.print(dt4));
// ⇒ 西暦 2006-01-02(月) 午後15:04:05.666 +09:00.
```

#### now()

現在日時を持つ`DateTime`インスタンスを生成します。

```java:now
DateTime dt5 = DateTime.now();
System.out.println(DEF_FMT.print(dt5));
// ⇒ 西暦 2015-07-08(水) 午後21:52:23.858 +09:00.
```

#### parse()

日付を表現する文字列を解析して`DateTime`インスタンスを生成します。

```java:parse
DateTime pd1 = DateTime.parse("2006-01-02");
System.out.println(DEF_FMT.print(pd1));
// ⇒ 西暦 2006-01-02(月) 午前00:00:00.000 +09:00.
```

```java:parse
DateTime pd2 = DateTime.parse("2006-01-02T15:04:05");
System.out.println(DEF_FMT.print(pd2));
// ⇒ 西暦 2006-01-02(月) 午後15:04:05.000 +09:00.
```

```java:parse
DateTime pd3 = DateTime.parse("20060102 150405", DateTimeFormat.forPattern("yyyyMMdd HHmmss"));
System.out.println(DEF_FMT.print(pd3));
// ⇒ 西暦 2006-01-02(月) 午後15:04:05.000 +09:00.
```

#### タイムゾーンを指定

`DateTime`インスタンス生成時に任意のタイムゾーンを指定することができます。
指定しない場合はデフォルトのタイムゾーンが使用されます。

```java:timezone
DateTimeZone tokyo = DateTimeZone.forID("Asia/Tokyo");
DateTime dt6 = new DateTime(tokyo);
System.out.println(DEF_FMT.print(dt6));
// ⇒ 西暦 2015-07-08(水) 午後21:52:23.909 +09:00.
```

```java:timezone
DateTimeZone nyc = DateTimeZone.forID("America/New_York");
DateTime dt7 = new DateTime(nyc);
System.out.println(DEF_FMT.print(dt7));
// ⇒ 西暦 2015-07-08(水) 午前08:52:23.911 -04:00.
```

**デフォルトのタイムゾーン**

```java:timezone
DateTime dt1 = DateTime.now();
DateTimeZone defaultZone = dt1.getZone();
System.out.println(defaultZone);
// ⇒ Asia/Tokyo
```

#### 暦

`DateTime`インスタンス生成時に任意の暦を指定することができます。

```java:chronology
Chronology gregorian = GregorianChronology.getInstance();
DateTime dt8 = new DateTime(gregorian);
System.out.println(DEF_FMT.print(dt8));
// ⇒ 西暦 2015-07-08(水) 午後21:52:23.912 +09:00.
```

**デフォルトの暦**

```java:chronology
DateTime dt1 = DateTime.now();
Chronology defaultChrono = dt1.getChronology();
System.out.println(defaultChrono);
// ⇒ ISOChronology[Asia/Tokyo]
```

### フォーマット

`DateTime`インスタンスを指定した書式の文字列にフォーマットします。

#### 事前定義フォーマット

`DateTimeFormat`クラスには事前定義されたフォーマットがあります。

```java:DateTimeFormat
DateTime dt1 = DateTime.now();

DateTimeFormatter fullFmt = DateTimeFormat.fullDateTime()
DateTimeFormatter longFmt = DateTimeFormat.longDateTime()
DateTimeFormatter mediumFmt = DateTimeFormat.mediumDateTime()
DateTimeFormatter shortFmt = DateTimeFormat.shortDateTime()

System.out.println(fullFmt.print(dt1));
// ⇒ 2015年7月8日 21時52分23秒 JST
System.out.println(longFmt.print(dt1));
// ⇒ 2015/07/08 21:52:23 JST
System.out.println(mediumFmt.print(dt1));
// ⇒ 2015/07/08 21:52:23
System.out.println(shortFmt.print(dt1));
// ⇒ 15/07/08 21:52
```

#### フォーマットのカスタマイズ

カスタマイズした書式でフォーマットすることができます。
カスタマイズの方法は`forPattern()`,`forStyle`でパターンを指定する方法と`DateTimeFormatterBuilder`を使用する方法があります。

```java:forPattern
DateTime dt1 = DateTime.now();

System.out.println(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").print(dt1));
// ⇒ 2015-07-08 21:52:23
System.out.println(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS").print(dt1));
// ⇒ 2015-07-08 21:52:23.924
System.out.println(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSSZ").print(dt1));
// ⇒ 2015-07-08 21:52:23.924+0900
System.out.println(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSSZZ").print(dt1));
// ⇒ 2015-07-08 21:52:23.924+09:00
System.out.println(DateTimeFormat.forPattern("G yyyy-MM-dd(E) aHH:mm:ss.SSS ZZ.").print(dt1));
// ⇒ 西暦 2015-07-08(水) 午後21:52:23.924 +09:00.
```

`forStyle`は2文字でパターンを指定します。パターンに使用できる文字は「`F`=Full、`L`=Long、`M`=Medium、`S`=Short、`-`=非表示」です。
1文字目に日付、2文字目に時刻のパターンを指定します。

```java:forStyle
DateTime dt1 = DateTime.now();

System.out.println(DateTimeFormat.forStyle("FF").print(dt1));
// ⇒ 2015年7月8日 21時52分23秒 JST
System.out.println(DateTimeFormat.forStyle("LL").print(dt1));
// ⇒ 2015/07/08 21:52:23 JST
System.out.println(DateTimeFormat.forStyle("MM").print(dt1));
// ⇒ 2015/07/08 21:52:23
System.out.println(DateTimeFormat.forStyle("SS").print(dt1));
// ⇒ 15/07/08 21:52

System.out.println(DateTimeFormat.forStyle("LS").print(dt1));
// ⇒ 2015/07/08 21:52
System.out.println(DateTimeFormat.forStyle("L-").print(dt1));
// ⇒ 2015/07/08
```

`DateTimeFormatterBuilder`を使用してフォーマットを組み立てることができます。

```java:DateTimeFormatterBuilder
DateTime dt1 = DateTime.now();

DateTimeFormatter buildFmt = new DateTimeFormatterBuilder()
  .appendEraText()
  .appendLiteral(" ")
  .appendYear(4, 4)
  .appendLiteral("年")
  .appendMonthOfYear(2)
  .appendLiteral("月")
  .appendDayOfMonth(2)
  .appendLiteral("日")
  .appendLiteral(" ")
  .appendDayOfWeekText()
  .appendLiteral(" ")
  .toFormatter();

System.out.println(buildFmt.print(dt1));
// ⇒ 西暦 2015年07月08日 水曜日
```

### 日付の計算

#### plus

`plus`系のメソッドを使って日時の加算を行います。

```java:plus
DateTime dt1 = DateTime.now();
System.out.println(DEF_FMT.print(dt1));
// ⇒ 西暦 2015-07-08(水) 午後21:52:23.949 +09:00.

/*10分足す*/
dt1 = dt1.plusMinutes(10);
System.out.println(DEF_FMT.print(dt1));
// ⇒ 西暦 2015-07-08(水) 午後22:02:23.949 +09:00.

/*2時間足す*/
dt1 = dt1.plusHours(2);
System.out.println(DEF_FMT.print(dt1));
// ⇒ 西暦 2015-07-09(木) 午前00:02:23.949 +09:00.

/*3日足す*/
dt1 = dt1.plusDays(3);
System.out.println(DEF_FMT.print(dt1));
// ⇒ 西暦 2015-07-12(日) 午前00:02:23.949 +09:00.
```

#### minus

`minus`系のメソッドを使って日時の減算を行います。

```java:minus
DateTime dt2 = DateTime.now();
System.out.println(DEF_FMT.print(dt2));
// ⇒ 西暦 2015-07-08(水) 午後21:52:23.950 +09:00.

/*10分引く*/
dt2 = dt2.minusMinutes(10);
System.out.println(DEF_FMT.print(dt2));
// ⇒ 西暦 2015-07-08(水) 午後21:42:23.950 +09:00.

/*2時間引く*/
dt2 = dt2.minusHours(2);
System.out.println(DEF_FMT.print(dt2));
// ⇒ 西暦 2015-07-08(水) 午後19:42:23.950 +09:00.

/*3日引く*/
dt2 = dt2.minusDays(3);
System.out.println(DEF_FMT.print(dt2));
// ⇒ 西暦 2015-07-05(日) 午後19:42:23.950 +09:00.
```

#### with

`with`系のメソッドを使って特定のフィールドの日時を変更します。

```java:with
DateTime dt3 = DateTime.now();
System.out.println(DEF_FMT.print(dt3));
// ⇒ 西暦 2015-07-08(水) 午後21:52:23.950 +09:00.

/*時、分、秒、ミリ秒を0にセット*/
dt3 = dt3.withTime(0, 0, 0, 0);
System.out.println(DEF_FMT.print(dt3));
// ⇒ 西暦 2015-07-08(水) 午前00:00:00.000 +09:00.

/*年を2016にセット*/
dt3 = dt3.withYear(2016);
System.out.println(DEF_FMT.print(dt3));
// ⇒ 西暦 2016-07-08(金) 午前00:00:00.000 +09:00.

/*月を12にセット*/
dt3 = dt3.withMonthOfYear(12);
System.out.println(DEF_FMT.print(dt3));
// ⇒ 西暦 2016-12-08(木) 午前00:00:00.000 +09:00.
```

#### round

`round`系のメソッドを使って日付の丸め処理を行います。

```java:round
DateTime dt4 = DateTime dt4 = new DateTime(2015, 7, 8, 12, 35, 25, 999);
System.out.println(DEF_FMT.print(dt4));
// ⇒ 西暦 2015-07-08(水) 午後12:35:25.999 +09:00.

DateTime dt5 = dt4.hourOfDay().roundFloorCopy();
System.out.println(DEF_FMT.print(dt4));
// ⇒ 西暦 2015-07-08(水) 午後12:00:00.000 +09:00.

dt5 = dt4.minuteOfHour().roundFloorCopy();
System.out.println(DEF_FMT.print(dt4));
// ⇒ 西暦 2015-07-08(水) 午後12:35:00.000 +09:00.

dt5 = dt4.hourOfDay().roundCeilingCopy();
System.out.println(DEF_FMT.print(dt4));
// ⇒ 西暦 2015-07-08(水) 午後13:00:00.000 +09:00.

dt5 = dt4.minuteOfHour().roundCeilingCopy();
System.out.println(DEF_FMT.print(dt4));
// ⇒ 西暦 2015-07-08(水) 午後12:36:00.000 +09:00.
```

#### roundサンプル

**year()**

`2015-05-15 11:30:00`、`2015-06-15 11:30:00`、`2015-07-15 11:30:00`の日時に対して3種類の丸め処理を行った結果を下表にまとめました。

```java:example
new DateTime(2015, 5, 15, 11, 30, 00, 000).year().roundFloorCopy();
new DateTime(2015, 5, 15, 11, 30, 00, 000).year().roundCeilingCopy()
new DateTime(2015, 5, 15, 11, 30, 00, 000).year().roundHalfFloorCopy()

new DateTime(2015, 6, 15, 11, 30, 00, 000).year().roundFloorCopy();
new DateTime(2015, 6, 15, 11, 30, 00, 000).year().roundCeilingCopy()
new DateTime(2015, 6, 15, 11, 30, 00, 000).year().roundHalfFloorCopy()

new DateTime(2015, 7, 15, 11, 30, 00, 000).year().roundFloorCopy();
new DateTime(2015, 7, 15, 11, 30, 00, 000).year().roundCeilingCopy()
new DateTime(2015, 7, 15, 11, 30, 00, 000).year().roundHalfFloorCopy()
```

|method                  |`2015-05-15 11:30:00` |`2015-06-15 11:30:00` |`2015-07-15 11:30:00` |
|:-----------------------|:---------------------|:---------------------|:---------------------|
|roundFloorCopy          |`2015-01-01 00:00:00` |`2015-01-01 00:00:00` |`2015-01-01 00:00:00` |
|roundCeilingCopy        |`2016-01-01 00:00:00` |`2016-01-01 00:00:00` |`2016-01-01 00:00:00` |
|roundHalfEvenCopy       |`2015-01-01 00:00:00` |`2015-01-01 00:00:00` |`2016-01-01 00:00:00` |


**monthOfYear()**

`2015-06-15 11:30:00`、`2015-06-16 11:30:00`、`2015-06-17 11:30:00`の日時に対して3種類の丸め処理を行った結果を下表にまとめました。

```java:example
new DateTime(2015, 6, 15, 11, 30, 00, 000).monthOfYear().roundFloorCopy();
new DateTime(2015, 6, 15, 11, 30, 00, 000).monthOfYear().roundCeilingCopy();
new DateTime(2015, 6, 15, 11, 30, 00, 000).monthOfYear().roundHalfFloorCopy();

new DateTime(2015, 6, 16, 11, 30, 00, 000).monthOfYear().roundFloorCopy();
new DateTime(2015, 6, 16, 11, 30, 00, 000).monthOfYear().roundCeilingCopy();
new DateTime(2015, 6, 16, 11, 30, 00, 000).monthOfYear().roundHalfFloorCopy();

new DateTime(2015, 6, 17, 11, 30, 00, 000).monthOfYear().roundFloorCopy();
new DateTime(2015, 6, 17, 11, 30, 00, 000).monthOfYear().roundCeilingCopy();
new DateTime(2015, 6, 17, 11, 30, 00, 000).monthOfYear().roundHalfFloorCopy();
```

|method                  |`2015-06-15 11:30:00` |`2015-06-16 11:30:00` |`2015-06-17 11:30:00` |
|:-----------------------|:---------------------|:---------------------|:---------------------|
|roundFloorCopy          |`2015-06-01 00:00:00` |`2015-06-01 00:00:00` |`2015-06-01 00:00:00` |
|roundCeilingCopy        |`2015-07-01 00:00:00` |`2015-07-01 00:00:00` |`2015-07-01 00:00:00` |
|roundHalfEvenCopy       |`2015-06-01 00:00:00` |`2015-07-01 00:00:00` |`2015-07-01 00:00:00` |


`2015-07-15 11:30:00`、`2015-07-16 11:30:00`、`2015-07-17 11:30:00`の日時に対して3種類の丸め処理を行った結果を下表にまとめました。

```java:exmaple
neww DateTime(2015, 7, 15, 11, 30, 00, 000).monthOfYear().roundFloorCopy();
neww DateTime(2015, 7, 15, 11, 30, 00, 000).monthOfYear().roundCeilingCopy();
neww DateTime(2015, 7, 15, 11, 30, 00, 000).monthOfYear().roundHalfFloorCopy();

neww DateTime(2015, 7, 16, 11, 30, 00, 000).monthOfYear().roundFloorCopy();
neww DateTime(2015, 7, 16, 11, 30, 00, 000).monthOfYear().roundCeilingCopy();
neww DateTime(2015, 7, 16, 11, 30, 00, 000).monthOfYear().roundHalfFloorCopy();

neww DateTime(2015, 7, 17, 11, 30, 00, 000).monthOfYear().roundFloorCopy();
neww DateTime(2015, 7, 17, 11, 30, 00, 000).monthOfYear().roundCeilingCopy();
neww DateTime(2015, 7, 17, 11, 30, 00, 000).monthOfYear().roundHalfFloorCopy();
```

|method                  |`2015-07-15 11:30:00` |`2015-07-16 11:30:00` |`2015-07-17 11:30:00` |
|:-----------------------|:---------------------|:---------------------|:---------------------|
|roundFloorCopy          |`2015-07-01 00:00:00` |`2015-07-01 00:00:00` |`2015-07-01 00:00:00` |
|roundCeilingCopy        |`2015-08-01 00:00:00` |`2015-08-01 00:00:00` |`2015-08-01 00:00:00` |
|roundHalfEvenCopy       |`2015-07-01 00:00:00` |`2015-07-01 00:00:00` |`2015-08-01 00:00:00` |


**hourOfDay()**

`2015-06-15 11:29:00`、`2015-06-15 11:30:00`、`2015-06-15 11:31:00`の日時に対して3種類の丸め処理を行った結果を下表にまとめました。

```java:example
new DateTime(2015, 6, 15, 11, 29, 00, 000).hourOfDay().roundFloorCopy();
new DateTime(2015, 6, 15, 11, 29, 00, 000).hourOfDay().roundCeilingCopy();
new DateTime(2015, 6, 15, 11, 29, 00, 000).hourOfDay().roundHalfFloorCopy();

new DateTime(2015, 6, 15, 11, 30, 00, 000).hourOfDay().roundFloorCopy();
new DateTime(2015, 6, 15, 11, 30, 00, 000).hourOfDay().roundCeilingCopy();
new DateTime(2015, 6, 15, 11, 30, 00, 000).hourOfDay().roundHalfFloorCopy();

new DateTime(2015, 6, 15, 11, 31, 00, 000).hourOfDay().roundFloorCopy();
new DateTime(2015, 6, 15, 11, 31, 00, 000).hourOfDay().roundCeilingCopy();
new DateTime(2015, 6, 15, 11, 31, 00, 000).hourOfDay().roundHalfFloorCopy();
```

|method                  |`2015-06-15 11:29:00` |`2015-06-15 11:30:00` |`2015-06-15 11:31:00` |
|:-----------------------|:---------------------|:---------------------|:---------------------|
|roundFloorCopy          |`2015-06-15 11:00:00` |`2015-06-15 11:00:00` |`2015-06-15 11:00:00` |
|roundCeilingCopy        |`2015-06-15 12:00:00` |`2015-06-15 12:00:00` |`2015-06-15 12:00:00` |
|roundHalfEvenCopy       |`2015-06-15 11:00:00` |`2015-06-15 11:00:00` |`2015-06-15 12:00:00` |


#### 日付の比較

```java:example
DateTime dt1 = DateTime.now();
DateTime dt2 = dt1.plusHours(1);
DateTime dt3 = dt1.minusHours(1);

System.out.println(DEF_FMT.print(dt1));
// ⇒ 西暦 2015-07-08(水) 午後22:04:14.745 +09:00.
System.out.println(DEF_FMT.print(dt2));
// ⇒ 西暦 2015-07-08(水) 午後23:04:14.745 +09:00.
System.out.println(DEF_FMT.print(dt3));
// ⇒ 西暦 2015-07-08(水) 午後21:04:14.745 +09:00.

if (dt1.isEqual(dt2)) {
  System.out.println("dt1 is equal dt2");
} else {
  System.out.println("dt1 is not equal dt2");
  // ⇒ dt1 is not equal dt2
}

if (dt1.isEqual(dt1)) {
  System.out.println("dt1 is equal dt1");
  // ⇒ dt1 is equal dt1
} else {
  System.out.println("dt1 is not equal dt1");
}

if (dt1.isAfter(dt2)) {
  System.out.println("dt1 is after dt2");
}
if (dt1.isAfter(dt3)) {
  System.out.println("dt1 is after dt3");
  // ⇒ dt1 is after dt3
}
if (dt1.isBefore(dt2)) {
  System.out.println("dt1 is before dt2");
  // ⇒ dt1 is before dt2
}
if (dt1.isBefore(dt3)) {
  System.out.println("dt1 is before dt2");
}
```


#### 期間の比較

Joda-Timeでは期間を表すクラスが3つあります。

* `Interval`
* `Duration`
* `Period`

##### Interval

2つの日付から期間を生成し、2つの期間同士を比較することができます。

> このクラスは、明確なインスタントによって範囲が決められた特定の期間を表現します。Interval は半開の期間です。つまり、Interval によってカプセル化された期間には、期間の開始は含まれますが、終了は除外されることを意味します。
Interval を使用するのは、時系列における特定の時点で始まり、特定の時点で終了する期間を表現しなければならない場合です。
> [Joda-Time - IBM developerWorks 日本語版] (http://www.ibm.com/developerworks/jp/java/library/j-jodatime.html)

###### abuts()

`abuts`で2つの期間が隣接しているか確認することができます。

```java:abuts
DateTime dt1 = new DateTime(2015, 7,  8,  0,  0,  0, 0);
DateTime dt2 = new DateTime(2015, 7,  9, 23, 59, 59, 0);
Interval interval1 = new Interval(dt1, dt2);
System.out.println(interval1.toString());
// ⇒ 2015-07-08T00:00:00.000+09:00/2015-07-09T23:59:59.000+09:00

DateTime dt3 = new DateTime(2015, 7, 10,  0,  0,  0, 0);
DateTime dt4 = new DateTime(2015, 7, 11, 23, 59, 59, 0);
Interval interval2 = new Interval(dt3, dt4);
System.out.println(interval2.toString());
// ⇒ 2015-07-10T00:00:00.000+09:00/2015-07-11T23:59:59.000+09:00

if (interval1.abuts(interval2)) {
  System.out.println("abuts");
} else {
  System.out.println("not abuts");
  // ⇒ not abuts
}

dt2 = dt2.plusSeconds(1);
interval1 = new Interval(dt1, dt2);

if (interval1.abuts(interval2)) {
  System.out.println("abuts");
  // ⇒ abuts
} else {
  System.out.println("not abuts");
}
```

###### gap()

`gap`で2つの期間の隔たりを確認することができます。

```java:gap
DateTime dt1 = new DateTime(2015, 7,  8,  0,  0,  0, 0);
DateTime dt2 = new DateTime(2015, 7, 10,  0,  0,  0, 0);
Interval interval1 = new Interval(dt1, dt2);
System.out.println(interval1.toString());
// ⇒ 2015-07-08T00:00:00.000+09:00/2015-07-10T00:00:00.000+09:00

DateTime dt3 = new DateTime(2015, 7, 13,  0,  0,  0, 0);
DateTime dt4 = new DateTime(2015, 7, 14,  0,  0,  0, 0);
Interval interval2 = new Interval(dt3, dt4);
System.out.println(interval2.toString());
// ⇒ 2015-07-13T00:00:00.000+09:00/2015-07-14T00:00:00.000+09:00

Interval gaps = interval1.gap(interval2);
if (gaps != null) {
  System.out.println(gaps.toString());
  // ⇒ 2015-07-10T00:00:00.000+09:00/2015-07-13T00:00:00.000+09:00
} else {
  System.out.println("not gaps");
}
```

###### overlap()

`overlap`で2つの期間の重なった範囲を確認することができます。

```java:overlap
DateTime dt1 = new DateTime(2015, 7,  8,  0,  0,  0, 0);
DateTime dt2 = new DateTime(2015, 7, 12,  0,  0,  0, 0);
Interval interval1 = new Interval(dt1, dt2);
System.out.println(interval1.toString());
// ⇒ 2015-07-08T00:00:00.000+09:00/2015-07-12T00:00:00.000+09:00

DateTime dt3 = new DateTime(2015, 7, 11, 15, 30,  0, 0);
DateTime dt4 = new DateTime(2015, 7, 13,  0,  0,  0, 0);
Interval interval2 = new Interval(dt3, dt4);
System.out.println(interval2.toString());
// ⇒ 2015-07-11T15:30:00.000+09:00/2015-07-13T00:00:00.000+09:00

if (interval1.overlaps(interval2)) {
  Interval overlap = interval1.overlap(interval2);
  System.out.println(overlap.toString());
  // ⇒ 2015-07-11T15:30:00.000+09:00/2015-07-12T00:00:00.000+09:00
} else {
  System.out.println("not overlaps");
}
```

###### after()/before()

`after`,`before`で2つの期間の前後関係を確認することができます。

```java
DateTime dt1 = new DateTime(2015, 7,  8,  0,  0,  0, 0);
DateTime dt2 = new DateTime(2015, 7,  9,  0,  0,  0, 0);
Interval a = new Interval(dt1, dt2);
System.out.println(a.toString());
// ⇒ 2015-07-08T00:00:00.000+09:00/2015-07-09T00:00:00.000+09:00

DateTime dt3 = new DateTime(2015, 7,  6,  0,  0,  0, 0);
DateTime dt4 = new DateTime(2015, 7,  7,  0,  0,  0, 0);
Interval b = new Interval(dt3, dt4);
System.out.println(b.toString());
// ⇒ 2015-07-06T00:00:00.000+09:00/2015-07-07T00:00:00.000+09:00

DateTime dt5 = new DateTime(2015, 7, 10,  0,  0,  0, 0);
DateTime dt6 = new DateTime(2015, 7, 11,  0,  0,  0, 0);
Interval c = new Interval(dt5, dt6);
System.out.println(c.toString());
// ⇒ 2015-07-10T00:00:00.000+09:00/2015-07-11T00:00:00.000+09:00

if (a.isAfter(b)) {
  System.out.println("a is after b");
  // ⇒ a is after b
} else {
  System.out.println("a is not after b");
}

if (a.isBefore(b)) {
  System.out.println("a is before b");
} else {
  System.out.println("a is not before b");
  // ⇒ a is not before b
}

if (a.isAfter(c)) {
  System.out.println("a is after c");
} else {
  System.out.println("a is not after c");
  // ⇒ a is not after c
}

if (a.isBefore(c)) {
  System.out.println("a is before c");
  // ⇒ a is before c
} else {
  System.out.println("a is not before c");
}
```

[Class Interval] (http://www.joda.org/joda-time/apidocs/org/joda/time/Interval.html)



##### Duration

期間を操作することができます。
plus/minusを使用して期間を短縮、延長することができます。

> このクラスは期間をミリ秒単位で数学的に表現します。このクラスのメソッドは、ミリ秒単位での表現を標準的な数学変換 (1 分は 60 秒、1 日は 24 時間など) によって秒、分、時などの標準単位での表現に変換するために使用することができます。
Duration のインスタンスを使用して期間を表現するのは、その特定の期間がいつから始まるかは重要でない場合、あるいは期間をミリ秒で処理すると都合がよい場合に限られます。
> [Joda-Time - IBM developerWorks 日本語版] (http://www.ibm.com/developerworks/jp/java/library/j-jodatime.html)

```java:Duration
DateTime dt5 = new DateTime(2015, 7,  1, 0, 0, 0);
DateTime dt6 = new DateTime(2016, 9,  4, 4, 5, 6);

Duration duration = new Duration(dt5, dt6);

System.out.println(String.format("Days:%d, Hours:%d, Minutes:%d, Seconds:%d",
  duration.getStandardDays(),
  duration.getStandardHours(),
  duration.getStandardMinutes(),
  duration.getStandardSeconds())
);
// ⇒ Days:431, Hours:10348, Minutes:620885, Seconds:37253106

System.out.println(PERIOD_FMT.print(duration.toPeriod()));
// ⇒ 0 years 0 months 0 weeks 0 days 10348 hours 5 minutes 6 seconds

System.out.println(PERIOD_FMT.print(duration.toPeriodFrom(dt5)));
// ⇒ 1 year 2 months 0 weeks 3 days 4 hours 5 minutes 6 seconds

/*1時間延長する*/
duration = duration.plus(1000L * 60L * 60L);

System.out.println(PERIOD_FMT.print(duration.toPeriodFrom(dt5)));
// ⇒ 1 year 2 months 0 weeks 3 days 5 hours 5 minutes 6 seconds

/*Partial*/
Days dDays = duration.toStandardDays();
Hours dHours = duration.toStandardHours();
Minutes dMinutes = duration.toStandardMinutes();
Seconds dSeconds = duration.toStandardSeconds();

System.out.println(String.format("Days:%d Hours:%d Minutes:%d Seconds:%d",
  dDays.getDays(),
  dHours.getHours(),
  dMinutes.getMinutes(),
  dSeconds.getSeconds()));
// ⇒ Days:431 Hours:10349 Minutes:620945 Seconds:37256706
```

[Class Duration] (http://www.joda.org/joda-time/apidocs/org/joda/time/Duration.html)



##### Period

期間を年や月、週や日といった単位で操作することが可能です。

> このクラスが表現する概念は Duration と同じですが、その表現は、例えば年、月、週などといった「人間」にとっての観点からです。
Period を使用するのは、その期間がいつから始まるかが必ずしも重要でない場合や、あるいは Period によってカプセル化された期間を表す個々のフィールドを取得できるということが重要な場合です。
> [Joda-Time - IBM developerWorks 日本語版] (http://www.ibm.com/developerworks/jp/java/library/j-jodatime.html)

```java:Period
DateTime dt7 = new DateTime(2015, 7,  1, 0, 0, 0);
DateTime dt8 = new DateTime(2016, 9,  4, 4, 5, 6);

Period period = new Period(dt7, dt8, PeriodType.yearMonthDayTime());

System.out.println(String.format("Years:%d, Months:%d, Days:%d, Hours:%d, Minutes:%d, Seconds:%d",
  period.getYears(),
  period.getMonths(),
  period.getDays(),
  period.getHours(),
  period.getMinutes(),
  period.getSeconds())
);
// ⇒ Years:1, Months:2, Days:3, Hours:4, Minutes:5, Seconds:6

System.out.println(PERIOD_FMT.print(period));
// ⇒ 1 year 2 months 0 weeks 3 days 4 hours 5 minutes 6 seconds

/*Partial*/
Years years = Years.yearsBetween(dt7, dt8);
Months months = Months.monthsBetween(dt7, dt8);
Days days = Days.daysBetween(dt7, dt8);
Hours hours = Hours.hoursBetween(dt7, dt8);
Minutes minutes = Minutes.minutesBetween(dt7, dt8);
Seconds seconds = Seconds.secondsBetween(dt7, dt8);
Weeks weeks = Weeks.weeksBetween(dt7, dt8);

System.out.println(String.format("Years:%d Months:%d Days:%d Hours:%d Minutes:%d Seconds:%d Weeks:%d",
  years.getYears(),
  months.getMonths(),
  days.getDays(),
  hours.getHours(),
  minutes.getMinutes(),
  seconds.getSeconds(),
  weeks.getWeeks()));
// ⇒ Years:1 Months:14 Days:431 Hours:10348 Minutes:620885 Seconds:37253106 Weeks:61
```

[Class Period] (http://www.joda.org/joda-time/apidocs/org/joda/time/Period.html)



#### 特定の日を求める

```java:example
DateTime dt1 = DateTime.now();
System.out.println(DEF_FMT.print(dt1));
// ⇒ 西暦 2015-07-08(水) 午後22:34:17.159 +09:00.

/*年初、年末*/
DateTime yf = dt1.dayOfYear().withMinimumValue();
DateTime yl = dt1.dayOfYear().withMaximumValue();
System.out.println(DEF_FMT.print(yf));
// ⇒ 西暦 2015-01-01(木) 午後22:34:17.159 +09:00.
System.out.println(DEF_FMT.print(yl));
// ⇒ 西暦 2015-12-31(木) 午後22:34:17.159 +09:00.

/*月初、月末*/
DateTime mf = dt1.dayOfMonth().withMinimumValue();
DateTime ml = dt1.dayOfMonth().withMaximumValue();
System.out.println(DEF_FMT.print(mf));
// ⇒ 西暦 2015-07-01(水) 午後22:34:17.159 +09:00.
System.out.println(DEF_FMT.print(ml));
// ⇒ 西暦 2015-07-31(金) 午後22:34:17.159 +09:00.

/*週初、週末*/
DateTime wf = dt1.dayOfWeek().withMinimumValue();
DateTime wl = dt1.dayOfWeek().withMaximumValue();
System.out.println(DEF_FMT.print(wf));
// ⇒ 西暦 2015-07-06(月) 午後22:34:17.159 +09:00.
System.out.println(DEF_FMT.print(wl));
// ⇒ 西暦 2015-07-12(日) 午後22:34:17.159 +09:00.

/*今週の木曜日*/
DateTime dt2 = DateTime.now();
System.out.println(DEF_FMT.print(dt2));
// ⇒ 西暦 2015-07-08(水) 午後22:34:17.160 +09:00.
dt2 = dt2.dayOfWeek().withMinimumValue().withDayOfWeek(DateTimeConstants.THURSDAY);
System.out.println(DEF_FMT.print(dt2));
// ⇒ 西暦 2015-07-09(木) 午後22:34:17.160 +09:00.
```

うるう年の判定

```java:isLeap
DateTime dt3 = new DateTime(2016, 2, 29, 0, 0, 0, 0);
System.out.println(DEF_FMT.print(dt3));
// ⇒ 西暦 2016-02-29(月) 午前00:00:00.000 +09:00.

if (dt3.year().isLeap()) {
  System.out.println("うるう年");
  // ⇒ うるう年
} else {
  System.out.println("");
}
```



## Instantを使った日付処理

`Instant`は、Java epoch(1970-01-01 00:00:00.000)からのオフセットで日時の定点を表します。
インスタンスの生成やフォーマットの方法は`DateTime`と似ています。

### インスタンスの生成

#### コンストラクタ

```java:constructor
Instant i1 = new Instant();
System.out.println(DEF_FMT.print(i1));
// ⇒ 西暦 2015-07-09(木) 午前00:36:16.368 +00:00.
```

引数に任意の時間のミリ秒を指定することもできます。

```java:constructor
Instant i2 = new Instant(new Date().getTime());
System.out.println(DEF_FMT.print(i2));
// ⇒ 西暦 2015-07-09(木) 午前00:36:16.408 +00:00.
```

引数に0秒を指定するとepochになります。

```java:constructor
Instant epoch = new Instant(0L);
System.out.println(DEF_FMT.print(epoch));
// ⇒ 西暦 1970-01-01(木) 午前00:00:00.000 +00:00.
```

#### now()

```java:now
Instant i3 = Instant.now();
System.out.println(DEF_FMT.print(i3));
// ⇒ 西暦 2015-07-09(木) 午前00:36:16.408 +00:00.
```

#### parse()

```java:parse
Instant pi1 = Instant.parse("2006-01-02");
System.out.println(DEF_FMT.print(pi1));
// ⇒ 西暦 2006-01-01(日) 午後15:00:00.000 +00:00.
```

```java:parse
Instant pi2 = Instant.parse("2006-01-02T15:04:05");
System.out.println(DEF_FMT.print(pi1));
// ⇒ 西暦 2006-01-02(月) 午前06:04:05.000 +00:00.
```

```java:parse
Instant pi3 = Instant.parse("20060102 150405", DateTimeFormat.forPattern("yyyyMMdd HHmmss"));
System.out.println(DEF_FMT.print(pi1));
// ⇒ 西暦 2006-01-02(月) 午前06:04:05.000 +00:00.
```

#### タイムゾーンと暦

Instantはタイムゾーンを指定できません。デフォルトで`UTC`が設定されています。

```java:timezone
Instant i1 = Instant.now();

DateTimeZone defaultZone = i1.getZone();
Chronology defaultChro = i1.getChronology();
System.out.println(defaultZone.toString());
// ⇒ UTC
System.out.println(defaultChro.toString());
// ⇒ ISOChronology[UTC]
```


#### フォーマット

フォーマットは`DateTime`と同じです。

```java:format
Instant i1 = Instant.now();

System.out.println(DateTimeFormat.fullDateTime().print(i1));
// ⇒ 2015年7月9日 0時36分16秒 UTC
System.out.println(DateTimeFormat.longDateTime().print(i1));
// ⇒ 2015/07/09 0:36:16 UTC
System.out.println(DateTimeFormat.mediumDateTime().print(i1));
// ⇒ 2015/07/09 0:36:16
System.out.println(DateTimeFormat.shortDateTime().print(i1));
// ⇒ 15/07/09 0:36
```

#### 日付の計算

```java:example
Instant i1 = Instant.now();
System.out.println(shortFmt.print(i1));
// ⇒ 西暦 2015-07-09(木) 午前00:36:16.446 +00:00.

/*60秒加算*/
i1 = i1.plus(1000L * 60L);
System.out.println(shortFmt.print(i1));
// ⇒ 西暦 2015-07-09(木) 午前00:37:16.446 +00:00.

/*30秒減算*/
i1 = i1.minus(1000L * 30L);
System.out.println(shortFmt.print(i1));
// ⇒ 西暦 2015-07-09(木) 午前00:36:46.446 +00:00.
```


## メモ

### 主要クラス

|class                |thread-safe |immutable   |interface                          |
|:--------------------|:----------:|:----------:|:----------------------------------|
|`Instant`            | O          | O          |`ReadableInstant`                  |
|`Partial`            | O          | O          |`ReadablePartial`                  |
|                     |            |            |                                   |
|`BuddhistChronology` | O          | O          |                                   |
|`CopticChronology`   | O          | O          |                                   |
|`EthiopicChronology` | O          | O          |                                   |
|`GJChronology`       | O          | O          |                                   |
|`GregorianChronology`| O          | O          |                                   |
|`IslamicChronology`  | O          | O          |                                   |
|`ISOChronology`      | O          | O          |                                   |
|`JulianChronology`   | O          | O          |                                   |
|                     |            |            |                                   |
|`DateTime`           | O          | O          |`ReadableDateTime`<br/>`ReadableInstant`|
|                     |            |            |                                   |
|`LocalDateTime`      | O          | O          |`ReadablePartial`                  |
|`LocalDate`          | O          | O          |`ReadablePartial`                  |
|`LocalTime`          | O          | O          |`ReadablePartial`                  |
|`YearMonth`          | O          | O          |`ReadablePartial`                  |
|`MonthDay`           | O          | O          |`ReadablePartial`                  |
|                     |            |            |                                   |
|`Interval`           | O          | O          |`ReadableInterval`                 |
|`Duration`           | O          | O          |`ReadableDuration`                 |
|`Period`             | O          | O          |`ReadablePeriod`                   |
|                     |            |            |                                   |
|`Years`              | O          | O          |`ReadablePeriod`                   |
|`Months`             | O          | O          |`ReadablePeriod`                   |
|`Days`               | O          | O          |`ReadablePeriod`                   |
|`Hours`              | O          | O          |`ReadablePeriod`                   |
|`Minutes`            | O          | O          |`ReadablePeriod`                   |
|`Seconds`            | O          | O          |`ReadablePeriod`                   |
|`Weeks`              | O          | O          |`ReadablePeriod`                   |

#### Chronologyクラス

|class                                                                                                      |description                      |
|:----------------------------------------------------------------------------------------------------------|:--------------------------------|
|[Chronology] (http://www.joda.org/joda-time/apidocs/org/joda/time/Chronology.html)                         |抽象クラス            |
|[BuddhistChronology] (http://www.joda.org/joda-time/apidocs/org/joda/time/chrono/BuddhistChronology.html)  |仏暦                 |
|[CopticChronology] (http://www.joda.org/joda-time/apidocs/org/joda/time/chrono/CopticChronology.html)      |コピト暦              |
|[EthiopicChronology] (http://www.joda.org/joda-time/apidocs/org/joda/time/chrono/EthiopicChronology.html)  |エチオピア暦          |
|[GJChronology] (http://www.joda.org/joda-time/apidocs/org/joda/time/chrono/GJChronology.html)              |グレゴリオ/ユリウス暦? |
|[GregorianChronology] (http://www.joda.org/joda-time/apidocs/org/joda/time/chrono/GregorianChronology.html)|グレゴリオ暦           |
|[IslamicChronology] (http://www.joda.org/joda-time/apidocs/org/joda/time/chrono/IslamicChronology.html)    |イスラム暦             |
|[ISOChronology] (http://www.joda.org/joda-time/apidocs/org/joda/time/chrono/ISOChronology.html)            |based on the ISO-8601 standard. |
|[JulianChronology] (http://www.joda.org/joda-time/apidocs/org/joda/time/chrono/JulianChronology.html)      |ユリウス暦             |