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.