Dates

Dates are used extensively throughout the application. They can be tricky to work with, and therefore deserve a separate chapter. It will explain some of the date’s technical details, and how that knowledge is applicable to practical use cases.

Classes

One of the thing that adds to the complexity, is that there are two kind of dates available in Groovy. Their class is both called Date, but they originate from a different package, namely java.sql and java.util. The application’s data model exclusively uses the former kind, i.e. an entity’s date attribute is always a java.sql.Date.

The class java.sql.Date is subclass of java.util.Date. In other words, an instance of a java.sql.Date is by definition also a java.util.Date, but not the other way around. For those unfamiliar with class hierarchies, think of it like this: apple is a subclass of fruit, so an apple is by definition a fruit, but a fruit is not necessary an apple.

When working with dates, a date instance is often already at hand, and its exact class is of no further importance. For example, claimLine.startDate and person.dateOfBirth can be used for all kinds of purposes, without having to explicitly mention their class:

assert person.dateOfBirth <= claimLine.startDate

When a new fixed java.sql.Date instance is required, the class becomes relevant:

def sqlDate = java.sql.Date.valueOf('2018-07-26')

Converting a java.util.Date to a java.sql.Date can be done using their common millisecond time attribute (more about time below):

def sqlDate = new java.sql.Date(utilDate.time)

Imports

The names of the packages java.sql and java.util are fairly short, but package names can become quite long. Occurrences of such names throughout dynamic logic can impact readability. Therefore, package names are generally only specified once, using an import statement at the top of the logic, such that it can be omitted from the rest of the logic. For example, the following statement will allow the SimpleDateFormat class to be used by the subsequent logic, without specifying its package name:

import java.text.SimpleDateFormat

Groovy adds a few hidden default imports, including java.util.Date. Referring simply to the Date class in Groovy, will therefore automatically yield a java.util.Date. When a java.sql.Date is required, it needs to be explicitly specified as such. It is possible to override the default import to java.sql.Date, but simultaneously importing two different classes with the same name is impossible.

Time

As the official documentation about java.util.Date says, it represents a specific instant in time, with millisecond precision. So besides the year, month, and day, a Date also carries the time of the day. That applies to java.sql.Date as well. In the application’s data model, the time components of a date field is always cleared, i.e. 00:00:00. That is different for fields with the class java.sql.Timestamp, such as claim.creationDate and ctrClaim.transactionDateTime.

Today

In some use-cases an instance of the current date is desired. Creating a new/empty java.util.Date will result in a date instance that is set to the current time:

def now = new Date()

Note that the java.util prefix is not required, because of the aforementioned default import. To create today’s java.sql.Date, the java.util.Date can be converted, similar to the earlier example:

def now = new java.sql.Date(new Date().time)

Comparing

Dates can easily be compared in Groovy using the regular comparison-operators:

assert yesterday < tomorrow

As mentioned, a java.sql.Date is in fact a java.util.Date, so you can also compare a java.sql.Date to a java.util.Date:

assert claimLine.startDate < new Date()

Do keep in mind that dates originating from the application’s data model always have a time component of 00:00:00, while the above newly created one does not. Therefore, those two dates will not be equal, even if their year, month, and day are equal. Groovy has provided the clearTime method for this purpose:

assert claimLine.startDate <= new Date().clearTime()

Modification

Adding or subtracting a certain number of days is simple in Groovy:

def tomorrow = today + 1

More complex date modification, requires more complex code. One possibility is by Java’s Calendar functionality:

def calendar = Calendar.getInstance()
calendar.setTime(claimLine.startDate)
calendar.add(Calendar.MONTH, 6)
calendar.add(Calendar.DATE, -1)
def date = calendar.getTime()

Another possibility is by using Groovy’s TimeCategory structure:

use (groovy.time.TimeCategory) {
  def date = claimLine.startDate + 6.months - 1.day
}