Core Java

OCA Java 8 Preparation : Date Time API

Below are the temporal classes that you are expected to know for your OCA Java 8 Certification Exam :

java.time package :

  1. LocalDate : This class represents a date only in terms of date – based values(year, month, day). Time-zones aren’t handled.
  2. LocalTime : LocalTime represents only the time value(hours, minutes, seconds, nanoseconds ) within a 24-hour day.Doesn’t deals with time-zones.
  3. LocalDateTime : This class stores both date and time values combined. They still don’t handle timezones.
  4. Period : Java 8 Date API provides a Period class to help you represents the date based values in terms of the count. For instance, 1 year 3 months 4 days etc.

java.time.format package :

  1. DateTimeFormatter : The purpose of formatter is to either help you obtain a string representation of a temporal object(known as formatting) or to obtain a temporal object from a string(known as parsing a temporal object).

Important Points :

All the above temporal classes have a few things in common, among which these are worth mentioning :

  1. All these temporal classes are immutable and thread-safe.Any method which attempts to modify these objects will return a modified copy of that temporal object.
  2. Any attempt to pass an invalid date- time values( out of range values or if a day is invalid for a specified month) as an argument to one of the methods will lead to java.time.DateTimeException.
  3. Using an inappropriate formatter, for instance – trying to format a LocalDate object with a time-based formatter, will also lead to an exception of type – java.time.DateTimeException.
  4. It is valid to have year expressed as a negative number as year in Java 8 Date API is represented as a ‘proleptic year’. It means 1 represents 1 AD or CE(Current Era), 0 represents 1 BCE(Before Current Era), -1 represents 2 BCE,  -2010 represents 2011 BCE and so on.
  5. Refer the below table for the range of valid date and time values.
    SubjectRange
    Year-999,999,999 to +999,999,999
    Month1 - 12
    Day1 - 31
    Hours0 - 23
    Minutes0 - 59
    Seconds0 - 59
    Naonseconds0 - 999,999,999
  6. Below table represents the default format of these temporal objects(output of toString())
    ClassDefault toString() Format
    LocalDateuuuu-MM-dd
    LocalTimeHH:mm:ss.SSSSSSSSS
    LocalDateTimeuuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS

It’s time to discuss the APIs in detail.

I know that it makes you a little bothered to think of the fact that you need to memorize all the methods(or at least most) of these classes which is a bit overwhelming. However, the methods of these temporal classes follow a common pattern and therefore won’t take you much a pain to grasp them all.

I’ll keep this post specific to LocalDate, LocalTime and LocalDateTime classes and will cover the remaining two classes in one of my upcoming posts.

Time to get started!

Instantiating Temporal Objects :

The temporal classes do not provide any public constructor. Watch out for such usage in the exam. All the above mentioned classes provides a static factory method of() which enables you to create an instance of that class based on the parameters.

static LocalDate of(int year, int month, int day)
//Use of enum java.time.Month
static LocalDate of(int year, Month month, int day)

static LocalTime of(int hour, int minute , int second, int nanosecond)
static LocalTime of(int hour, int minute, int second)
static LocalTime of(int hour, int minute)


static LocalDateTime of(int year, int month, int day, int hour, int minute, int second, int nanosecond)
static LocalDateTime of(int year, Month month, int day, int hour, int minute, int second, int nanosecond)
static LocalDateTime of(int year, int month, int day, int hour, int minute, int second)
static LocalDateTime of(int year, Month month, int day, int hour, int minute, int second)
static LocalDateTime of(int year, int month, int day, int hour, int minute)
static LocalDateTime of(int year, Month month, int day, int hour, int minute)
static LocalDateTime of(LocalDate localDate, LocalTime localTime)

The seconds and nanoseconds are defaulted to 0 for any time-based values, wherever not specified. There are also methods available in the library to convert a LocalDate or LocalTime to LocalDateTime. Likewise, LocalDateTime class provides methods to extract LocalDate or LocalTime object out of it.

//to be invoked on LocalDate object
LocalDateTime atTime(int hour, int minute, int second, int nanosecond)
LocalDateTime atTime(int hour, int minute, int second)
LocalDateTime atTime(int hour, int minute)
LocalDateTime atTime(LocalTime localTime)

//to be invoked on LocalTime object
LocalDateTime atDate(LocalDate localDate)

//to be invoked on LocalDateTime
LocalDate toLocalDate()
LocalTime toLocalTime()

Please find below some example valid and invalid usages of the above methods.

LocalTime localTime1 = LocalTime.of(11,23,30);//valid
LocalTime localTime2 = LocalTime.of(11,23,30,233);//valid
LocalTime localTime3 = LocalTime.of(27,23,30,233);//throws DateTimeException


LocalDate localDate1 = LocalDate.of(2017,02,11); //valid
LocalDate localDate2 = LocalDate.of(2017,02,61);///throws DateTimeException

LocalDateTime localDateTime1 = localTime1.atDate(localDate1); //valid
LocalDateTime localDateTime2 = localDate1.atTime(11,12); //valid
LocalDateTime localDateTime2 = localDate1.atTime(LocalTime.NOON);//valid

Each temporal class also provides a static method now() that returns the temporal value based on the system clock.

LocalDate currentDate = LocalDate.now();
LocalTime currentTime = LocalTime.now();
LocalDateTime currentDateTime = LocalDateTime.now();

Querying Temporal Objects :

Once you have created a temporal object of your choice, you need methods to operate on them.Below are some common methods, you need to know.

//Methods common to LocalDate,LocalDateTime
int getDayOfMonth()
//DayOfWeek is an enum with values DayOfWeek.MONDAY to DayOfWeek.SUNDAY
DayOfWeek getDayOfWeek()
int getDayOfYear()
//Month is an enum with values Month.JANUARY to Month.DECEMBER
Month getMonth()
int getMonthValue()
int getYear()

