62
Java 8: Date Time API Ganesh Samarthyam [email protected] h

Java 8 Date and Time API

Embed Size (px)

Citation preview

Page 1: Java 8 Date and Time API

Java 8: Date Time API

Ganesh [email protected]

Page 2: Java 8 Date and Time API

–Craig Larman

"The critical design tool for software development is a mind well educated in design principles"

Page 3: Java 8 Date and Time API

Design Smells: Example

Page 4: Java 8 Date and Time API

Discussion Example

// using java.util.Date Date today = new Date(); System.out.println(today);

$ java DateUse Wed Dec 02 17:17:08 IST 2015

Why should we get the time and timezone details if I only want a date? Can

I get rid of these parts? No!

Page 5: Java 8 Date and Time API

So What?!Date today = new Date(); System.out.println(today); Date todayAgain = new Date(); System.out.println(todayAgain);

System.out.println(today.compareTo(todayAgain) == 0);

Thu Mar 17 13:21:55 IST 2016 Thu Mar 17 13:21:55 IST 2016 false

What is going on here?

Page 6: Java 8 Date and Time API

Joda API

JSR 310: Java Date and Time API

Stephen Colebourne

Page 7: Java 8 Date and Time API

Refactoring for Date

Replace inheritance with delegation

Page 8: Java 8 Date and Time API

java.time package!

Date, Calendar, and TimeZone Java 8 replaces these types

Page 9: Java 8 Date and Time API

Refactored SolutionLocalDate today = LocalDate.now(); System.out.println(today); LocalDate todayAgain = LocalDate.now(); System.out.println(todayAgain); System.out.println(today.compareTo(todayAgain) == 0);

2016-03-17 2016-03-17 true

Works fine now!

Page 10: Java 8 Date and Time API

Refactored Example … You can use only date, time, or even timezone, and combine them as

needed!

LocalDate today = LocalDate.now(); System.out.println(today); LocalTime now = LocalTime.now(); System.out.println(now);

ZoneId id = ZoneId.of("Asia/Tokyo"); System.out.println(id);

LocalDateTime todayAndNow = LocalDateTime.now(); System.out.println(todayAndNow);

ZonedDateTime todayAndNowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo")); System.out.println(todayAndNowInTokyo);

2016-03-17 13:28:06.927 Asia/Tokyo 2016-03-17T13:28:06.928 2016-03-17T16:58:06.929+09:00[Asia/Tokyo]

Page 11: Java 8 Date and Time API

“Fluent interfaces”

❖ Code is more readable and easier to use:

❖ Classes in this package have numerous static methods (many of them factory methods)

❖ Methods in the classes follow a common naming convention (for example, they use the prefixes plus and minus to add or subtract date or time values)

Page 12: Java 8 Date and Time API

java.time Sub-packages

❖ java.time.temporal —Accesses date/time fields and units

❖ java.time.format —Formats the input and output of date/time objects

❖ java.time.zone —Handles time zones

❖ java.time.chrono —Supports calendar systems such as Japanese and Thai calendars

Page 13: Java 8 Date and Time API

ISO-8601 Calendar System Format

❖ The Java 8 date and time API uses ISO 8601 as the default calendar format.

❖ In this internationally accepted format, the date and time values are sorted from the largest to the smallest unit of time: year, month/week, day, hour, minute, second, and millisecond/nanosecond.

❖ Example: LocalDate is represented in the in a year-month-day format (YYYY-MM-DD), as in, 2015-10-26.

Page 14: Java 8 Date and Time API

java.time.LocalDate

LocalDate newYear2016 = LocalDate.of(2016, 1, 1); System.out.println("New year 2016: " + newYear2016);

New year 2016: 2016-01-01

Page 15: Java 8 Date and Time API

java.time.LocalDate

LocalDate valentinesDay = LocalDate.of(2016, 14, 2); System.out.println("Valentine's day is on: " + valentinesDay);

Exception in thread "main" java.time.DateTimeException: Invalid value

