JSR-310 is a set of classes ear-marked for Java 7 which are a revamp of Java's built-in Date and Calendar classes. Given that JSR-310 is still at the proposal stage, some of the information here may change. Some key classes in JSR-310 include:
| Class | Description |
|---|---|
| ZonedDateTime | ZonedDateTime is an immutable class representing calendar information, often viewed as year-month-day-hour-minute-second-zone. |
| LocalDate | Immutable class representing a local date with no time or time zone |
| LocalTime | Immutable class representing a time with no date or time zone |
| LocalDateTime | Immutable class representing a local date and time with no time zone |
| Period | Immutable class representing period consisting of the standard year, month, day, hour, minute, second and nanosecond units |
| Instant | Immutable class representing an instantaneous point in time with nanosecond precision |
| MonthDay | One of many partial date representations; this one representing a month and day but no year |
| Clock | A facade for accessing the current time |
If you are not using Java 7 by the time you read this, make sure you add a jsr-310-ri-yyyymmdd.jar jar to your classpath before running these examples. We used a hand built version based on trunk at 28-Sep-2008 running under Java 6 and have glossed over some differences (i.e. disguised the differences) so that it appears as we think it would under Java 7.
Accessing the current time is done using the Clock class. Several variations are shown here:
import javax.time.Clock import javax.time.calendar.* // use Clock.system() to get default time zone def systemClock = Clock.system(TimeZone.UTC) // some useful LocalDate instances def today = systemClock.today() def tomorrow = systemClock.tomorrow() def yesterday = systemClock.yesterday() // a ZonedDateTime instance def todayZoned = systemClock.currentZonedDateTime() println yesterday println today println tomorrow println todayZoned
which will produce output like this:
2008-09-27 2008-09-28 2008-09-29 2008-09-28T03:24:36.781Z UTC
You can access fields of a LocalDate and ZonedDateTime instances using numerous properties:
println today.chronology // just rely on the toString() of the year class println today.year // just rely on the toString() of the enums [yesterday, today, tomorrow].each { day -> println day.monthOfYear println day.dayOfYear println day.dayOfMonth println day.dayOfWeek } // print out the integer values todayZoned.with { println hourOfDay.value println minuteOfHour.value println secondOfMinute.value }
which will produce output like this:
ISO Year=2008 MonthOfYear=SEPTEMBER DayOfYear=271 DayOfMonth=27 DayOfWeek=SATURDAY MonthOfYear=SEPTEMBER DayOfYear=272 DayOfMonth=28 DayOfWeek=SUNDAY MonthOfYear=SEPTEMBER DayOfYear=273 DayOfMonth=29 DayOfWeek=MONDAY 3 46 3
You can also use time periods:
import static javax.time.period.Period.* def lastNewYears = LocalDateTime.dateTime(2008, 1, 1, 0, 0, 0) println lastNewYears def nextNewYears = lastNewYears + years(1) println nextNewYears
which will produce output like this:
2008-01-01T00:00 2009-01-01T00:00
You can also input or output dates and times using various formatting helper classes including a powerful format building class or using Groovy's GStrings:
// pattern formatting not finalised for JSR-310 at time of writing // so kludge this using normal Java facilities for now def input = "20080125" def fmt_in = new java.text.SimpleDateFormat("yyyyMMdd") def cal_in = Calendar.instance cal_in.setTime(fmt_in.parse(input)) def date_in = cal_in.toLocalDate() // now output using predefined formatter import javax.time.calendar.format.* def fmt_out = DateTimeFormatters.isoDate() println fmt_out.print(date_in) // now try the format builder import static javax.time.calendar.ISOChronology.* import static javax.time.calendar.format.DateTimeFormatterBuilder.TextStyle.* def fmt = new DateTimeFormatterBuilder(). appendValue(dayOfMonthRule(), 2). appendLiteral('-'). appendText(monthOfYearRule(), SHORT). appendLiteral('-'). appendText(yearRule()). toFormatter() println fmt.print(today) fmt = new DateTimeFormatterBuilder(). appendLiteral('Some ways to represent the current month: '). appendValue(monthOfYearRule()). appendLiteral(' '). appendValue(monthOfYearRule(), 2). appendLiteral(' '). appendText(monthOfYearRule(), NARROW). appendLiteral(' '). appendText(monthOfYearRule(), SHORT). appendLiteral(' '). appendText(monthOfYearRule(), FULL). toFormatter() println fmt.print(today) // now just using a plain GString println "$today.dayOfMonth.value-${today.monthOfYear.value.toString().padLeft(2, '0')}-$today.year.value"
which will produce output like this:
2008-01-25 28-Sep-2008 Some ways to represent the current month: 9 09 9 Sep September 28-09-2008
If you want to make things look a little more compact, you can apply a little bit of metaprogramming to overload some of the format builder methods like follows:
DateTimeFormatterBuilder.metaClass.leftShift = { String s -> delegate.appendLiteral s }
DateTimeFormatterBuilder.metaClass.leftShift = { DateTimeFieldRule r -> delegate.appendText r }
Now we can use a simpler builder syntax:
def builder = new DateTimeFormatterBuilder() << dayOfMonthRule() << "/" << monthOfYearRule() << "/" << yearRule() println builder.toFormatter().print(today)
which will produce output like this:
28/September/2008
Copyright (c) 2008 Paul King. All rights reserved.