java8の日付時間が新しくなったよ

# JDK1.8前の日付時間クラス
## Date
jdk1.0から提供されている日付時間クラスで、エポックからのミリ秒ヲ保持している。
「GMT 1970年1月1日 0時0分0秒からの現在に至るミリ秒」
Y2k問題や性能面の問題があるので、メソッドは殆ど非推奨(@Deprecated)されていている。

```java:生き残っているコントラクターとメソッド
// 生成
Date d1 = new Date();
Date d2 = new Date(System.currentTimeMillis() + 1);

// before,after
System.out.println(d1.after(d2));
System.out.println(d1.before(d2));

// set,get
d1.setTime(System.currentTimeMillis() + 1);
d2.setTime(System.currentTimeMillis() - 1);
System.out.println(d1.getTime());
System.out.println(d2.getTime());
```

### Dateのy2k問題
```java:y2k問題
System.out.println(new Date(10, 1, 1));
```
⇒ 1910年1月1日になってしまう。

```java:Date.java
public Date(int year, int month, int date, int hrs, int min, int sec) {
   int y = year + 1900;　// <- ここ
   // 略
}
```

## Calendar
Date.javaの欠陥を改善したもので、名前の通りカレンダーを表現しているクラス。
1. Calendarクラスは、年月日時分秒ミリ秒のフィールドを持っている。
`protected int           fields[];`

2. 抽象クラスであり、__（多分）__Tmeplate Methodパターンで実装されており、
サブクラスを実装することで世界各地で使うカレンダーの差異を吸収している。
例：和暦、旧暦

### Calendar のコアAPI
|API|概要|
|---|---|
|Calendar | カレンダーの(抽象)親クラス |
|TimeZone  | 時間帯を表す | 
|Locale    | 地域を表して、これによって生成されるCalendarが異なる |

### Caldendar生成
```java:表示用
private static void show(Calendar cal) {
    System.out.println("生成されたカレンダー : " + cal.getClass().getName());
    System.out.println(
        cal.get(Calendar.YEAR) + "年"
        + (cal.get(Calendar.MONTH) + 1) + "月"
        + cal.get(Calendar.DAY_OF_MONTH) + "日 "
        + cal.get(Calendar.HOUR_OF_DAY) + "時"
        + cal.get(Calendar.MINUTE) + "分"
        + cal.get(Calendar.SECOND) + "秒");
}
```
```java:生成
Calendar デフォルトカレンダー = Calendar.getInstance();
show(デフォルトカレンダー);

Calendar 和暦_デフォルト時間帯 = Calendar.getInstance(new Locale("ja", "JP", "JP"));
show(和暦_デフォルト時間帯);

Calendar デフォルト地域_JST = Calendar.getInstance(TimeZone.getTimeZone("JST"));
show(デフォルト地域_JST);

Calendar 和暦_GMT = Calendar.getInstance(TimeZone.getTimeZone("GMT"), new Locale("ja", "JP", "JP"));
show(和暦_GMT);
```

```test:出力
生成されたカレンダー : java.util.GregorianCalendar
2017年11月13日 12時20分0秒
生成されたカレンダー : java.util.JapaneseImperialCalendar
29年11月13日 12時20分0秒
生成されたカレンダー : java.util.GregorianCalendar
2017年11月13日 12時20分0秒
生成されたカレンダー : java.util.JapaneseImperialCalendar
29年11月13日 3時20分0秒
```