for MonthOfYear(valid values 1 - 12): 14

Page 16: Java 8 Date and Time API

java.time.LocalDate

long visaValidityDays = 180L; LocalDate currDate = LocalDate.now(); System.out.println("My Visa expires on: " + currDate.plusDays(visaValidityDays));

My Visa expires on: 2016-04-23

Page 17: Java 8 Date and Time API

Important Methods in LocalDate

Page 18: Java 8 Date and Time API

java.time.LocalTime

LocalTime currTime = LocalTime.now(); System.out.println("Current time is: " + currTime);

Current time is: 12:23:05.072

Page 19: Java 8 Date and Time API

java.time.LocalTime

System.out.println(LocalTime.of(18,30));

prints: 18:30

Page 20: Java 8 Date and Time API

java.time.LocalTime

long hours = 6; long minutes = 30; LocalTime currTime = LocalTime.now(); System.out.println("Current time is: " + currTime); System.out.println("My meeting is at: " + currTime.plusHours(hours).plusMinutes(minutes));

Current time is: 12:29:13.624My meeting is at: 18:59:13.624

Page 21: Java 8 Date and Time API

Important Methods in LocalTime

Page 22: Java 8 Date and Time API

java.time.LocalDateTime

LocalDateTime currDateTime = LocalDateTime.now(); System.out.println("Today's date and current time is: " + currDateTime);

Today's date and current time is: 2015-10-29T21:04:36.376

Page 23: Java 8 Date and Time API

java.time.LocalDateTime

LocalDateTime christmas = LocalDateTime.of(2015, 12, 25, 0, 0); LocalDateTime newYear = LocalDateTime.of(2016, 1, 1, 0, 0); System.out.println("New Year 2016 comes after Christmas 2015”

+ newYear.isAfter(christmas));

New Year 2016 comes after Christmas 2015? true

Page 24: Java 8 Date and Time API

java.time.LocalDateTime

LocalDateTime dateTime = LocalDateTime.now(); System.out.println("Today's date and current time: " + dateTime); System.out.println("The date component is: " + dateTime.toLocalDate()); System.out.println("The time component is: " + dateTime.toLocalTime());

Today's date and current time: 2015-11-04T13:19:10.497

The date component is: 2015-11-04The time component is: 13:19:10.497

Page 25: Java 8 Date and Time API

java.time.Instant

import java.time.Instant;

public class UsingInstant { public static void main(String args[]){

// prints the current timestamp with UTC as time zone Instant currTimeStamp = Instant.now(); System.out.println("Instant timestamp is: "+ currTimeStamp); // prints the number of seconds as Unix timestamp from epoch time System.out.println("Number of seconds elapsed: " + currTimeStamp.getEpochSecond()); // prints the Unix timestamp in milliseconds System.out.println("Number of milliseconds elapsed: " + currTimeStamp.toEpochMilli());

} }

Instant timestamp is: 2015-11-02T03:16:04.502ZNumber of seconds elapsed: 1446434164

Number of milliseconds elapsed: 1446434164502

Page 26: Java 8 Date and Time API

java.time.Period

LocalDate manufacturingDate = LocalDate.of(2016, Month.JANUARY, 1); LocalDate expiryDate = LocalDate.of(2018, Month.JULY, 18); Period expiry = Period.between(manufacturingDate, expiryDate); System.out.printf("Medicine will expire in: %d years, %d months, and %d days (%s)\n", expiry.getYears(), expiry.getMonths(), expiry.getDays(), expiry);

Medicine will expire in: 2 years, 6 months, and 17 days (P2Y6M17D)

Page 27: Java 8 Date and Time API

Important Methods in Period

Page 28: Java 8 Date and Time API

The Java 8 date and time API differentiates how humans and computers use date- and time-related information.

For example, the Instant class represents a Unix timestamp and internally uses long and int variables.

Instant values are not very readable or usable by humans because the class does not support methods

related to day, month, hours, and so on (in contrast, the Period class supports such methods).

