JDK1.8前の日付時間クラス
Date
jdk1.0から提供されている日付時間クラスで、エポックからのミリ秒ヲ保持している。
「GMT 1970年1月1日 0時0分0秒からの現在に至るミリ秒」
Y2k問題や性能面の問題があるので、メソッドは殆ど非推奨(@Deprecated)されていている。
生き残っているコントラクターとメソッド
// 生成
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問題
y2k問題
System.out.println(new Date(10, 1, 1));
⇒ 1910年1月1日になってしまう。
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[];
- 抽象クラスであり、(多分)Tmeplate Methodパターンで実装されており、
サブクラスを実装することで世界各地で使うカレンダーの差異を吸収している。
例:和暦、旧暦
Calendar のコアAPI
API |
概要 |
Calendar |
カレンダーの(抽象)親クラス |
TimeZone |
時間帯を表す |
Locale |
地域を表して、これによって生成されるCalendarが異なる |
Caldendar生成
表示用
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) + "秒");
}
生成
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);
出力
生成されたカレンダー : 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秒
- GregorianCalendar、デフォルト地域で生成される
- JapaneseImperialCalendar、地域を日本にすることで生成される
Calendar <=> Date
Calendar,Date変換
// Date to Calendar
Calendar.getInstance().setTime(new Date());
// Calendar to Date
Calendar.getInstance().getTime();
add()とroll()の違い
add()とroll()両方指定フィールド(年月日時分秒ミリ秒)を増減するためのものだが、
|
上位 |
下位 |
add() |
上位を変更する |
最小変更にする |
roll() |
上位を変更しない |
最小変更にする |
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
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(寛大さ)&遅延
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()));
出力
2016/05/02
Exception in thread "main" java.lang.IllegalArgumentException: MONTH
- Lenientのデフォルトはtrueなので、
2015/15/32 -> 2016/05/02
を容認する
- Lenient=falaseで、月=15を容認しないから
-
例外はsetではなく、get()で発生する。
set()は遅延されて、無駄な計算が行われなくするため。
JDK1.8の日付時間クラス
本題!!
JKD1.8からjava.timeパッケージ
に日付時間のクラスが数多く追加されている。
コアAPI
コアAPI
日付時間のコアAPI |
概要 |
TemporalAccessor |
日付、時間、オフセット、またはそれらのなんらかの組合せなどへの読取り専用アクセスを定義したインタフェースです。 |
Temporal |
日付、時間、オフセット、またはそれらのなんらかの組合せなどへの読取/書込アクセスを定義したインタフェースです。 |
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 |
- TemporalAccessorを実装したLocalDateで
インスタンス
を取得してます。
- TemporalFieldを実装した
ChronoField
で使って年フィールド
を取得します。
- 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 |
- TemporalAmountを実装した
Period
で加算、減算してます。
- TemporalUnitを実装した
ChronoUnit
で加算、減算してます。
- TemporalFieldを実装した
ChronoField
で年フィールド
を調整してます。
- 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 |
- TemporalAmountを実装した
Duration
でインスタンス
取得してます。
- 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
例:年末まで何日残っているか?
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は色んなアクセス戦略を提供します。
例:オブジェクトの精度はなんだ?
LocalDate.of(2015, 10, 3).query(TemporalQueries.precision())
日付時間の実装
Instant
- エポック秒(1970-01-01T00:00:00Zから経過時間)を表現する不変&スレッドセーフクラス。
- ナノ秒まで保持する。
- 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
)を表現する不変&スレッドセーフクラスです。
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は完全なタイムゾーン・ルールを追加します。」
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();
UTC時計
Clock clockUTC = Clock.systemUTC();
タイムゾーン指定時計
Clock clockParis= Clock.system(ZoneId.of("Europe/Paris"));
Clockは時計なので、時間は進みます
※gifで取得した理由
時間は進む
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
特殊な時計取得
止まっている時計
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());
結果
fixed clock : 2017-11-13T11:46:01.224Z
fixed clock : 2017-11-13T11:46:01.224Z
⇒ 時計が進みません。
※テスト時刻を止まっている時計を活用してUTを行うとよいそうです。
秒時計
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());
結果
seconds tick clock : 2017-11-13T11:52:20Z
seconds tick clock : 2017-11-13T11:52:22Z
⇒ 秒刻みで、秒以下は保持しない
分時計
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());
結果
minutes tick clock : 2017-11-13T11:52:00Z
minutes tick clock : 2017-11-13T11:52:00Z
⇒ 分刻みで、秒以下は保持しない
指定時間量分進んだ時計
Clock nowClock = Clock.systemDefaultZone();
Clock offsetClock = Clock.offset(nowClock, Duration.ofDays(1));
System.out.println("nowClock : " + nowClock.instant());
System.out.println("offsetClock : " + offsetClock.instant());
結果
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
時間帯を表現するクラス
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 |
タイムゾーンを設定できる
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()));
出力
2017/11/14 17:26:53
2017/11/14 16:26:53
DateTimeFormatter
JKD1.8から日付時間クラスと一緒に追加されたものです。
java.time.format
パッケージに入っており、DateFormatとSimpleDateFormatを合体したようなもの?
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))
);
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
が推奨されてます。