====== Java 8 Date & Time ======
* [[java:dateformat|Java DateFormat]]
* [[http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html|Java SE 8 Date and Time]]
* [[http://www.mkyong.com/java8/java-8-convert-date-to-localdate-and-localdatetime/|Java 8 – Convert Date to LocalDate and LocalDateTime]]
* [[https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_LOCAL_DATE_TIME|DateTimeFormatter#ISO_LOCAL_DATE_TIME]] : LocalDateTime ISO 8601 표준 포맷터 ''2011-12-03T10:15:30''
* [[https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_OFFSET_DATE_TIME|DateTimeFormatter#ISO_OFFSET_DATE_TIME]] : Offset DateTime ISO 8601 표준 포맷터 ''2011-12-03T10:15:30+01:00''
===== java.util.Date <-> LocalDate/LocalDateTime/Instant간 변환 =====
* [[http://stackoverflow.com/questions/21242110/convert-java-util-date-to-java-time-localdate|datetime - Convert java.util.Date to java.time.LocalDate]]
/**
* Calls {@link #asLocalDate(Date, ZoneId)} with the system default time zone.
*/
public static LocalDate asLocalDate(java.util.Date date) {
return asLocalDate(date, ZoneId.systemDefault());
}
/**
* Creates {@link LocalDate} from {@code java.util.Date} or it's subclasses. Null-safe.
*/
public static LocalDate asLocalDate(java.util.Date date, ZoneId zone) {
if (date == null) {
return null;
}
if (date instanceof java.sql.Date) {
return ((java.sql.Date) date).toLocalDate();
} else {
return Instant.ofEpochMilli(date.getTime()).atZone(zone).toLocalDate();
}
}
/**
* Calls {@link #asLocalDateTime(Date, ZoneId)} with the system default time zone.
*/
public static LocalDateTime asLocalDateTime(java.util.Date date) {
return asLocalDateTime(date, ZoneId.systemDefault());
}
/**
* Creates {@link LocalDateTime} from {@code java.util.Date} or it's subclasses. Null-safe.
*/
public static LocalDateTime asLocalDateTime(java.util.Date date, ZoneId zone) {
if (date == null) {
return null;
}
if (date instanceof java.sql.Timestamp) {
return ((java.sql.Timestamp) date).toLocalDateTime();
} else {
return Instant.ofEpochMilli(date.getTime()).atZone(zone).toLocalDateTime();
}
}
/**
* Calls {@link #asUtilDate(Object, ZoneId)} with the system default time zone.
*/
public static java.util.Date asUtilDate(Object date) {
return asUtilDate(date, ZoneId.systemDefault());
}
/**
* Creates a {@link java.util.Date} from various date objects. Is null-safe. Currently supports:
* - {@link java.util.Date}
*
- {@link java.sql.Date}
*
- {@link java.sql.Timestamp}
*
- {@link java.time.LocalDate}
*
- {@link java.time.LocalDateTime}
*
- {@link java.time.ZonedDateTime}
*
- {@link java.time.Instant}
*
*
* @param zone Time zone, used only if the input object is LocalDate or LocalDateTime.
*
* @return {@link java.util.Date} (exactly this class, not a subclass, such as java.sql.Date)
*/
public static java.util.Date asUtilDate(Object date, ZoneId zone) {
if (date == null) {
return null;
}
if (date instanceof java.sql.Date || date instanceof java.sql.Timestamp) {
return new java.util.Date(((java.util.Date) date).getTime());
}
if (date instanceof java.util.Date) {
return (java.util.Date) date;
}
if (date instanceof LocalDate) {
return Date.from(((LocalDate) date).atStartOfDay(zone).toInstant());
}
if (date instanceof LocalDateTime) {
return Date.from(((LocalDateTime) date).atZone(zone).toInstant());
}
if (date instanceof ZonedDateTime) {
return Date.from(((ZonedDateTime) date).toInstant());
}
if (date instanceof Instant) {
return Date.from((Instant) date);
}
throw new UnsupportedOperationException("Don't know hot to convert " + date.getClass().getName() + " to java.util.Date");
}
/**
* Creates an {@link Instant} from {@code java.util.Date} or it's subclasses. Null-safe.
*/
public static Instant asInstant(Date date) {
if (date == null) {
return null;
} else {
return Instant.ofEpochMilli(date.getTime());
}
}
/**
* Calls {@link #asZonedDateTime(Date, ZoneId)} with the system default time zone.
*/
public static ZonedDateTime asZonedDateTime(Date date) {
return asZonedDateTime(date, ZoneId.systemDefault());
}
/**
* Creates {@link ZonedDateTime} from {@code java.util.Date} or it's subclasses. Null-safe.
*/
public static ZonedDateTime asZonedDateTime(Date date, ZoneId zone) {
if (date == null) {
return null;
} else {
return asInstant(date).atZone(zone);
}
}
===== Time Mocking for test =====
* refer to [[http://docs.oracle.com/javase/8/docs/api/java/time/Clock.html|java.time.Clock]]
* [[http://blog.freeside.co/2015/01/15/fixing-current-time-for-tests-with-java-8-s-date-time-api/|Ad-Hockery - Fixing current time for tests with Java 8's date/time API]]
* [[http://www.baeldung.com/java-override-system-time|Overriding System Time for Testing in Java | Baeldung]]
===== Duration 기반으로 흐른 시간 검사 =====
* [[https://adambien.blog/roller/abien/entry/beyond_system_currenttimemillis_measuring_time|Beyond System.currentTimeMillis: Measuring Time with Duration and Instant : Adam Bien's Weblog]]
var start = Instant.now();
Thread.sleep(2042);
var duration = Duration.between(start,Instant.now());
System.out.printf("%d seconds and %d ms",duration.toSeconds(),duration.toMillisPart());
===== systemDefaultTimeZone 과 LocalDateTime =====
* [[https://docs.oracle.com/javase/8/docs/api/java/time/Clock.html|java.time.Clock]]의 ''systemDefaultTimeZone()''은 ''System.currentTimeMilliss()''를 사용하기 때문에 nanosecond 부분은 모두 잘린다.
* 그리고 [[https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html|java.time.LocalDateTime]]의 ''now()'' 메소드는 ''systemDefaultTimeZone()'' clock을 사용하기 때문에 결과적으로 nanosecond 부분이 잘린다.
* 따라서, **''LocalDateTime.now()''를 여러차례 호출할때 nanosecond 의 시간차이만 날 뿐이라면 동일한 값이 반환될 수 있다.**
* 이로인해 Test 코드에서 ''LocalDateTime.now()''를 두번 연속 호출하고서 두 값이 서로 다를것이라는 예상으로 (''firstNow.isBefore(secondNow) == true'') 작성한 코드는 상황에 따라 틀려지게 된다.