Page 29: Java 8 Date and Time API

java.time.Duration

LocalDateTime comingMidnight = LocalDateTime.of(LocalDate.now().plusDays(1), LocalTime.MIDNIGHT);

LocalDateTime now = LocalDateTime.now(); Duration between = Duration.between(now, comingMidnight); System.out.println(between);

PT7H13M42.003S

Page 30: Java 8 Date and Time API

Important Methods in Duration

Page 31: Java 8 Date and Time API

Summary of Instant, Period and Duration

Page 32: Java 8 Date and Time API

TemporalUnit

import java.time.temporal.ChronoUnit;

public class ChronoUnitValues { public static void main(String []args) {

System.out.println("ChronoUnit DateBased TimeBased Duration"); System.out.println("---------------------------------------"); for(ChronoUnit unit : ChronoUnit.values()) {

System.out.printf("%10s \t %b \t\t %b \t\t %s %n”, unit, unit.isDateBased(), unit.isTimeBased(), unit.getDuration());

} }

}

Page 33: Java 8 Date and Time API
Page 34: Java 8 Date and Time API

ZoneId

System.out.println("My zone id is: " + ZoneId.systemDefault());

My zone id is: Asia/Kolkata

ZoneId AsiaKolkataZoneId = ZoneId.of("Asia/Kolkata");

Page 35: Java 8 Date and Time API

ZonedDateTime

LocalDate currentDate = LocalDate.now(); LocalTime currentTime = LocalTime.now(); ZoneId myZone = ZoneId.systemDefault(); ZonedDateTime zonedDateTime = ZonedDateTime.of(currentDate, currentTime, myZone); System.out.println(zonedDateTime);

2015-11-05T11:38:40.647+05:30[Asia/Kolkata]

Page 36: Java 8 Date and Time API

ZonedDateTime

ZoneId myZone = ZoneId.of("Asia/Kolkata"); LocalDateTime dateTime = LocalDateTime.now(); ZonedDateTime zonedDateTime = dateTime.atZone(myZone); ZoneOffset zoneOffset = zonedDateTime.getOffset(); System.out.println(zoneOffset);

+05:30

Page 37: Java 8 Date and Time API

ZonedDateTimeZoneId singaporeZone = ZoneId.of(“Asia/Singapore"); ZonedDateTime dateTimeInSingapore =

ZonedDateTime.of(LocalDateTime.of(2016, Month.JANUARY, 1, 6, 0), singaporeZone);

ZoneId aucklandZone = ZoneId.of("Pacific/Auckland"); ZonedDateTime sameDateTimeInAuckland =

dateTimeInSingapore.withZoneSameInstant(aucklandZone);

Duration timeDifference = Duration.between( dateTimeInSingapore.toLocalTime(),

sameDateTimeInAuckland.toLocalTime());

System.out.printf("Time difference between %s and %s zones is %d hours”, singaporeZone, aucklandZone, timeDifference.toHours());

Time difference between Asia/Singapore and Pacific/Auckland zones is 5 hours

Page 38: Java 8 Date and Time API

Daylight Savings

ZoneId kolkataZone = ZoneId.of("Asia/Kolkata"); Duration kolkataDST = kolkataZone.getRules().getDaylightSavings(Instant.now()); System.out.printf("Kolkata zone DST is: %d hours %n", kolkataDST.toHours());

ZoneId aucklandZone = ZoneId.of("Pacific/Auckland"); Duration aucklandDST = aucklandZone.getRules().getDaylightSavings(Instant.now()); System.out.printf("Auckland zone DST is: %d hours", aucklandDST.toHours());

Kolkata zone DST is: 0 hoursAuckland zone DST is: 1 hours

Page 39: Java 8 Date and Time API

DateTimeFormatter

Predefined formatters: • ISO_DATE (2015-11-05) • ISO_TIME (11:25:47.624) • RFC_1123_DATE_TIME (Thu, 5 Nov 2015 11:27:22 +0530) • ISO_ZONED_DATE_TIME (2015-11-05T11:30:33.49+05:30[Asia/Kolkata])

Page 40: Java 8 Date and Time API

DateTimeFormatter

Wake up time: 06:00:00

LocalTime wakeupTime = LocalTime.of(6, 0, 0); System.out.println("Wake up time: " + DateTimeFormatter.ISO_TIME.format(wakeupTime));

01 Jan 2016

DateTimeFormatter customFormat = DateTimeFormatter.ofPattern("dd MMM yyyy"); System.out.println(customFormat.format(LocalDate.of(2016, Month.JANUARY, 01)));

Page 41: Java 8 Date and Time API

Uppercase and lowercase letters can have similar or different meanings when used in format strings fordates and times. Read the Javadoc for these patterns

carefully before trying to use these letters. For example,in dd-MM-yy, MM refers to month; however, in dd-mm-

yy, mm refers to minutes !

Page 42: Java 8 Date and Time API

Formatting Dates

• G (era: BC, AD) • y (year of era: 2015, 15) • Y (week-based year: 2015, 15) • M (month: 11, Nov, November) • w (week in year: 13) • W (week in month: 2) • E (day name in week: Sun, Sunday) • D (day of year: 256) • d (day of month: 13)

Page 43: Java 8 Date and Time API

Custom Date Patternspublic class CustomDatePatterns {

public static void main(String []args) { // patterns from simple to complex ones String [] dateTimeFormats = {

"dd-MM-yyyy", /* d is day (in month), M is month, y is year */ "d '('E')' MMM, YYYY", /*E is name of the day (in week), Y is year*/ "w'th week of' YYYY", /* w is the week of the year */ "EEEE, dd'th' MMMM, YYYY" /*E is day name in the week */

};

LocalDateTime now = LocalDateTime.now(); for(String dateTimeFormat : dateTimeFormats) {

System.out.printf("Pattern \"%s\" is %s %n", dateTimeFormat, DateTimeFormatter.ofPattern(dateTimeFormat).format(now));

} }

} Pattern "dd-MM-yyyy" is 05-11-2015Pattern "d '('E')' MMM, YYYY" is 5 (Thu) Nov, 2015Pattern "w'th week of' YYYY" is 45th week of 2015Pattern "EEEE, dd'th' MMMM, YYYY" is Thursday, 05th November, 2015

Page 44: Java 8 Date and Time API

Formatting Times

• a (marker for the text a.m./p.m. marker) • H (hour: value range 0–23) • k (hour: value range 1–24) • K (hour in a.m./p.m.: value range 0–11) • h (hour in a.m./p.m.: value range 1–12) • m (minute) • s (second) • S (fraction of a second) • z (time zone: general time-zone format)

Page 45: Java 8 Date and Time API

Custom Time Patternsclass CustomTimePatterns {

public static void main(String []args) { // patterns from simple to complex ones String [] timeFormats = {

"h:mm", /* h is hour in am/pm (1-12), m is minute */ "hh 'o''clock'", /* '' is the escape sequence to print a single quote */ "H:mm a", /* H is hour in day (0-23), a is am/pm*/ "hh:mm:ss:SS", /* s is seconds, S is milliseconds */ "K:mm:ss a" /* K is hour in am/pm(0-11) */

};

LocalTime now = LocalTime.now(); for(String timeFormat : timeFormats) {

System.out.printf("Time in pattern \"%s\" is %s %n", timeFormat, DateTimeFormatter.ofPattern(timeFormat).format(now));

} }

} Time in pattern "h:mm" is 12:27Time in pattern "hh 'o''clock'" is 12 o'clockTime in pattern "H:mm a" is 12:27 PMTime in pattern "hh:mm:ss:SS" is 12:27:10:41Time in pattern "K:mm:ss a" is 0:27:10 PM

Page 46: Java 8 Date and Time API

Flight Travel - Time Calculation - Example

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd MMM yyyy hh.mm a");

// Leaving on 1st Jan 2016, 6:00am from "Singapore" ZonedDateTime departure = ZonedDateTime.of(

LocalDateTime.of(2016, Month.JANUARY, 1, 6, 0), ZoneId.of("Asia/Singapore"));