//Methods common to LocalTime,LocalDateTime
int getHour()
int getMinute()
int getSecond()
int getNano()

//Invoked on LocalDate only
boolean isLeapYear()

Comparing Temporal Objects :

Below methods are available to help you compare the temporal objects.

//LocalTime
boolean isAfter(LocalTime other)
boolean isBefore(LocalTime other)

//LocalDate(LocalDate implements ChronoLocalDate interface)
boolean isAfter(ChronoLocalDate other)
boolean isBefore(ChronoLocalDate other)
boolean isEqual(ChronoLocalDate other)

//LocalDateTime(LocalDateTime implements ChronoLocalDateTime interface)
boolean isAfter(ChronoLocalDateTime<?> other)
boolean isBefore(ChronoLocalDateTime<?> other)
boolean isEqual(ChronoLocalDateTime<?> other)

Some example usages includes :

LocalDate d1 = LocalDate.of(-2004, 3, 1);                    // -2004-03-01
LocalDate d2 = LocalDate.of(2004, 3, 1);                     // 2004-03-01
boolean result1 = d1.isBefore(d2);                           // true
boolean result2 = d2.isAfter(d1);                            // true
boolean result3 = d1.isEqual(d2);                            // false

These temporal classes also implement Comparable interface providing compareTo() method. They also override equals() method of the Object class.

int compareTo(LocalTime other) //LocalTime
int compareTo(ChronoLocalDate other) //LocalDate
int compareTo(ChronoLocalDateTime<?> other) //LocalDateTime

boolean  equals(Object obj) //LocalDate, LocalTime, LocalDateTime

Modifying Temporal Objects :

Since all of these classes are immutable, so no setters are available. Still, these classes provide with methods(referred as ‘withers‘) which return a modified copy of the original object where exactly one property of that object has been set to a new value.Important point to note here is that the original object is not impacted.

//LocalTime,LocalDateTime
[LocalTime | LocalDateTime] withHour(int hour)
[LocalTime | LocalDateTime]  withMinute(int minute)
[LocalTime | LocalDateTime] withSecond(int second)
[LocalTime | LocalDateTime] withNano(int nano)

//LocalDate, LocalDateTime
[LocalDate | LocalDateTime] withYear(int year)
[LocalDate | LocalDateTime] withMonth(int month)
[LocalDate | LocalDateTime] withDayOfMonth(int dayOfMonth)
[LocalDate | LocalDateTime] withDayOfYear(int dayOfYear)

These methods also throw DateTimeException if the input value is out of range.

withYear() & withMonth() methods will adjust the day of the month to be the last valid day of the month, if the day of month becomes invalid when the year or the month is changed (e.g., the month value 2 will change the date 2016-03-31 to 2016-02-29).

In contrast, withDayOfMonth()  will throw DateTimeException, if the day of the month becomes invalid for a specified month of that year. (eg : 29 as the day of the month for Feb, 2018).

Some example usages to make your understanding clearer :

LocalDateTime dateTime1 = LocalDateTime.of(2003, 8, 12, 10, 15);
System.out.println(dateTime1.getYear());  //2003
System.out.println(dateTime1.getMonthValue()); //8
System.out.println(dateTime1.getMonth()); //AUGUST
System.out.println(dateTime1.getDayOfYear()); //224
System.out.println(dateTime1.getDayOfMonth()); //12
System.out.println(dateTime1.getDayOfWeek()); //TUESDAY
System.out.println(dateTime1.toLocalDate().isLeapYear());//false
System.out.println(dateTime1.withMonth(9));//2003-09-12T10:15
System.out.println(dateTime1.withDayOfMonth(19));//2003-08-19T10:15

Again, I prefer to repeat, these methods don’t modify the state of dateTime1.

Temporal Arithmetic :

These temporal classes provides plus and minus methods that return a copy of original object incremented or decremented by a specific amount of value(time or date based value).

//All these methods throws DateTimeException, if the result exceeds the date range.
// LocalTime, LocalDateTime
//The calculation always wraps around midnight.
[LocalTime|LocalDateTime] minusHours/plusHours(long hours)
[LocalTime|LocalDateTime] minusMinutes/plusMinutes(long minutes)
[LocalTime|LocalDateTime] minusSeconds/plusSeconds(long seconds)
[LocalTime|LocalDateTime] minusNanos/plusNanos(long nanos)

// LocalDate, LocalDateTime
[LocalDate|LocalDateTime] minusYears/plusYears(long years)
[LocalDate|LocalDateTime] minusMonths/plusMonths(long months)
[LocalDate|LocalDateTime] minusWeeks/plusWeeks(long weeks)
[LocalDate|LocalDateTime] minusDays/plusDays(long days)

Sample usages include :

LocalDate date = LocalDate.of(2018, 02, 01);          
System.out.println("Date:             " + date);       // 2018-02-01
date = date.plusMonths(11);                            
System.out.println("11 months after:  " + date);       // 2019-01-01
date = date.plusWeeks(5);                              
System.out.println("5 weeks after:    " + date);       // 2019-02-05
date = date.plusDays(29);                              
System.out.println("29 days after:    " + date);       // 2019-03-06

date = date.minusDays(4);                             
System.out.println("4 days before:    " + date);       // 2019-03-02
date = date.minusWeeks(5);                            
System.out.println("5 weeks before:   " + date);       // 2019-01-26
date = date.minusMonths(10);                          
System.out.println("10 months before: " + date);       // 2018-03-26

 

2 comments

Shubra…You did the job perfectly for us to help and cover all important concepts in all topics.Thank You . All topics you explained is the crystal clear summary of any good java book .

Leave a Comment

Your email address will not be published. Required fields are marked *