1. GregorianCalendar、デフォルト地域で生成される
2. JapaneseImperialCalendar、地域を日本にすることで生成される  
![Japanese-Calendar.PNG](https://qiita-image-store.s3.amazonaws.com/0/104977/38b9fcca-a584-fe78-5d86-30f14c27ec6d.png)

### Calendar <=> Date
```java:Calendar,Date変換
// Date to Calendar
Calendar.getInstance().setTime(new Date());
// Calendar to Date
Calendar.getInstance().getTime();
```

### add()とroll()の違い
add()とroll()両方指定フィールド(年月日時分秒ミリ秒)を増減するためのものだが、

| 　| 上位 | 下位 |
|---|---|---|
| add() | 上位を変更する | 最小変更にする | 
| roll() | 上位を変更しない | 最小変更にする | 

```java:add()
Calendar calendar = Calendar.getInstance();
calendar.set(2015, Calendar.NOVEMBER,  30);
System.out.println("初期値 : " + formatter.format(calendar.getTime()));

calendar.add(Calendar.MONTH, 3);
System.out.println("add : " + formatter.format(calendar.getTime()));
```
__2015/11/30 -> add 月+3 -> 2016/2/29__

```java:roll()
Calendar calendar = Calendar.getInstance();
calendar.set(2015, Calendar.NOVEMBER,  30);
System.out.println("初期値 : " + formatter.format(calendar.getTime()));

calendar.roll(Calendar.MONTH, 3);
System.out.println("roll : " + formatter.format(calendar.getTime()));
```
__2015/11/30 -> roll 月+3 -> 2015/2/28__

### Lenient（寛大さ）&遅延

```java:
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
Calendar calendar = Calendar.getInstance();
calendar.set(2015, 15,  32);
System.out.println(formatter.format(calendar.getTime()));  // 2016/05/02

calendar.setLenient(false);
calendar.set(2015, 15,  32);
// Exception in thread "main" java.lang.IllegalArgumentException: MONTH
System.out.println(formatter.format(calendar.getTime()));
```
```text:出力
2016/05/02
Exception in thread "main" java.lang.IllegalArgumentException: MONTH
```

1. Lenientのデフォルトはtrueなので、`2015/15/32 -> 2016/05/02`を容認する
2. Lenient=falaseで、月=15を容認しないから
3. __例外はsetではなく、get()で発生する。__  
__set()は遅延されて、無駄な計算が行われなくするため。__

# JDK1.8の日付時間クラス
__本題！！__
JKD1.8から`java.timeパッケージ`に日付時間のクラスが数多く追加されている。

コアAPI
![jdk8-datetime-class (1).png](https://qiita-image-store.s3.amazonaws.com/0/104977/ae03441b-bbcb-63fd-fe54-dd58f10ff4ee.png)

## コアAPI
| 日付時間のコアAPI| 概要 |
|:---|:---|
|TemporalAccessor|日付、時間、オフセット、またはそれらのなんらかの組合せなどへの<b>読取り専用</b>アクセスを定義したインタフェースです。|
|Temporal|日付、時間、オフセット、またはそれらのなんらかの組合せなどへの<b>読取/書込</b>アクセスを定義したインタフェースです。|
|TemporalAmount|__時間の量__を定義したインタフェースです。|
|TemporalField|__日付時間__のフィールドを定義したインタフェースです。|
|TemporalUnit|__日付時間の単位__を定義したFunctionalインタフェースです。|
|TemporalAdjuster|__日付時間調整戦略__を提供するためのFunctionalインタフェースです。|
|TemporalQuery|__日付時間にアクセスする戦略__を提供するためのFunctionalインタフェースです。|

### TemporalAccessor
| TemporalAccessorメソッド| 結果| 
|:---|:---| 
| TemporalAccessor temporalAccessor =  LocalDate.of(2016, 2, 9) |2016-02-09|
| temporalAccessor.get(ChronoField.YEAR) |2016|
| temporalAccessor.getLong(ChronoField.MONTH_OF_YEAR) |2|
| temporalAccessor.isSupported(ChronoField.HOUR_OF_DAY) |false|
| temporalAccessor.range(ChronoField.DAY_OF_MONTH) |1 - 29|
| temporalAccessor.query(TemporalQueries.precision()) |Days|

1. TemporalAccessorを実装したLocalDateで`インスタンス`を取得してます。
2. TemporalFieldを実装した`ChronoField`で使って`年フィールド`を取得します。
3. TemporalQueryの実装返す`TemporalQueries.zoneId()`を使って`精度`を取得してます。

### Temporal
Temporalは、TemporalAccessorを継承して、書込みインタフェースを追加してます。

| Temporalメソッド| 結果| 
|:---|:---| 
| Temporal temporal = LocalDate.of(2016, 10, 1) |2016-10-01|
| temporal.plus(10, ChronoUnit.MONTHS) |2017-08-01|
| temporal.minus(Period.ofYears(1)) |2015-10-01|
| temporal.minus(2, ChronoUnit.YEARS) |2014-10-01|
| temporal.with(ChronoField.YEAR, 2010) |2010-10-01|
| temporal.with(LocalDate.of(2010, 1, 10)) |2010-01-10|
| temporal.until(LocalDate.of(2016, 1, 1), ChronoUnit.DAYS) |-274|

1. TemporalAmountを実装した`Period`で加算、減算してます。
2. TemporalUnitを実装した`ChronoUnit`で加算、減算してます。
3. TemporalFieldを実装した`ChronoField`で`年フィールド`を調整してます。
4. temporal.with(LocalDate.of(2010, 1, 10))の`LocalDate.of(2010, 1, 10)`はTemporalAdjusterにキャストされます。

### TemporalAmount
| TemporalAmountメソッド| 結果| 
|:---|:---| 
| TemporalAmount temporalAmount = Duration.ofDays(61) |P61D|
| temporalAmount.getUnits() |[Years, Months, Days]|
| temporalAmount.get(ChronoUnit.DAYS) |61|
| temporalAmount.get(ChronoUnit.MONTHS) |0|
| temporalAmount.subtractFrom(LocalDate.of(2010, 10, 1)) |2010-08-01|
| temporalAmount.addTo(LocalDate.of(2010, 10, 1)) |2010-12-01|

1. TemporalAmountを実装した`Duration`で`インスタンス`取得してます。
2. TemporalUnitを実装した`ChronoUnit`で値を取得してます。


### TemporalField
| TemporalFieldメソッド| 結果| 
|:---|:---| 
| TemporalField year = ChronoField.YEAR |Year|
| year.range()|-999999999 - 999999999|
| year.getBaseUnit()|Years|
| year.getDisplayName(Locale.JAPAN)|年|
| year.getFrom(LocalDate.of(2011, 1, 10))|2011|
| year.getRangeUnit() |Forever|
| year.isDateBased()|true|
| year.isTimeBased()|false|

TemporalFieldを実装した`ChronoField`でインスタンスを取得してます。

### TemporalUnit
| TemporalUnitメソッド| 結果| 
|:---|:---| 
| TemporalUnit days = ChronoUnit.DAYS |Days|
| days.addTo(LocalDate.of(2011, 1, 1), 2) |2011-01-03|
| days.getDuration() |PT24H|
| days.isSupportedBy(LocalDate.now()) |true|
| days.isDurationEstimated() |true|
| days.isDateBased() |true|
| days.isTimeBased() |false|

### TemporalAdjuster&TemporalAdjusters

| TemporalAdjusterメソッド| 結果| 
|:---|:---| 
| TemporalAdjuster adjuster = LocalDate.of(2011, 1, 1) |2011-01-01|
| adjuster.adjustInto(LocalDate.of(9999, 10, 1)) |2011-01-01|


TemporalAdjustersは色んな時間調整戦略を提供します。

| TemporalAdjusters| 結果| 
|:---|:---| 
| LocalDate.of(2011, 1, 1).with(TemporalAdjusters.lastDayOfYear()) |2011-12-31|
| LocalDate.of(2011, 1, 1).with(TemporalAdjusters.lastDayOfMonth()) |2011-01-31|

### TemporalQuery, TemporalQueries

例：年末まで何日残っているか？

```java:
TemporalQuery<Long> leftDays = temporal -> {
    LocalDate dayOfTarget = LocalDate.from(temporal);
    LocalDate lastDayOfYear = dayOfTarget.with(TemporalAdjusters.lastDayOfYear());
    Period period = dayOfTarget.until(lastDayOfYear);
    return ChronoUnit.DAYS.between(dayOfTarget, lastDayOfYear);
};
System.out.println(
    LocalDate.of(2015, 10, 3).query(leftDays)
);
```

TemporalQueriesは色んなアクセス戦略を提供します。
例：オブジェクトの精度はなんだ？

```java
LocalDate.of(2015, 10, 3).query(TemporalQueries.precision())
```

## 日付時間の実装
### Instant
1. エポック秒(1970-01-01T00:00:00Zから経過時間)を表現する__不変＆スレッドセーフ__クラス。
2. ナノ秒まで保持する。
3. Temporal, TemporalAdjusterを継承してます。

| インスタンス取得| toString()| 
|---|---| 
| Instant.now() |2017-11-14T01:47:25.392Z
| Instant.now(Clock.systemUTC()) |2017-11-14T01:47:25.486Z|
| Instant.now(Clock.system(ZoneId.of("Asia/Shanghai")))  |2017-11-14T01:47:25.502Z|
| Instant.parse("2016-10-10T10:20:30.123Z")  |2016-10-10T10:20:30.123Z|
| Instant.EPOCH  |1970-01-01T00:00:00Z|
| Instant.ofEpochMilli(10) |1970-01-01T00:00:00.010Z|
| Instant.ofEpochSecond(1)  |1970-01-01T00:00:01Z|
| Instant.ofEpochSecond(1, 2)  |1970-01-01T00:00:01.000000002Z|

| 常用メソッド| 結果| 
|---|---| 
| Instant instant = Instant.parse("2016-10-10T10:00:00.000Z") |2016-10-10T10:00:00Z|
| instant.toEpochMilli() | 1476093600000 |
| instant.plusSeconds(30) | 2016-10-10T10:00:30Z
| instant.minusSeconds(30) | 2016-10-10T09:59:30Z
| instant.isAfter(instant) | false
| instant.isBefore(instant) | false
| instant.equals(instant) | true

### LocalDate
__タイムゾーンなし日付__(`yyyy-mm-dd`)を表現する不変＆スレッドセーフクラスです。
誕生日などに使えます。

| インスタンス取得| toString()| 
|---|---| 
| LocalDate.now() |2017-11-14|
| LocalDate.now(Clock.systemUTC()) |2017-11-14|
| LocalDate.now(ZoneId.of("Europe/Paris")) |2017-11-14|
| LocalDate.of(2015, 10, 1) |2015-10-01|
| LocalDate.parse("2015 - 10 - 10") |2015-10-10|
| LocalDate.ofYearDay(2016, 60) |2016-02-29|

| 常用メソッド| toString()| 
|:---|:---| 
| LocalDate.of(2010, 2, 3).getYear() |2010|
| LocalDate.of(2010, 2, 3).getMonth() |FEBRUARY|
| LocalDate.of(2010, 2, 3).getDayOfMonth() |3|
| LocalDate.of(2010, 3, 3).getDayOfWeek() |WEDNESDAY|
| LocalDate.of(2010,1,1).withMonth(3).withYear(2016).withDayOfMonth(15)| 2016-03-15|
| LocalDate.of(2010,1,1).withYear(2016).withDayOfYear(59) | 2016-02-28|
| LocalDate.of(2010,1,1).minusYears(1).minusMonths(2).minusDays(3) | 2008-10-29|
| LocalDate.of(2010,1,1).plusYears(1).plusMonths(2).plusDays(3) | 2011-03-04|

### LocalTime
__タイムゾーンなし__(`HH:mm:ss.SSSSSSSSS`)を表現する不変＆スレッドセーフクラスです。

| インスタンス取得| toString()| 
|:---|:---| 
| LocalTime.now() |12:06:40.790|
| LocalTime.now(Clock.systemUTC()) |03:06:40.805|
| LocalTime.now(ZoneId.of("Europe/Paris")) |04:06:40.868|
| LocalTime.of(6, 10, 30) |06:10:30|
| LocalTime.parse("10:20:30") |10:20:30 | 
| LocalTime.of(6, 10, 30, 999999999) |06:10:30.999999999|

| 常用メソッド| toString()| 
|:---|:---| 
| LocalTime.of(10, 20, 30).getHour()|10|
| LocalTime.of(10, 20, 30).getSecond()|30|
| LocalTime.of(10, 20, 30).getMinute()|20|
| LocalTime.of(10, 20, 30).withHour(11).withMinute(22).withSecond(33).withNano(44)| 11:22:33.000000044|
| LocalTime.of(10, 20, 30).minusHours(1).minusMinutes(1).minusSeconds(1).minusNanos(1)| 09:19:28.999999999|
| LocalTime.of(10, 20, 30).plusHours(1).plusMinutes(1).plusSeconds(1).plusNanos(1)| 11:21:31.000000001|

### LocalDateTime
LocalDateとLocalTimeを内部で持っていて、
__タイムゾーンなし日付時間__(`yyyy-mm-dd HH:mm:ss.SSSSSSSSS`)を表現する不変＆スレッドセーフクラスです。

```java:LocalDataTime.java
/**
 * The date part.
 */
private final LocalDate date;
/**
 * The time part.
 */
private final LocalTime time;
```

| インスタンス取得| toString()| 
|:---|:---| 
| LocalDate.now() |2017-11-14T12:45:41.756|
| LocalDate.now(Clock.systemUTC()) |2017-11-14T03:45:41.756|
| LocalDate.now(ZoneId.of("Europe/Paris")) |2017-11-14T04:45:41.834|
| LocalDateTime.of(2010, 10, 1, 10, 20, 30, 123456789) |2010-10-01T10:20:30.123456789|
| ZonedDateTime.parse("2010-10-01T10:20:30.123456789") |2010-10-01T10:20:30.123456789|

| 常用メソッド| toString()| 
|:---|:---| 
|LocalDateTime.of(2010, 10, 1, 10, 20, 30).getYear() |2010|
|LocalDateTime.of(2010, 10, 1, 10, 20, 30).getMonth() |OCTOBER|
|LocalDateTime.of(2010, 10, 1, 10, 20, 30).getDayOfMonth() |1|
|LocalDateTime.of(2010, 10, 1, 10, 20, 30).getDayOfYear() |274|
|LocalDateTime.of(2010, 10, 1, 10, 20, 30).getHour()  |10|
|LocalDateTime.of(2010, 10, 1, 10, 20, 30).getMinute() |20|
|LocalDateTime.of(2010, 10, 1, 10, 20, 30).getSecond() |30|
|LocalDateTime.of(2010, 10, 1, 10, 20, 30).plusYears(1)  |2011-10-01T10:20:30|
|LocalDateTime.of(2010, 10, 1, 10, 20, 30).minusYears(1) |2009-10-01T10:20:30|

### ZoneDateTime
__タイムゾーン付き__(`HH:mm:ss.SSSSSSSSS`)を表現する不変＆スレッドセーフクラスです。
基本的な使い方は、LocalTimeDateと変わらないようです。

| インスタンス取得| toString()| 
|:---|:---| 
| ZonedDateTime.now() |2017-11-14T12:53:12.536+09:00[Asia/Tokyo]|
| ZonedDateTime.now(Clock.systemUTC()) |2017-11-14T03:53:12.536Z|
| ZonedDateTime.now(ZoneId.of("Europe/Paris")) |2017-11-14T04:53:12.598+01:00[Europe/Paris]|
| ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("Asia/Shanghai")) |2017-11-14T12:53:12.614+08:00[Asia/Shanghai]|
| ZonedDateTime.of(2010, 10, 1, 10, 20,30, 999, ZoneId.of("Asia/Tokyo")) |2010-10-01T10:20:30.000000999+09:00[Asia/Tokyo]|
| ZonedDateTime.parse("2010-10-01T10:20:30.000000999+09:00[Asia/Tokyo]") |2010-10-01T10:20:30.000000999+09:00[Asia/Tokyo]|

| 常用メソッド| toString()| 
|:---|:---| 
|ZonedDateTime.of(2010, 10, 1, 10, 20, 30, 999, ZoneId.of("Asia/Tokyo")).getYear() |2010|
|ZonedDateTime.of(2010, 10, 1, 10, 20, 30, 999, ZoneId.of("Asia/Tokyo")).getMonth() |OCTOBER|
|ZonedDateTime.of(2010, 10, 1, 10, 20, 30, 999, ZoneId.of("Asia/Tokyo")).getDayOfMonth() |1|
|ZonedDateTime.of(2010, 10, 1, 10, 20, 30, 999, ZoneId.of("Asia/Tokyo")).getDayOfYear() |274|
|ZonedDateTime.of(2010, 10, 1, 10, 20, 30, 999, ZoneId.of("Asia/Tokyo")).getHour()  |10|
|ZonedDateTime.of(2010, 10, 1, 10, 20, 30, 999, ZoneId.of("Asia/Tokyo")).getMinute() |20|
|ZonedDateTime.of(2010, 10, 1, 10, 20, 30, 999, ZoneId.of("Asia/Tokyo")).getSecond() |30|
|ZonedDateTime.of(2010, 10, 1, 10, 20, 30, 999, ZoneId.of("Asia/Tokyo")).plusYears(1)  |2011-10-01T10:20:30.000000999+09:00[Asia/Tokyo]|
|ZonedDateTime.of(2010, 10, 1, 10, 20, 30, 999, ZoneId.of("Asia/Tokyo")).minusYears(1) |2009-10-01T10:20:30.000000999+09:00[Asia/Tokyo]|

### OffsetDateTime
LocalDateTimeとOffsetを組み合わせたものです。

https://docs.oracle.com/javase/jp/8/docs/api/java/time/OffsetDateTime.html
「OffsetDateTime、ZonedDateTime、およびInstantはすべて、時系列上のインスタントをナノ秒の精度まで格納します。Instantはもっとも単純で、単にインスタントを表します。OffsetDateTimeは、UTC/グリニッジからのオフセットをインスタントに加算して、ローカル日付/時間を取得できるようにします。ZonedDateTimeは完全なタイムゾーン・ルールを追加します。」

```java:OffsetDateTime.java
/**
 * The local date-time.
 */
private final LocalDateTime dateTime;
/**
 * The offset from UTC/Greenwich.
 */
private final ZoneOffset offset;
```

### YearMonth、MonthDay

YearMonth : `yyyy-mm`を表現する不変＆スレッドセーフクラスです。
MonthDay : `mm-dd`を表現する不変＆スレッドセーフクラスです。

| YearMonth インスタンス取得| toString()| 
|:---|:---| 
| YearMonth.now() |2017-11|
| YearMonth.now(Clock.systemUTC()) |2017-11|
| YearMonth.now(ZoneId.of("Europe/Paris")) |2017-11|
| YearMonth.of(2011, 10)  |2011-10|
| YearMonth.parse("2012-10")|2012-10|

| YearMonth 常用メソッド| toString()| 
|:---|:---| 
| YearMonth.of(2011, 10).getYear() |2011|
| YearMonth.of(2011, 10).getMonth() |OCTOBER|
| YearMonth.of(2011, 10).plusMonths(2) |2011-12|
| YearMonth.of(2011, 10).minusYears(3) |2008-10|

| MonthDay インスタンス取得| toString()| 
|:---|:---| 
| MonthDay.now() |--11-14|
| MonthDay.now(Clock.systemUTC()) |--11-14|
| MonthDay.now(ZoneId.of("Europe/Paris")) |--11-14|
| MonthDay.of(5, 10)  |--05-10|
| MonthDay.parse("--05-10") |--05-10|

| MonthDay 常用メソッド| toString()| 
|:---|:---| 
| MonthDay.of(5, 10).getMonth() |MAY|
| MonthDay.of(5, 10).getDayOfMonth()  |10|
| MonthDay.of(5, 10).with(Month.JANUARY).withDayOfMonth(20) |--01-20|

### Year
Year : `yyyy`を表現する不変＆スレッドセーフクラスです。

| インスタンス取得| toString()| 
|:---|:---| 
| Year.now() |2017|
| Year.now(Clock.systemUTC()) |2017|
| Year.now(ZoneId.of("Europe/Paris")) |2017|
| Year.of(2011)  |2011|
| Year.parse("2012")|2012|

| 常用メソッド| toString()| 
|:---|:---| 
| Year.of(2011).getValue() |2011|
| Year.of(2011).plusYears(3) |2014|
| Year.of(2011).minusYears(10) |2001|

### Month、DayOfWeek
Month、月を表現する列挙体
DayOfWeek、曜日を表す列挙体

| Monthインスタンス取得| toString()| 
|:---|:---| 
| Month.of(10)  |OCTOBER|
| Month.valueOf("JANUARY") |JANUARY|
| Month.FEBRUARY | FEBRUARY|

| Month常用メソッド| toString()| 
|:---|:---| 
| Month.of(1).getValue() |1|
| Month.of(12).plus(3) |MARCH|
| Month.of(3).minus(4)  |NOVEMBER|

| DayOfWeekインスタンス取得| toString()| 
|:---|:---| 
| DayOfWeek.of(1)  |MONDAY|
| DayOfWeek.valueOf("FRIDAY") |FRIDAY|
| DayOfWeek.FRIDAY | FRIDAY|

| DayOfWeek常用メソッド| toString()| 
|:---|:---| 
| DayOfWeek.of(1).getValue() |1|
| DayOfWeek.of(1).plus(7) |MONDAY|
| DayOfWeek.of(1).minus(7) |MONDAY|

## Clock
__タイムゾーン付システム時刻__を表現するクラスです。
日付時間クラスのnow()は、このClockを元に生成します。

### Clock取得
```デフォルトタイムゾーン(日本)時計
Clock clockDefault = Clock.systemDefaultZone();  
```
![defalut-clock-1.gif](https://qiita-image-store.s3.amazonaws.com/0/104977/5f40a9c0-2007-d389-777d-bdbf3d204079.gif)


```java:UTC時計
Clock clockUTC = Clock.systemUTC();  
```
![UTC-Clock2.gif](https://qiita-image-store.s3.amazonaws.com/0/104977/bdd30511-f66f-46fb-10ed-8edf93ba8337.gif)

```java:タイムゾーン指定時計
Clock clockParis= Clock.system(ZoneId.of("Europe/Paris"));
```

![clock-paris.gif](https://qiita-image-store.s3.amazonaws.com/0/104977/c3b555b4-3955-2a25-2e3b-c96f1a86279e.gif)

### Clockは時計なので、時間は進みます
※gifで取得した理由

```java:時間は進む
Clock clock = Clock.systemDefaultZone();
System.out.println(clock.instant());
Thread.sleep(1000 * 2);
System.out.println(clock.instant());
```
```
2017-11-13T11:41:27.548Z
2017-11-13T11:41:29.551Z
```

### 特殊な時計取得
```java:止まっている時計
Clock fixedClock = Clock.fixed(Instant.now(), ZoneId.of("Asia/Tokyo"));
System.out.println("fixed clock : " + fixedClock.instant());
Thread.sleep(1000 * 2);
System.out.println("fixed clock : " + fixedClock.instant());
```
```text:結果
fixed clock : 2017-11-13T11:46:01.224Z
fixed clock : 2017-11-13T11:46:01.224Z
```
__⇒ 時計が進みません。__
※__テスト時刻を止まっている時計を活用してＵＴを行うとよいそうです。__

```java:秒時計
Clock secondsTickClock = Clock.tickSeconds(ZoneId.of("Asia/Tokyo"));
System.out.println("seconds tick clock : " + secondsTickClock.instant());
Thread.sleep(1000 * 2);
System.out.println("seconds tick clock : " + secondsTickClock.instant());
```
```text:結果
seconds tick clock : 2017-11-13T11:52:20Z
seconds tick clock : 2017-11-13T11:52:22Z
```
__⇒ 秒刻みで、秒以下は保持しない__

```java:分時計
Clock minutesTickClock = Clock.tickMinutes(ZoneId.of("Asia/Tokyo"));
System.out.println("minutes tick clock : " + minutesTickClock.instant());
Thread.sleep(1000 * 2);
System.out.println("minutes tick clock : " + minutesTickClock.instant());
```
```text:結果
minutes tick clock : 2017-11-13T11:52:00Z
minutes tick clock : 2017-11-13T11:52:00Z
```
__⇒ 分刻みで、秒以下は保持しない__


```java:指定時間量分進んだ時計
Clock nowClock = Clock.systemDefaultZone();
Clock offsetClock = Clock.offset(nowClock, Duration.ofDays(1));
System.out.println("nowClock : " + nowClock.instant());
System.out.println("offsetClock : " + offsetClock.instant());
```
```text:結果
nowClock : 2017-11-13T11:58:25.647Z
offsetClock : 2017-11-14T11:58:25.647Z
```
__⇒ 1日進んだ時計__

## TemporalAmount
### Duration
時間量を表現する不変＆スレッドセーフクラスです。
※ 単位はSeconds, Nanos

| インスタンス取得| 結果| 
|:---|:---| 
| Duration.ofDays(2) | PT48H|
| Duration.ofHours(3) | PT3H|
| Duration.ofMinutes(40) | PT40M|
| Duration.parse("PT15M") | PT15M|

| 常用メソッド| 結果| 
|:---|:---| 
| Duration.ofDays(3).getUnits() | [Seconds, Nanos]|
| Duration.ofDays(3).toHours() | 72|
| Duration.ofDays(3).toMinutes() | 4320|
| DDuration.ofDays(3).toMillis() | 259200000|
| Duration.ofDays(3).plusDays(1) | PT96H|
| Duration.ofDays(3).plusDays(-1) | PT48H|

### Period
時間量を表現する不変＆スレッドセーフクラスです。
※ 単位はYears, Months, Days

| インスタンス取得| 結果| 
|:---|:---| 
| Period.ofDays(2)| P2D|
| Period.ofMonths(3) | P3M|
| Period.ofYears(4) | P4Y|
| Period.parse("P4Y") | P4Y|

| 常用メソッド| 結果| 
|:---|:---| 
| Period.ofYears(3).getDays() | 0|
| Period.ofYears(3).getMonths() | 0|
| Period.ofYears(3).getYears() | 3|
| Period.ofYears(3).getUnits() | [Years, Months, Days]|
| Period.ofDays(3).plusDays(1) | P4D|
| Period.ofDays(3).minusDays(1) | P2D|

## ZoneId
時間帯を表現するクラス

```java:
ZoneId.systemDefault();
ZoneId.getAvailableZoneIds();
ZoneId.of("Asia/Tokyo");
```

## 日付時間クラス間の変換

|変換メソッド|変換後クラス|
|---|---|
| MonthDay.of(10, 1).atYear(2015) |java.time.LocalDate|
| YearMonth.of(2015, 10).atDay(30) |java.time.LocalDate|
| YearMonth.of(2015, 10).atEndOfMonth() |java.time.LocalDate|
| LocalTime.now().atDate(LocalDate.now()) |2017-11-14T14:41:28.728|
| LocalDate.now().atTime(10, 20) |java.time.LocalDateTime|
| LocalDate.now().atStartOfDay() |java.time.LocalDateTime|
| LocalDate.now().atStartOfDay(ZoneId.of("Asia/Shanghai")) |java.time.ZonedDateTime|
| LocalDateTime.now().atZone(ZoneId.of("Asia/Shanghai")) |java.time.ZonedDateTime|
| LocalDateTime.now().toLocalDate() |java.time.LocalDate|
| LocalDateTime.now().toLocalTime() |java.time.LocalTime|
| LocalDateTime.now().toInstant(ZoneOffset.UTC) |java.time.Instant|
| ZonedDateTime.now().toLocalDateTime() |java.time.LocalDateTime|
| ZonedDateTime.now().toLocalDate() |java.time.LocalDate|
| ZonedDateTime.now().toInstant() |java.time.Instant|
| Instant.now().atZone(ZoneId.of("Asia/Shanghai")) |java.time.ZonedDateTime|
| Instant.now().atOffset(ZoneOffset.UTC)|java.time.OffsetDateTime|

# 日付時間フォーマット

## DateFormat
jdk1.0??から提供されていて、下記二つの要素でフォーマットを制御している。
1. LONG,FULL,MEDIUM.SHORT
2. Locale

もう使わないだろう？！

| インスタンス生成＆format&parse| toString()| 
|:---|:---| 
| DateFormat.getDateInstance(DateFormat.FULL, Locale.JAPAN).format(new Date())  | 2017年11月14日|
| DateFormat.getTimeInstance(DateFormat.FULL, Locale.US).format(new Date()) | 4:56:05 PM JST|
| DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, Locale.CHINA).format(new Date())  | 2017-11-14 下午4:56|
| DateFormat.getDateInstance(DateFormat.FULL, Locale.JAPAN).parse("2017年11月14日")  | Tue Nov 14 00:00:00 JST 2017|
| DateFormat.getTimeInstance(DateFormat.FULL, Locale.US).parse("4:52:25 PM JST") | Thu Jan 01 16:52:25 JST 1970|
| DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, Locale.CHINA).parse("2017-11-14 下午4:52")  | Tue Nov 14 16:52:00 JST 2017|

## SimpleDateFormat
馴染み深い日付フォーマッタですね！！
DateFormmatのサブクラスで、pattern文字列でフォーマットを決める。

| インスタンス生成＆format&parse| toString()| 
|:---|:---| 
| new SimpleDateFormat("yyyy-MM-dd").format(new Date())  | 2017-11-14|
| new SimpleDateFormat("yyyy年MM月dd HH時mm分ss秒だよ").format(new Date()) | 2017年11月14 17時24分11秒だよ|
| new SimpleDateFormat("yyyy-MM-dd").parse("2017-11-14")  | Tue Nov 14 00:00:00 JST 2017|

```java:タイムゾーンを設定できる
SimpleDateFormat s1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
SimpleDateFormat s2 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
s2.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
System.out.println(s1.format(new Date()));
System.out.println(s2.format(new Date()));
```
```text:出力
2017/11/14 17:26:53
2017/11/14 16:26:53
```

## DateTimeFormatter
JKD1.8から日付時間クラスと一緒に追加されたものです。
`java.time.format`パッケージに入っており、DateFormatとSimpleDateFormatを合体したようなもの？

```java:format
DateTimeFormatter[] formatters = {
    DateTimeFormatter.ISO_DATE,
    DateTimeFormatter.ISO_LOCAL_DATE,
    DateTimeFormatter.ISO_LOCAL_DATE_TIME,
    DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.MEDIUM),
    DateTimeFormatter.ofPattern("Gyyyy/MM/dd HH::mm:ss.SSS")
};
LocalDateTime localDateTime = LocalDateTime.now();
Arrays.stream(formatters)
    .forEach(
        formatter ->
            System.out.println(formatter.format(localDateTime))
    );
Arrays.stream(formatters)
    .forEach(
        formatter ->
            System.out.println(localDateTime.format(formatter))
    );
```

```java:parse
 // 日付時刻#parse
 LocalDate.parse("2015/10/10", DateTimeFormatter.ofPattern("yyyy/MM/dd"));

 // DateTimeFormatter#parse
 DateTimeFormatter.ofPattern("yyyy/MM/dd").parse("2015/10/10");
 DateTimeFormatter.ofPattern("yyyy/MM/dd").parse("2015/10/10", TemporalQueries.localDate());
```
可読性の観点からは`日付時刻#parse`が推奨されてます。