System.out.println("Departure: " + dateTimeFormatter.format(departure));

// Arrival on the same day in 10 hours in "Auckland" ZonedDateTime arrival =

departure.withZoneSameInstant(ZoneId.of("Pacific/Auckland")).plusHours(10); System.out.println("Arrival: " + dateTimeFormatter.format(arrival));

Departure: 01 Jan 2016 06.00 AMArrival: 01 Jan 2016 09.00 PM

Page 47: Java 8 Date and Time API

Summary❖ The Java 8 date and time API uses ISO 8601 as the default calendar format.

❖ The java.time.LocalDate class represents a date without time or time zones; the java.time.LocalTime class represents time without dates and time zones; the java.time.LocalDateTime class represents both date and time without time zones.

❖ The java.time.Instant class represents a Unix timestamp.

❖ The java.time.Period is used to measure the amount of time in terms of years, months, and days.

❖ The java.time.Duration class represents time in terms of hours, minutes, seconds, and fraction of seconds.

Page 48: Java 8 Date and Time API

Summary❖ ZoneId identifies a time zone; ZoneOffset represents time zone offset

from UTC/Greenwich.

❖ ZonedDateTime provides support for all three aspects: date, time, and time zone.

❖ You have to account for daylight savings time (DST) when working with different time zones.

