Saturday, July 19, 2014

Date And Time With Java

How do you deal with dates and time in Java and perform common operations like finding difference between two dates or translate dates into a particular string formats?

This post seeks to provide an answer to those questions.

I would start off by giving a brief description of the available date related classes and packages you might encounter on the Java platform and then do follow up posts exploring some of the common date/time operations like how to format date-time, dealing with time zones and locale, finding differences between dates/times etc.

You should not find yourself using java.util.Date directly. It appeared since JDK 1.0 and most of the methods contained within it has been deprecated and replaced with recent alternatives. It's listed here maily for completeness.

The java.util.Date class contains functionality that allowed the interpretation of dates as year, month, day, hour, minute, and second values. It does not contain any timezone related information.

A new java.util.Date can thus be created via:

Date today = new Date()

The other overloaded constructors for creating a java.util.Date has been deprecated.

An inconsistency worthy of note is that although the class is called java.util.Date, it contains Time information expressed in milliseconds of the "epoch" which is the amount of seconds that has elapsed since 1 January 1970, 00:00:00 UTC. It can be retrieved via:

java.util.Calendar is an abstract class that models the concept of a calendar. It contains functionality that enables translation from an instant in time to calendar fields like Year, Months etc; and also for interacting with a Calendar, such as being able to get the days already spent in a year.

Since java.util.Calendar is an absract class, it cant be constructed with the new operator.

You only have concrete implementations that extend the abstact java.util.Calendar class. eg the GregorianCalendar.

The concrete implementations are usually not instantiated directly but are gotten via the use of the Calendar's static method getInstance()

These are things like Year, Week, Month etc. These fields are specified as static constants of the java.util.Calendar class and they can be used to retrieve the appropiate field from the instantiated java.util.Calendar sub-class.

You can easily convert a moment in time captured in java.util.Calendar instance to java.util.Date. You use java.util.Calendar.getTime() to get a java.util.Date instance while you use java.util.Calendar.setTime(Date date) to convert from java.util.Date to java.util.Calendar.

java.sql.Date, java.sql.Time, java.sql.Timestamp are date related classes you would find inside the java.sql package. They are used for representing date and time values that would be saved into the database.

Their usage corresponds to the respective SQL date time value they operate on.

java.sql.Date

java.sql.Date models SQL's Date value which only represents the Date portion of a moment in time. The SQL literal format is YYYY-MM-DD. Creating the corresponding java.sql.Data object can be done thus:

java.sql.Date sqlDate = new java.sql.Date(long time);

which constructs java.sql.Date object using the given milliseconds time value. The other methods have been deprecated.

java.sql.Time

java.sql.Time models SQL's Time value which represents the Time portion of a moment in time. The SQL literal format is hh:mm:ss. Creating the corresponding java.sql.Time object can be done thus:

java.sql.Time sqlTime = new java.sql.Time(long time);

which constructs a Time object using a milliseconds time value. The other methods have been deprecated.

java.sql.Timestamp

java.sql.Timestamp is for SQL's DATETIME (or TIMESTAMP) value which represents both the Date and Time portion of a moment in time. The SQL literal format is 'YYYY-MM-DD HH:MM:SS' . Creating the corresponding java.sql.Timestamp object can be done thus:

java.sql.Timestamp sqlTimestamp =
new java.sql.Timestamp(long time);

which constructs a Timestamp object using a milliseconds time value. The other methods have been deprecated.

Joda time provides a much better API for handling Date and Time in Java. The JDK's Date and Time API has long proven to be incosistent and quirky - although that has pretty much changed with the Date/Time classes in Java 8 - Joda time was a project started to provide Java developers a better alternative and it has basically emerged as the defacto: more consistent and friendly API to use when working with Date/Time in Java.

The Joda Time library offer a wealth of functionality. Getting started though, there are 5 date/time classes you should be aware of:

org.joda.time.DateTime - replacement for JDK Calendar

org.joda.time.DateMidnight - class representing a date where the time is forced to midnight

org.joda.time.LocalDate - class representing a local date without a time (no time zone)

org.joda.time.LocalTime - class representing a time without a date (no time zone)

org.joda.time.LocalDateTime - class representing a local date and time (no time zone)

All these classes are immutable.

Any of these classes can be created using the new keyword, so for example

org.joda.time.DateTime = new org.joda.time.DateTime();

or using the static method Now()

org.joda.time.DateTime = org.joda.time.DateTime.Now();

It is also easy to convert from any of the JDK date classes to these joda time classes. This is done by passing the JDK classes as constructors arguments. For example

With Java 8, the JDK comes with new Date and Time API which is more consistent in its design. If developing with Java 8 and you do not want to use Joda Time, it is fine, you would easily survive and do well with the date/time classes that ships with Java 8.

The new sets of classes can be found under the java.time package. Briefly outlined below are the main set of classes you would probably initially interact with.

An immutable thread safe class that embodies a date. That is just day, month and year. Other date fields, such as day-of-year, day-of-week and week-of-year, etc can be accessed from the java.time.LocalDate class.

It is important to note that a java.time.LocalDate object comes without a time-zone and has got the ISO-8601 calendar system.

java.time.LocalDate instance can be created using now() method or of(int year, int month, int day)

An immutable thread safe class that embodies a time. It is in the format of hours:minutes:seconds.nonoseconds (hh:mm:ss:zzz). Time in java.time.LocalTime is represented to nanosecond precision. For example, the value "12:35.30.123456789".

The java.time.LocalTime is without time-zone and is in the ISO-8601 calendar system.

Used to represent an instantaneous moment in time which is usually expressed as the epoch time which is the amount of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970, not counting leap seconds.