Search

Dark theme | Light theme

April 4, 2023

Groovy Goodness: Using Subscript Operator With Multiple Fields On Date Related Objects

Since Groovy 4.0.5 we can use a subscript operator that accepts multiple fields on a java.util.Date and java.util.Calendar objects. And Groovy 4.0.6 extended this subscript operator to any java.time.TemporalAccessor instance. Before these Groovy version we could already use the subscript operator, but we could provide only one field we wanted to access. In a previous post we already have seen this. But now we can use multiple fields to get their values with one statement. We simply define the fields we want as arguments to the subscript operator. Under the hood the subscript operator is implemented by a getAt method that is added as an extension to the Date, Calendar and TemporalAccess classes. The return type is java.util.List and we can combine this with the multiple assignment support in Groovy. In other languages it is also called destructurizing. With multiple assignments we can assign the values from a java.util.List directly to variables.

In the following example we see several usages of the subscript operator with multiple fields on Date, Calendar and LocalDateTime objects:

import java.time.LocalDateTime
import java.time.Month
import static java.time.temporal.ChronoField.*
import static java.time.temporal.IsoFields.*

// Create a Date instance.
def date = new Date().parse('yyyy/MM/dd', '1973/07/09')

// Groovy adds the subscript operator for multiple
// fields to the Date class.
def output = date[Calendar.DATE, Calendar.MONTH, Calendar.YEAR]
assert output == [9, 6, 1973]

// The result is a list and we can destructurize it
// to assign values to variables (also called multiple assignments).
def (day, month, year) = date[Calendar.DATE, Calendar.MONTH, Calendar.YEAR]

assert "$day-${month + 1}-$year" == "9-7-1973"


// Create a Calendar instance.
def calendar = date.toCalendar()

// The subscript operator supporting multiple fields
// is also added to the Calendar class.
def (calDay, calMonth, calYear) = calendar[Calendar.DATE, Calendar.MONTH, Calendar.YEAR]

assert "Time to celebrate on $calDay-${calMonth + 1}" == "Time to celebrate on 9-7"


// Create a LocalDateTime instance
def birthDateTime = LocalDateTime.of(1973, Month.JULY, 9, 6, 30, 0);

// Groovy adds the subscript operator with multiple fields
// on any TemporalAccessor instance.
def (dayOfWeek, dayOfYear, quarter, week) = birthDateTime[DAY_OF_WEEK, DAY_OF_YEAR, QUARTER_OF_YEAR, WEEK_OF_WEEK_BASED_YEAR]

assert "Born in week $week on day $dayOfWeek" == "Born in week 28 on day 1"
assert quarter == 3
assert dayOfYear == 190

def (hour, minute) = birthDateTime[HOUR_OF_DAY, MINUTE_OF_HOUR]

assert "Live started at $hour:$minute" == "Live started at 6:30"

Written with Groovy 4.0.11.