❖ The java.time.format.DateTimeFormatter class provides support for reading or printing date and time values in different formats.

❖ The DateTimeFormatter class provides predefined constants (such as ISO_DATE and ISO_TIME ) for formatting date and time values.

Page 49: Java 8 Date and Time API

Summary❖ You encode the format of the date or time using case-

sensitive letters to form a date or time pattern string with the DateTimeFormatter class.

❖ The enumeration java.time.temporal.ChronoUnit implements the java.time.temporal.TemporalUnit interface.

❖ Both TemporalUnit and ChronoUnit deal with time unit values such as seconds, minutes, and hours and date values such as days, months, and years.

Page 50: Java 8 Date and Time API

Quiz Question #1 Choose the correct option based on this code segment:

LocalDate babyDOB = LocalDate.of(2015, Month.FEBRUARY, 20);

LocalDate now = LocalDate.of(2016, Month.APRIL, 10);

System.out.println(Period.between(now, babyDOB).getYears()); // PERIOD_CALC

A. The code segment results in a compiler error in the line marked with the comment PERIOD_CALC

B. The code segment throws a DateTimeException

C. The code segment prints: 1

D. The code segment prints: -1

Page 51: Java 8 Date and Time API

Quiz Question #1 - Answer

The code segment prints: - 1

Here are the arguments to the between() method in the Period class:

Period between(LocalDate startDateInclusive, LocalDate endDateExclusive)

The first argument is the start and the second argument is the end, and hence the call Period.between(now, babyDOB) results in -1 (not +1).

Page 52: Java 8 Date and Time API

Quiz Question #2

Which one of the following classes is best suited for storing timestamp values of application events in a file?

A. java.time.ZoneId class

B. java.time.ZoneOffset class

C. java.time.Instant class

D. java.time.Duration class

E. java.time.Period class

Page 53: Java 8 Date and Time API

Quiz Question #2 - Answer

C . Instant class

The Instant class stores the number of seconds elapsed since the start of the Unix epoch (1970-01-01T00:00:00Z). The Instant class is suitable for storing a log of application events in a file as timestamp values.

The ZoneId and ZoneOffset classes are related to time zones and hence are unrelated to storing timestamp values. The Duration class is for time-based values in terms of quantity of time (such as seconds, minutes, and hours). The Period class is for date-based values such as years, months, and days.

Page 54: Java 8 Date and Time API

Quiz Question #3 Given this code segment:

