7.3. Date operations (JSR-310 Date and Time API)¶
Index
7.3.1. Overview¶
java.util.Date and java.util.Calendar.Note
Since JSR-310 Date and Time API has been introduced from Java8, using Joda Time is recommended for the environments of versions Java8 and below. For how to use Joda Time, refer Date Operations (Joda Time).
7.3.2. How to use¶
java.time.LocalDate , java.time.LocalTime and java.time.LocalDateTime, however, since the prefix of all the methods offered by each class is same for primary date and time operations, it should be interpreted by substituting with the appropriate class name.| Class name | Description | Primary factory methods |
|---|---|---|
| Class which handles date and time operation and does not possess information about timezone difference | now Generated by current date and timeof Generated by any date and timeparse Generated from date and time stringfrom Generated from other objects with date and time information |
|
| Class which handles date and time operation considering timezone difference | Same as above | |
| Class to handle Japanese calendar operations | Same as above |
| Class name | Description | Primary factory methods |
|---|---|---|
| Class which handles date and time base, time base period | between Generated from the difference between two objects with date and time informationfrom Generated from another object that contains amount of timeof Generated in any time period |
| Class name | Description | Primary factory method |
|---|---|---|
| Class which handles operations related to date and time format | ofPattern Generates a formatter in specified pattern |
Note
For the topics that are not covered in the guideline, refer Javadoc for details.
Note
Date and Time API class is immutable (date and time calculation result is considered as a new object, and changes do not occur in the objects for calculation).
7.3.2.1. Fetch date and time¶
7.3.2.1.1. Fetch by current date and time¶
java.time.LocalTime , java.time.LocalDate and java.time.LocalDateTime must be selectively used in accordance with the purpose for which it is to be used. Example is shown below.- Use
java.time.LocalTimewhen only time is to be fetched.
LocalTime localTime = LocalTime.now();
- Use
java.time.LocalDatewhen only date is to be fetched.
LocalDate localDate = LocalDate.now();
- Use
java.time.LocalDateTimewhen both date and time are to be fetched.
LocalDateTime localDateTime = LocalDateTime.now();
7.3.2.1.2. Fetch by specifying year, month, day, hours, minutes and seconds¶
- Specify time and fetch
java.time.LocalTime.
// 23:30:59
LocalTime localTime = LocalTime.of(23, 30, 59);
- Specify date and fetch
java.time.LocalDate.
// 2015/12/25
LocalDate localDate = LocalDate.of(2015, 12, 25);
- Specify date and time and fetch
java.time.LocalDateTime.
// 2015/12/25 23:30:59
LocalDateTime localDateTime = LocalDateTime.of(2015, 12, 25, 23, 30, 59);
java.time.temporal.TemporalAdjusters.// LeapYear(2012/2)
LocalDate localDate1 = LocalDate.of(2012, 2, 1);
// Last day of month(2012/2/29)
LocalDate localDate2 = localDate1.with(TemporalAdjusters.lastDayOfMonth());
// Next monday(2012/2/6)
LocalDate localDate3 = localDate1.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
Note
Unlike the specifications of java.util.Calendar, calendar month starts from 1.
7.3.2.1.3. Fetch date and time when time zone is specified¶
java.time.OffsetTime , java.time.OffsetDateTime and java.time.ZonedDateTime must be used selectively in Date and Time API in accordance with the purpose for which it is to be used.- Use
java.time.OffsetTimewhen the time difference between time + UTC is to be fetched.
// Ex, 12:30:11.567+09:00
OffsetTime offsetTime = OffsetTime.now();
- Use
java.time.OffsetDateTimewhen the time difference between date, time + UTC is to be fetched.
// Ex, 2015-12-25T12:30:11.567+09:00
OffsetDateTime offsetDateTime = OffsetDateTime.now();
- Use
java.time.ZonedDateTimewhen the time difference and region for date, time + UTC is to be fetched.
// Ex, 2015-12-25T12:30:11.567+09:00[Asia/Tokyo]
ZonedDateTime zonedDateTime = ZonedDateTime.now();
java.time.ZoneId which indicates time zone in the argument.java.time.ZoneId example is shown below.ZoneId zoneIdTokyo = ZoneId.of("Asia/Tokyo");
OffsetTime offsetTime = OffsetTime.now(zoneIdTokyo);
java.time.ZoneId consists of a method to be defined by region name/area name format and a method defined by time difference from UTC.ZoneId.of("Asia/Tokyo");
ZoneId.of("UTC+01:00");
java.time.OffsetDateTime and java.time.ZonedDateTime is similar, the basic difference is as given below.| Class name | Description |
|---|---|
java.time.OffsetDateTime |
Since it only consists of quantitative value (only time difference), system does not undergo any change even if there is a change in the concept of time for each area. |
java.time.ZonedDateTime |
Since it includes concept of region besides time difference, the system undergoes change when a change occurs in the concept of time for each region.(when daylight saving etc is included as a policy) |
7.3.2.2. Time period¶
7.3.2.2.1. Fetch time period¶
java.time.Period is used while handling date based period and java.time.Duration is used while handling time based period.java.time.Duration is of exactly 24 hours, expected results may not be obtained if daylight saving changes are not incorporated.java.time.Period represents 1 day including daylight saving, an error does not occur even in the system which handles daylight saving.LocalDate date1 = LocalDate.of(2010, 01, 15);
LocalDate date2 = LocalDate.of(2011, 03, 18);
LocalTime time1 = LocalTime.of(11, 50, 50);
LocalTime time2 = LocalTime.of(12, 52, 53);
// One year, two months and three days.
Period pd = Period.between(date1, date2);
// One hour, two minutes and three seconds.
Duration dn = Duration.between(time1, time2);
Note
A method can also be employed wherein the period is generated by specifying it by using
ofmethod. For details, refer Javadoc of Period, Duration.
7.3.2.3. Type conversion¶
7.3.2.3.1. Interoperability of each class of Date and Time API¶
java.time.LocalTime , java.time.LocalDate and java.time.LocalDateTime can easily be mutually converted. Example is given below.- Conversion from
java.time.LocalTimetojava.time.LocalDateTime.
// Ex. 12:10:30
LocalTime localTime = LocalTime.now();
// 2015-12-25 12:10:30
LocalDateTime localDateTime = localTime.atDate(LocalDate.of(2015, 12, 25));
- Conversion from
java.time.LocalDatetojava.time.LocalDateTime.
// Ex. 2012-12-25
LocalDate localDate = LocalDate.now();
// 2015-12-25 12:10:30
LocalDateTime localDateTime = localDate.atTime(LocalTime.of(12, 10, 30));
- Conversion from
java.time.LocalDateTimetojava.time.LocalTimeandjava.time.LocalDate.
// Ex. 2015-12-25 12:10:30
LocalDateTime localDateTime = LocalDateTime.now();
// 12:10:30
LocalTime localTime = localDateTime.toLocalTime();
// 2012-12-25
LocalDate localDate = localDateTime.toLocalDate();
java.time.OffsetTime , java.time.OffsetDateTime and java.time.ZonedDateTime can also be easily mutually converted. Example is given below.- Conversion from
java.time.OffsetTimetojava.time.OffsetDateTime.
// Ex, 12:30:11.567+09:00
OffsetTime offsetTime = OffsetTime.now();
// 2015-12-25T12:30:11.567+09:00
OffsetDateTime offsetDateTime = offsetTime.atDate(LocalDate.of(2015, 12, 25));
- Conversion from
java.time.OffsetDateTimetojava.time.ZonedDateTime.
// Ex, 2015-12-25T12:30:11.567+09:00
OffsetDateTime offsetDateTime = OffsetDateTime.now();
// 2015-12-25T12:30:11.567+09:00[Asia/Tokyo]
ZonedDateTime zonedDateTime = offsetDateTime.atZoneSameInstant(ZoneId.of("Asia/Tokyo"));
- Conversion from
java.time.ZonedDateTimetojava.time.OffsetDateTimeandjava.time.OffsetTime.
// Ex, 2015-12-25T12:30:11.567+09:00[Asia/Tokyo]
ZonedDateTime zonedDateTime = ZonedDateTime.now();
// 2015-12-25T12:30:11.567+09:00
OffsetDateTime offsetDateTime = zonedDateTime.toOffsetDateTime();
// 12:30:11.567+09:00
OffsetTime offsetTime = zonedDateTime.toOffsetDateTime().toOffsetTime();
java.time.LocalTime can be converted to java.time.OffsetTime by adding time difference information.// Ex, 12:30:11.567
LocalTime localTime = LocalTime.now();
// 12:30:11.567+09:00
OffsetTime offsetTime = localTime.atOffset(ZoneOffset.ofHours(9));
LocalTime to LocalDateTime).7.3.2.3.2. Interoperability with java.util.Date¶
A method which directly converts java.time.LocalDate class to java.util.Date is not provided.
java.time.Instant offered by Date and Time API is added to java.util.Date from Java8 and subsequent versions, a conversion can be carried out through java.time.Instant.- Conversion from
java.time.LocalDateTimetojava.util.Date.
LocalDateTime localDateTime = LocalDateTime.now();
Instant instant = localDateTime.toInstant(ZoneOffset.ofHours(9));
Date date = Date.from(instant);
- Conversion from
java.util.Datetojava.time.LocalDateTime.
Date date = new Date();
Instant instant = date.toInstant();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
Note
Since
java.time.LocalTimeandjava.time.LocalDatedo not contain Instant values, it is necessary to convert once tojava.time.LocalDateTime.
7.3.2.3.3. Interoperability with java.sqlpackage¶
java.sql package from Java8 version and a method for mutual conversion with java.time package is defined.- Conversion from
java.sql.Datetojava.time.LocalDate.
java.sql.Date date = new java.sql.Date(System.currentTimeMillis());
LocalDate localDate = date.toLocalDate();
- Conversion from
java.time.LocalDatetojava.sql.Date.
LocalDate localDate = LocalDate.now();
java.sql.Date date = java.sql.Date.valueOf(localDate);
- Conversion from
java.sql.Timetojava.time.LocalTime.
java.sql.Time time = new java.sql.Time(System.currentTimeMillis());
LocalTime localTime = time.toLocalTime();
- Conversion from
java.time.LocalTimetojava.sql.Time.
LocalTime localTime = LocalTime.now();
java.sql.Time time = java.sql.Time.valueOf(localTime);
- Conversion from
java.sql.Timestamptojava.time.LocalDateTime.
java.sql.Timestamp timestamp = new java.sql.Timestamp(System.currentTimeMillis());
LocalDateTime localDateTime = timestamp.toLocalDateTime();
- Conversion from
java.time.LocalDateTimetojava.sql.Timestamp.
LocalDateTime localDateTime = LocalDateTime.now();
java.sql.Timestamp timestamp = java.sql.Timestamp.valueOf(localDateTime);
7.3.2.3.4. How to use org.terasoluna.gfw.common.date package¶
java.time.LocalDate can be generated by using org.terasoluna.gfw.common.date.ClassicDateFactory and java.sql.Date as an interim measure.java.time.LocalDate even for the java.time.LocalTime and java.time.LocalDateTime classes.bean definition file ([projectname]-env.xml)
<bean id="dateFactory" class="org.terasoluna.gfw.common.date.DefaultClassicDateFactory" />
Java class
@Inject
ClassicDateFactory dateFactory;
public DateFactorySample getSystemDate() {
java.sql.Date date = dateFactory.newSqlDate();
LocalDate localDate = date.toLocalDate();
// omitted
}
Note
Date Factory corresponding to Date and Time API will be added later.
7.3.2.3.5. Format for the string¶
toString method and a method which uses java.time.fomat.DateTimeFormatter can be used for converting the object containing date and time information to string.java.time.fomat.DateTimeFormatter.java.time.fomat.DateTimeFormatter consists of a method which uses a formatter of predefined ISO pattern and a method which is used by defining a format of any pattern.DateTimeFormatter formatter1 = DateTimeFormatter.BASIC_ISO_DATE;
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("G uuuu/MM/dd E")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT);
Locale and ResolverStyle (strict) can be defined besides string format.Locale changes depending on the system, it should be set at the time of initialization.ResolverStyle (strict) uses ofPattern method, ResolverStyle.SMART is set as default, however, in this guideline, it is recommended to specify ResolverStyle.STRICT for strict interpretation of date to avoid occurrence of unexpected behaviour.(When ISO pattern formatter is to be used, ResolverStyle.STRICT is specified.)yyyy in Date and Time API represent year in the calendar, interpretation will be different according to the calendar. (Year will be 2015 according to Western calendar but will be 0027 according to Japanese calendar).uuuu format instead of yyyy format.For the defined format list, refer DateTimeFormatter .DateTimeFormatter formatter1 = DateTimeFormatter.BASIC_ISO_DATE;
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("G uuuu/MM/dd E")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT);
LocalDate localDate1 = LocalDate.of(2015, 12, 25);
// "2015-12-25"
System.out.println(localDate1.toString());
// "20151225"
System.out.println(formatter1.format(localDate1));
// "Western calendar 2015/12/25 Friday"
System.out.println(formatter2.format(localDate1));
fmt:formatDate tag of JSTL handles only java.util.Date and java.util.TimeZone objects,Controller class
@Controller
public class HomeController {
@RequestMapping(value = "/", method = {RequestMethod.GET, RequestMethod.POST})
public String home(Model model, Locale locale) {
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuuu/MM/dd")
.withLocale(locale)
.withResolverStyle(ResolverStyle.STRICT);
LocalDate localDate1 = LocalDate.now();
model.addAttribute("currentDate", localDate1.toString());
model.addAttribute("formattedCurrentDateString", dateFormatter.format(localDate1));
// omitted
}
}
jsp file
<p>currentDate = ${f:h(currentDate)}.</p>
<p>formattedCurrentDateString = ${f:h(formattedCurrentDateString)}.</p>
Output results example (html)
<p>currentDate = 2015-12-25.</p>
<p>formattedCurrentDateString = 2015/12/25.</p>
7.3.2.3.6. Path from the string¶
java.time.fomat.DateTimeFormatter.DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("uuuu/MM/dd")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT);
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("HH:mm:ss")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT);
LocalDate localDate = LocalDate.parse("2015/12/25", formatter1);
LocalTime localTime = LocalDate.parse("14:09:20", formatter2);
7.3.2.4. Date operation¶
7.3.2.4.1. Date and time calculation¶
plus method and minus method are provided for calculating date and time.- Example for calculating time.
LocalTime localTime = LocalTime.of(20, 30, 50);
LocalTime plusHoursTime = localTime.plusHours(2);
LocalTime plusMinutesTime = localTime.plusMinutes(10);
LocalTime minusSecondsTime = localTime.minusSeconds(15);
- Example for calculating date.
LocalDate localDate = LocalDate.of(2015, 12, 25);
LocalDate plusYearsDate = localDate.plusYears(10);
LocalDate minusMonthsTime = localDate.minusMonths(1);
LocalDate plusDaysTime = localDate.plusDays(3);
Note
If a negative number is passed in the
plusmethod, results similar to the results at the time of usingminusmethod can be obtained. Same forminusmethod.
7.3.2.4.2. Date and time comparison¶
- Example for comparison of time.
LocalTime morning = LocalTime.of(7, 30, 00);
LocalTime daytime = LocalTime.of(12, 00, 00);
LocalTime evening = LocalTime.of(17, 30, 00);
daytime.isBefore(morning); // false
morning.isAfter(evening); // true
evening.equals(LocalTime.of(17, 30, 00)); // true
daytime.isBefore(daytime); // false
morning.isAfter(morning); // false
- Example for comparison of date.
LocalDate may = LocalDate.of(2015, 6, 1);
LocalDate june = LocalDate.of(2015, 7, 1);
LocalDate july = LocalDate.of(2015, 8, 1);
may.isBefore(june); // true
june.isAfter(july); // false
july.equals(may); // false
may.isBefore(may); // false
june.isAfter(june); // false
Interval of Joda Time currently does not exist in Date and Time API.7.3.2.4.3. Determination of date and time¶
- When a valid date and time string is to be determined, it can be determined based on the occurrence and non-occurrence of
java.time.format.DateTimeParseException.
String strDateTime = "aabbcc";
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HHmmss")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT);;
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuMMdd")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT);;
try {
// DateTimeParseException
LocalTime localTime = LocalTime.parse(strDateTime, timeFormatter);
}
catch (DateTimeParseException e) {
System.out.println("Invalid time string !!");
}
try {
// DateTimeParseException
LocalDate localDate = LocalDate.parse(strDateTime, dateFormatter);
}
catch (DateTimeParseException e) {
System.out.println("Invalid date string !!");
}
- When a leap year is to be determined,
isLeapYearmethod ofjava.time.LocalDatecan be used.
LocalDate date1 = LocalDate.of(2012, 1, 1);
LocalDate date2 = LocalDate.of(2015, 1, 1);
date1.isLeapYear(); // true
date2.isLeapYear(); // false
7.3.2.4.4. Fetching year, month, day, hours, minutes, seconds¶
get method.LocalDate localDate = LocalDate.of(2015, 2, 1);
// 2015
int year = localDate.getYear();
// 2
int month = localDate.getMonthValue();
// 1
int dayOfMonth = localDate.getDayOfMonth();
// 32 ( day of year )
int dayOfYear = localDate.getDayOfYear();
7.3.2.5. Japanese calendar (JapaneseDate)¶
java.time.chrono.JapaneseDate is provided in Date and Time API to handle Japanese calendar.Note
java.time.chrono.JapaneseDatecannot be used before Meiji 6 (1873 of Western calendar) when the Gregorian calendar was introduced.
7.3.2.5.1. Fetching Japanese calendar¶
java.time.LocalDate, Japanese calendar can be fetched by using now method and of method.java.time.chrono.JapaneseEra class.JapaneseDate japaneseDate1 = JapaneseDate.now();
JapaneseDate japaneseDate2 = JapaneseDate.of(2015, 12, 25);
JapaneseDate japaneseDate3 = JapaneseDate.of(JapaneseEra.HEISEI, 27, 12, 25);
// DateTimeException
JapaneseDate japaneseDate = JapaneseDate.of(1500, 1, 1);
7.3.2.5.2. Format for the string¶
java.time.fomat.DateTimeFormatter. While using, calendar is set to java.time.chrono.JapaneseChronology by using DateTimeFormatter#withChronology method.DateTimeFormatter formatter = DateTimeFormatter.ofPattern("GppyYearppMMonthppdDay")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(JapaneseChronology.INSTANCE);
JapaneseDate japaneseDate = JapaneseDate.of(1992, 1, 1);
// "Heisei YY4 MM1 DD1"
System.out.println(formatter.format(japaneseDate));
7.3.2.5.3. Path from the string¶
java.time.chrono.JapaneseDate by using java.time.fomat.DateTimeFormatter.DateTimeFormatter formatter = DateTimeFormatter.ofPattern("GyYearMMMonthddDate")
.withLocale(Locale.JAPANESE)
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(JapaneseChronology.INSTANCE);
JapaneseDate japaneseDate1 = JapaneseDate.from(formatter.parse("Heisei 27YY12MM25DD"));
JapaneseDate japaneseDate2 = JapaneseDate.from(formatter.parse("Meiji YY6MM01DD01"));
7.3.2.5.4. Conversion of Western and Japanese calendar¶
java.time.LocalDate by using from method.LocalDate localDate = LocalDate.of(2015, 12, 25);
JapaneseDate jpDate = JapaneseDate.from(localDate);
