background
java's date and time API design is not ideal. java 8 introduces a new time and date API to solve this problem.
The core class of the old date API | shortcoming |
---|---|
Date | Month starts from 0, year minimum starts from 1900, there is no concept of time zone |
Calendar | Month starts from 0 |
DateFormat | Thread unsafe |
Other | It is difficult to choose Date and Calendar at the same time; both Date and Calendar classes are mutable, thus maintaining nightmares |
Java 8 introduces new features like joda time. The core classes are as follows:
LocalDate
Identify the date. Here is the translation of javadoc:
The date has no time zone and is under the ISO-8601 calendar system. For example: December 3, 2007
It is an immutable Date object, which is usually expressed as year, month and day. Other date fields such as dayofyear, DayOfWeek and weekofyear can also be accessed.
LocalDate.now().get(ChronoField.ALIGNED_WEEK_OF_YEAR);
For example, October 2, 2007 can be stored in LocalDate.
This class does not store or represent time or time zone.
Instead, it describes the date, for example, it can be used to represent the birthday. It can't represent an instant without additional information on the time line, such as an offset of the latter time zone.
This is a value based class. Using identity sensitive operations, such as = =, hashCode(), or synchronization of LocalDate objects, may have unpredictable results and should be avoided. The equals method should be used for comparison.
This class is immutable and thread safe.
//Here is the original javadoc. I have deleted the unimportant content. /** * A date without a time-zone in the ISO-8601 calendar system, * such as {@code 2007-12-03}. * <p> * {@code LocalDate} is an immutable date-time object that represents a date, * often viewed as year-month-day. Other date fields, such as day-of-year, * day-of-week and week-of-year, can also be accessed. * For example, the value "2nd October 2007" can be stored in a {@code LocalDate}. * <p> * This class does not store or represent a time or time-zone. * Instead, it is a description of the date, as used for birthdays. * It cannot represent an instant on the time-line without additional information * such as an offset or time-zone. * <p> * This is a <a href="{@docRoot}/java/lang/doc-files/ValueBased.html">value-based</a> * class; use of identity-sensitive operations (including reference equality * ({@code ==}), identity hash code, or synchronization) on instances of * {@code LocalDate} may have unpredictable results and should be avoided. * The {@code equals} method should be used for comparisons. * This class is immutable and thread-safe. public final class LocalDate implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable
There are four construction methods:
Types of construction methods | Explain |
---|---|
Class of | There are four, of (int year, int month, int day), of (int year, month month, int day), of year day (int year, int day of year), of epoch day (long epoch day), January 1, 1970 as the first year of machines |
Class now 3 | In fact, overloading now(Clock clock), the other two now(), now(ZoneId zoneId) get the date that the machine always takes in one time zone, and then call ofEpochday(long epochDay) to initialize date. |
Class from 1 | From (temporalaccessor temporary) initializes the date through a Temporal object. For specific usage, see the example |
Class parse 2 | Paste (string date), parse (string date, datetimeformatter formater) initializes the date as a string |
Get class method:
Get class method | Explain |
---|---|
getYear() | Year of acquisition |
getMonthValue() | Get month value |
getMonth() | Get month object |
getDayOfMonth | Get the day value of the month |
getDayOfWeek | Get weeks of the week |
package com.test.time; import java.time.LocalDate; import java.time.chrono.ChronoLocalDate; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import java.util.Objects; /** * Description: Study of localDate class * @author carter * Creation time: 15:31, November 11, 2019 **/ public class LocalDateTest { public static void main(String[] args) { LocalDate localDate = LocalDate.of(2019,11,11); print("localDate.getYear()",localDate.getYear()); print("localDate.getMonth().getValue()",localDate.getMonth().getValue()); print("localDate.lengthOfMonth()",localDate.lengthOfMonth()); print("localDate.getMonthValue()",localDate.getMonthValue()); print("localDate.getDayOfMonth()",localDate.getDayOfMonth()); print("localDate.getDayOfWeek().getValue()",localDate.getDayOfWeek().getValue()); print("localDate.getDayOfYear()",localDate.getDayOfYear()); print("localDate.lengthOfYear()",localDate.lengthOfYear()); print("localDate.getChronology()",localDate.getChronology()); print("localDate.getEra()",localDate.getEra()); print("localDate.isLeapYear()",localDate.isLeapYear()); final LocalDate localDateNow = LocalDate.now(); print("localDateNow.atStartOfDay()",localDateNow.atStartOfDay()); final LocalDate localDateOfEpo = LocalDate.ofEpochDay(1L); print("localDateOfEpo.format(DateTimeFormatter.BASIC_ISO_DATE)",localDateOfEpo.format(DateTimeFormatter.BASIC_ISO_DATE)); final LocalDate localDateFrom = LocalDate.from(new TemporalAccessor() { @Override public boolean isSupported(TemporalField field) { return true; } @Override public long getLong(TemporalField field) { //This actually sets the epoch day, which is the incremental date of the machine return 2; } }); print("localDateFrom.format(DateTimeFormatter.BASIC_ISO_DATE)",localDateFrom.format(DateTimeFormatter.BASIC_ISO_DATE)); final LocalDate localDateParse = LocalDate.parse("2019-11-11"); print("localDateParse.format(DateTimeFormatter.BASIC_ISO_DATE)",localDateParse.format(DateTimeFormatter.BASIC_ISO_DATE)); } private static void print(String title,Object printContent){ System.out.println(title + " : " + Objects.toString(printContent)); } }
Output:
localDate.getYear() : 2019
localDate.getMonth().getValue() : 11
localDate.lengthOfMonth() : 30
localDate.getMonthValue() : 11
localDate.getDayOfMonth() : 11
localDate.getDayOfWeek().getValue() : 1
localDate.getDayOfYear() : 315
localDate.lengthOfYear() : 365
localDate.getChronology() : ISO
localDate.getEra() : CE
localDate.isLeapYear() : false
localDateNow.atStartOfDay() : 2019-11-12T00:00
localDateOfEpo.format(DateTimeFormatter.BASIC_ISO_DATE) : 19700102
localDateFrom.format(DateTimeFormatter.BASIC_ISO_DATE) : 19700103
localDateParse.format(DateTimeFormatter.BASIC_ISO_DATE) : 20191111
Other methods will not be explored first, but will be studied later. First of all, this code reference is proposed.
LocalTime
Similar to LocalDate and javadoc, the difference is that the value it can mark is usually expressed in minutes and seconds, which can be accurate to nanoseconds.
It is initialized by obtaining the time, minute, second and nanosecond part of the machine time.
package com.test.time; import java.time.LocalDate; import java.time.LocalTime; /** * Description: Research on localTime class * @author carter * Creation time: 10:35, November 12, 2019 **/ public class LocalTimeTest { public static void main(String[] args) { final LocalTime localTime = LocalTime.of(12, 0, 0, 0); System.out.println(localTime); System.out.println( "LocalTime.hour"+ " : "+localTime.getHour()); System.out.println( "LocalTime.getMinute"+ " : "+localTime.getMinute()); System.out.println( "LocalTime.getSecond"+ " : "+localTime.getSecond()); System.out.println( "LocalTime.getNano"+ " : "+localTime.getNano()); System.out.println( "LocalTime.MIDNIGHT"+ " : "+LocalTime.MIDNIGHT); System.out.println("LocalTime.NOON"+ " : "+LocalTime.NOON); System.out.println("LocalTime.MIN"+ " : "+LocalTime.MIN); System.out.println("LocalTime.MAX"+ " : "+LocalTime.MAX); } }
LocalDateTime
It is a combination of localdate and Localtime, indicating the date and time.
package com.test.time; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; import java.time.ZoneOffset; /** * Description: a simple study of localdatetime * @author carter * Creation time: 10:47, November 12, 2019 **/ public class LocalDateTimeTest { public static void main(String[] args) { LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime.getYear()" + " : " + localDateTime.getYear()); System.out.println("localDateTime.getMonthValue()" + " : " + localDateTime.getMonthValue()); System.out.println("localDateTime.getDayOfMonth()" + " : " + localDateTime.getDayOfMonth()); System.out.println("localDateTime.getHour()" + " : " + localDateTime.getHour()); System.out.println("localDateTime.getMinute()" + " : " + localDateTime.getMinute()); System.out.println("localDateTime.getSecond()" + " : " + localDateTime.getSecond()); System.out.println("localDateTime.getNano()" + " : " + localDateTime.getNano()); final LocalDateTime ofEpochSecond = LocalDateTime.ofEpochSecond(System.currentTimeMillis() / 1000, 0,ZoneOffset.ofHours(8)); System.out.println("ofEpochSecond" + " : " + ofEpochSecond); //Get localdate and Localtime through localdatetime, or get localdatetime through localdate and Localtime final LocalDate localDate = localDateTime.toLocalDate(); final LocalTime localTime = localDateTime.toLocalTime(); System.out.println("localDate" + " : " + localDate); System.out.println("localTime" + " : " + localTime); final LocalDateTime localDateTimeFromLocalDate = localDate.atTime(LocalTime.MIN); final LocalDateTime localDateTimeFromLoalTime = localTime.atDate(LocalDate.now()); System.out.println("localDateTimeFromLocalDate" + " : " + localDateTimeFromLocalDate); System.out.println("localDateTimeFromLoalTime" + " : " + localDateTimeFromLoalTime); } }
Instant
Time model of the machine: it is calculated by the number of seconds experienced by the machine on January 1, 1970; it is equivalent to LocalDateTime. However, it can only obtain seconds and nanoseconds from it, and cannot obtain the time of month, day, hour, minute, etc.
package com.test.time; import java.time.Instant; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; /** * Description: TODO * @author carter * Creation time: 11:08, November 12, 2019 **/ public class InstanceTest { public static void main(String[] args) { Instant instant1 = Instant.ofEpochSecond(3); Instant instant2 = Instant.ofEpochSecond(2,1000000000); System.out.println("instant1" + " : " + instant1); System.out.println("instant2" + " : " + instant2); System.out.println(instant1.get(ChronoField.DAY_OF_YEAR)); } }
instant1 : 1970-01-01T00:00:03Z
instant2 : 1970-01-01T00:00:03Z
Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfYear
at java.time.Instant.get(Instant.java:566) at com.test.time.InstanceTest.main(InstanceTest.java:25)
Localdate and localtime.localdatetime.instant all implement the Temporal interface, which can read and set the time. The next duration and period are modeled based on two Temporal interfaces.
Duration
It mainly obtains the units of seconds and nanoseconds, and cannot calculate the time difference of LocalDate;
Construction method:
Types of construction methods | Explain |
---|---|
of series | Of days (long days), of hours (long hours), of minutes (long minutes), of seconds (long seconds), of seconds (long seconds, long nano), of milis (long mins), of nanos (long nanos), of (long time, temporalunit) are finally overloaded by of method |
Class from | from(TemporalAmount amount) |
Class parse | |
Class between | Difference between two temporals |
package com.test.time; import java.time.Duration; import java.time.LocalDateTime; import java.time.Period; import java.time.temporal.ChronoUnit; import java.time.temporal.Temporal; import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalUnit; import java.util.Arrays; import java.util.List; /** * Description: Duration * @author carter * Creation time: 13:09, November 12, 2019 **/ public class DurationTest { public static void main(String[] args) { final Duration duration = Duration.between(LocalDateTime.of(1988, 1, 2, 0, 0, 0), LocalDateTime.now()); System.out.println("duration "+ " : " + duration); System.out.println("duration.toDays() "+ " : " + duration.toDays()); System.out.println("duration.toHours() "+ " : " + duration.toHours()); System.out.println("duration.toMinutes() "+ " : " + duration.toMinutes()); final Duration durationHours = Duration.ofHours(1); System.out.println("durationHours "+ " : " + durationHours); System.out.println("durationHours.toHours() "+ " : " + durationHours.toHours()); System.out.println("durationHours.toMinutes() "+ " : " + durationHours.toMinutes()); System.out.println("durationHours.getSeconds() "+ " : " + durationHours.getSeconds()); final Duration fromDuration = Duration.from(Duration.ofDays(1)); System.out.println(":" + fromDuration); final Duration durationParse = Duration.parse("PT279301H32M6.488S"); System.out.println(durationParse); } }
duration : PT279301H32M50.61S duration.toDays() : 11637 duration.toHours() : 279301 duration.toMinutes() : 16758092 durationHours : PT1H durationHours.toHours() : 1 durationHours.toMinutes() : 60 durationHours.getSeconds() : 3600 :PT24H PT279301H32M6.488S
Period
The difference of year, month and day can be obtained;
package com.test.time; import java.time.LocalDate; import java.time.Period; import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalUnit; /** * Description: TODO * @author carter * Creation time: 13:04, November 12, 2019 **/ public class TestPeriod { public static void main(String[] args) { final Period period = Period.between(LocalDate.of(1988, 1, 2), LocalDate.now()); System.out.println(period); System.out.println(period.getYears()); System.out.println(period.getMonths()); System.out.println(period.getDays()); System.out.println(period.get(ChronoUnit.DAYS)); System.out.println( period.toTotalMonths()); } }
ChronoUnit
It can also be used to calculate the difference value without limitation.
final long daysBetween = ChronoUnit.YEARS.between(LocalDate.of(1988, 1, 2), LocalDate.now()); System.out.println(daysBetween);
Manipulating and formatting dates
Operation class | Explain |
---|---|
Class with | Set the value of time, with (chronofield field, long newvalue) |
plus | How many time units to add |
minus | How much time to lose |
with(TemproalAdjuster adjuster)
Provides a quick way to set the time.
Fast method | Explain |
---|---|
firstDayOfMonth | Set to the first day of the month |
lastDayOfMonth | Set to the last day of the month |
firstDayOfNextMonth | The first day of next month |
firstDayOfYear | The first day of |
lastDayOfYear | The last day of |
firstDayOfNextYear | The first day of next year |
lastInMonth | The last one in line with the day of the week |
package com.test.time; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.FormatStyle; import java.time.temporal.ChronoField; import java.time.temporal.TemporalAdjusters; import java.time.temporal.TemporalField; /** * Description: Date operation and formatting * @author carter * Creation time: 13:58, November 12, 2019 **/ public class OpTest { public static void main(String[] args) { final LocalDate localDate = LocalDate.now().withYear(1988).withDayOfYear(2).with(ChronoField.MONTH_OF_YEAR, 2L); System.out.println(localDate); final LocalTime localTime = LocalTime.now().plusHours(1).plusHours(1).plusMinutes(10); System.out.println(localTime); final LocalDate localDate1 = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()); System.out.println(localDate1); final LocalDate localDate2 = LocalDate.now().with(TemporalAdjusters.firstInMonth(DayOfWeek.FRIDAY)); System.out.println("First Friday of the month:" + localDate2); final LocalDate localDate3 = LocalDate.now().with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY)); System.out.println("Last Friday of the month:" + localDate3); final LocalDate localDate4 = LocalDate.now().withDayOfMonth(15); System.out.println( localDate4 + "The next working day is: " + localDate4.with(getNextWorkDay(localDate4))); System.out.println(localDate4.format(DateTimeFormatter.ofPattern("YYYY-MM-dd"))); System.out.println(localDate4.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL))); System.out.println(localDate4.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG))); System.out.println(localDate4.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM))); System.out.println(localDate4.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))); System.out.println(localDate4.format(new DateTimeFormatterBuilder().appendText(ChronoField.YEAR).appendLiteral("====").appendText(ChronoField.MONTH_OF_YEAR).toFormatter())); } public static LocalDate getNextWorkDay(LocalDate localDate) { return localDate.with(TemporalAdjusters.ofDateAdjuster((temp) -> { final DayOfWeek dayOfWeek = temp.getDayOfWeek(); if (dayOfWeek.getValue() == 5) { return temp.plusDays(3); } else if (dayOfWeek.getValue() == 6) { return temp.plusDays(2); } else { return temp.plusDays(1); } })); } }
Handling different time zones
Time is relative to the time zone, which is divided into the same standard time intervals according to certain rules. After getting a time zone, zoneId can be combined with localdate, localdatetime and instant to construct a zonedatetime
package com.test.time; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.TimeZone; /** * Description: TODO * @author carter * Creation time: 14:52, November 12, 2019 **/ public class ZoneTest { public static void main(String[] args) { ZoneId zoneId = TimeZone.getDefault().toZoneId(); System.out.println(zoneId); final ZoneId zoneId1 = ZoneId.of("Asia/Shanghai"); System.out.println(zoneId1.toString()); //LocalDateTime and Instant are converted to each other; LocalDateTime localDateTime = LocalDateTime.now(); final ZoneOffset zoneOffset = ZoneOffset.of("+8"); Instant instant = localDateTime.toInstant(zoneOffset); System.out.println(localDateTime); System.out.println(instant); LocalDateTime localDateTime1 = LocalDateTime.ofInstant(instant,ZoneId.systemDefault()); System.out.println(localDateTime1); //Time zone based date1 ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDateTime.now(),ZoneId.systemDefault()); System.out.println(zonedDateTime); //Time zone based date2 OffsetDateTime offsetDateTime = OffsetDateTime.of(LocalDateTime.now(),zoneOffset); System.out.println(offsetDateTime); } }
Dealing with different calendar systems
ISO-8601 calendar system is the fact standard of world civilization calendar system. However, there are four other calendar systems available in Java 8. Each of these calendar systems has a corresponding log class, namely, Thai buddhistdate, MinguoDate, Japanese date and HijrahDate.
//Buddhist date of Thailand final ThaiBuddhistDate thaiBuddhistDate = ThaiBuddhistDate.from(LocalDateTime.now()); System.out.println(thaiBuddhistDate); //Date of Republic of China final MinguoDate minguoDate = MinguoDate.from(LocalDateTime.now()); System.out.println(minguoDate);
Summary
The old version of date and calendar before java8 has many design defects. The api designed by ourselves should be out of the stage of history.
In the new version of date API, the date is immutable and thread safe;
The new version of the date API identifies the time in a way that distinguishes people and machines;
You can change the date flexibly, or you can use the more flexible TemporalAdjuster to operate the date
You can use the hour time zone relative to the deviation of a time zone and location from Greenwich mean time, and apply it to date and time objects for localization
Original is not easy, reprint please indicate the source, welcome to communicate.