ZoneId zoneId = ZoneId.of("Asia/Singapore");

ZonedDateTime zonedDateTime =

ZonedDateTime.of(LocalDateTime.now(), zoneId);

System.out.println(zonedDateTime.getOffset());

assume that the time-offset value for the Asia/Singapore time zone from UTC/Greenwich is +08:00. Choose the correct option.

A. This code segment results in throwing DateTimeException

B. This code segment results in throwing UnsupportedTemporalTypeException

C. The code segment prints: Asia/Singapore

D. The code segment prints: +08:00

E. This code segment prints: +08:00 [Asia/Singapore]

Page 55: Java 8 Date and Time API

Quiz Question #3 - Answer

D. The code segment prints: + 08:00

Given a ZonedDateTime object, the getOffset() method returns a ZoneOffset object that corresponds to the offset of the time zone from UTC/Greenwich. Given that the time-offset value for the Asia/Singapore zone from UTC/Greenwich is +08:00, the toString() method of ZoneOffset prints the string “+08:00” to the console.

Page 56: Java 8 Date and Time API

Quiz Question #4 Choose the correct option based on this code segment:

DateTimeFormatter dateFormat = DateTimeFormatter.ISO_DATE; // DEF

LocalDate dateOfBirth = LocalDate.of(2015, Month.FEBRUARY, 31);

System.out.println(dateFormat.format(dateOfBirth)); // USE

A. The program gives a compiler error in the line marked with the comment DEF

B. The program gives a compiler error in the line marked with the comment USE

C. The code segment prints: 2015-02-31

D. The code segment prints: 2015-02-03

E. This code segment throws java.time.DateTimeException with the message "Invalid date 'FEBRUARY 31'"

Page 57: Java 8 Date and Time API

Quiz Question #4 - Answer

E. This code segment throws java.time.DateTimeException with the message "Invalid date 'FEBRUARY 31'" .

The date value 31 passed in the call LocalDate.of(2015, 2, 3 1); is invalid for the month February, and hence the of() method in the LocalDate class throws DateTimeException.

One of the predefined values in DateTimeFormatter is ISO_DATE. Hence, it does not result in a compiler error for the statement marked with the comment DEF. The statement marked with the comment USE compiles without errors because it is the correct way to use the format() method in the DateTimeFormatter class.

Page 58: Java 8 Date and Time API

Quiz Question #5 Consider this code segment:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE", Locale.US);

System.out.println(formatter.format(LocalDateTime.now()));

Which of the following outputs matches the string pattern "EEEE" given in this code segment?

A. F

B. Friday

C. Sept

D. September

Page 59: Java 8 Date and Time API

Quiz Question #5 - Answer

B. Friday

E is the day name in the week; the pattern "EEEE" prints the name of the day in its full format. “Fri” is a short form that would be printed by the pattern “E", but "EEEE" prints the day of the week in full form: for example, “Friday”. Because the locale is Locale.US, the result is printed in English. The output “Sept” or “September” is impossible because E refers to the name in the week, not in a month.

Page 60: Java 8 Date and Time API

Meetups

h"p://www.meetup.com/JavaScript-Meetup-Bangalore/h"p://www.meetup.com/Container-Developers-Meetup-Bangalore/h"p://www.meetup.com/So>ware-Cra>smanship-Bangalore-Meetup/h"p://www.meetup.com/Core-Java-Meetup-Bangalore/h"p://www.meetup.com/Technical-Writers-Meetup-Bangalore/h"p://www.meetup.com/CloudOps-Meetup-Bangalore/h"p://www.meetup.com/Bangalore-SDN-IoT-NetworkVirtualizaHon-Enthusiasts/h"p://www.meetup.com/So>wareArchitectsBangalore/

Page 61: Java 8 Date and Time API

Upcoming Java 8 Workshop

Modern Programming with Java 8 Workshop Refactor your legacy applications using Java 8 features

Register here: https://www.townscript.com/e/java8-refactoring