java8 LocalDateTime ZoneDateTime OffsetTime

Time:2021-9-23

time zone
The earth rotates from west to East. The sun is seen in the East before the west, and the time in the East is earlier than that in the West. In order to unify world time, the regulations of the international longitude conference in 1884 stipulated that the world was divided into 24 time zones (12 time zones in the East and 12 time zones in the West). It is stipulated that the United Kingdom (the former site of Greenwich Observatory) is in the zero time zone (GMT + 00), East 1-12, West 1-12, and Beijing, China is in East 8 (GMT + 08).
If the UK time is 6:00 sharp, GMT time is 6:00 sharp and Beijing time is 14:00 sharp.
Time zone ID
Zoneid is the time zone ID, such as Europe / Paris, which represents the time zone of Paris, Europe
GMT and UTC
GMT, Greenwich mean time, or universal time. Noon in GMT refers to the time when the sun crosses the Greenwich meridian (primary meridian). However, due to the uneven and irregular rotation of the earth, GMT is not accurate, and it is no longer used as the world standard time.

UTCCoordinated universal time. UTC is a time measurement system based on atomic time and second length, which is as close as possible to GMT in time. To ensure that UTC does not differ from GMT by more than 0.9 seconds, positive or negative leap seconds will be added to UTC if necessary. UTC is now used as world standard time.

So,UTC is basically equivalent to GMT, the error shall not exceed 0.9 seconds.

UNIX timestamp
The UNIX timestamp in the computer is the number of seconds from GMT / UTC time “1970-01-01t00:00:00” to the specific time, regardless of leap seconds. Of course, this is to simplify the complexity of computer time operation.

For example, the current system time of my computer is 15:43:0 on February 27, 2015. Because the default time zone of my computer is East Zone 8, the time in Zone 0 is 7:43:0 on February 27, 2015, and the UNIX timestamp is 1425022980 seconds.
thereforeThe time of time zone or offset information can be compared with UTC time, the time difference can be calculated, and the time stamp can be calculated.

Offset vs time zone (zoneoffset vs zoneid)

Offset (offset from UTC) offset from UTC only records hours, minutes and seconds, and there is no other information. For example, + 08:00 means eight hours ahead of UTC, while – 05:45 means five hours and 45 minutes behind UTC.

The time zone is a historical collection of past, present and future offsets for people in a specific area. Anomalies such as daylight saving time will cause the offset in a specific time period to change over time, whether it has occurred in the past or the changes announced by politicians in the future.

The time zone is offset, and a set of rules are added to deal with exceptions for the history in a specific area, such as daylight saving time (DST), resulting in changes in the offset of time over a specific time period.

Time zone = (offset history + exception rule)

Therefore, it is better to use the area when you know it.

The offset in many areas will change with time. For example, daylight saving time in the United States will lead to an offset of one hour from the original basis in about half a year, and then adjust back to the offset of one hour in the second half of the year. The meaning of time zone is to record all these situations that will cause offset.

So,The offset calculated without date is meaningless。 For example, the offset of French time (Europe / Paris) is + 01:00 in a small part of the year, while the offset of most time (from the end of March to the end of October) is + 02:00 due to daylight saving time.

//Specified area, construction time: current time of Paris time, France, DST in May, offset + 2

LocalDateTime now = LocalDateTime.of(LocalDate.of(2020, 5, 31), LocalTime.now())
ZonedDateTime zonedDateTime = ZonedDateTime.of(now, ZoneId.of("Europe/Paris"));
zonedDateTime.getOffset(); // +02:00

//In February manually adjusted, there is no DST at this time, and the offset is + 1

ZonedDateTime thirdMonth = zonedDateTime.minusMonths(3);
thirdMonth.getOffset(); // +01:00

Get the current default time zone ID of the JVM:

ZoneId.systemDefault()

Get the current default offset of the JVM:

 ZoneOffset offset = ZonedDateTime.now().getOffset();
 ZoneOffset offset = OffsetDateTime.now().getOffset();

● instant represents the time stamp, such as 2016-04-14t14:20:13.592z,Instant has no time zone, which can be obtained from the java.time.clock class, such as:

Instant current = Clock.system(ZoneId.of("Asia/Tokyo")).instant();

Clock: clock, such as getting the current time in New York, USA
The clock class provides methods to access the current date and time,Clock is time zone sensitive, can be used instead of system. Currenttimemillis() to get the current microseconds. A specific point in time can also be represented by the instant class, which can also be used to create the old java.util.date object.

Clock clock = Clock.systemDefaultZone();

long millis = clock.millis();

Instant instant = clock.instant();

● localdate refers to the date without time, such as 2021-04-14.

● Localtime – it represents the time without date, such as 19:23:01.438.

● localdatetime – it contains time and date, but there is no offset with time zone, such as 2021-04-27t19:30:42.749.

● zoneddatetime – this is a complete time with time zone, which is adjusted according to UTC / Greenwich mean time
For example, 2021-04-27t19:31:43.090 + 08:00 [Asia / Shanghai]
Since zoneddatetime contains time zone information, zoneid must be specified to construct or convert zoneddatetime,
For example, localdatetime is as follows:

LocalDateTime localDateTime = LocalDateTime.now();
//Zoneid needs to be specified to convert localdatetime to zoneddatetime
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
//To convert zoneddatetime to localdatetime, you only need to remove the zoneid contained in zoneddatetime
LocalDateTime localDateTime2 = zonedDateTime.toLocalDateTime();

Instant also has no time zone information, so zoneid should also be specified to construct zoneddatetime from instant. An example is as follows:

ZonedDateTime.ofInstant(Instant.now(),ZoneId.systemDefault())

Clock is the time zone information, so it is not necessary to specify zoneid to construct zoneddatetime from clock. An example is as follows:

ZonedDateTime.now(Clock.systemDefaultZone());

Zoneddatetime example: 2021-04-27t19:31:43.090 + 08:00 [Asia / Shanghai], which includes not only localdatetime and zoneid, but also zoneoffset. However, zoneoffset is not specified when constructing zoneddatetime. Why?

Zoneoffset can also be passed in in zonedatetime. The example is as follows:

ZoneOffset offset = OffsetDateTime.now().getOffset();// My local is Shanghai, and the offset is (+ 8)
ZonedDateTime zonedDateTime2 = ZonedDateTime.ofInstant(localDateTime, zoneOffset, ZoneId.systemDefault());//2021-04-27T20:21:35.300+08:00[Asia/Shanghai]

Can you transfer other values, such as + 9? It must be possible. Examples are as follows:

 ZoneOffset zoneOffset3 = ZoneOffset.of("+09:00");
 ZonedDateTime zonedDateTime3 = ZonedDateTime.ofInstant(localDateTime, zoneOffset3, ZoneId.systemDefault());//2021-04-27T19:21:35.300+08:00[Asia/Shanghai]

You can see that compared with the above, the time is not 20 o’clock, but 19 o’clock. If you want to convert localdatetime to zonedatetime, it is wrong, soIt's better not to call this method. It's better to call the method without offset parameter. It's not clear what scenario this method will be called. If there is any guidance from the great God, I'd be grateful.
So the above answer is: zoneid determines how and when the offset changes. You cannot set the offset freely because the area controls which offsets are valid.

● the offsetdatetime class actually contains localdatetime and zoneoffset. It is used to represent a complete date (month, year, day) and time (hour, minute, second, nanosecond) including the Greenwich mean time offset (+ / – hour: minute, such as + 06:00 or – 08:00), but does not include the time zone ID. For example: 2021-04-29t15:37:11.331 + 08:00
Therefore, if the date without time zone or offset information is converted to offsetdatetime, you need to specify zoneid or offset

//Instantto OffsetDateTime
OffsetDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
//LocalDateTime to OffsetDateTime
LocalDateTime.now().atOffset(OffsetDateTime.now().getOffset())
perhaps
OffsetDateTime.of(LocalDateTime.now(),OffsetDateTime.now().getOffset())

Difference between zoneddatetime and offsetdatetime

ZonedDateTime:

● store all date and time fields with accuracy of nanosecond, time zone and area offset to deal with fuzzy local date and time

● the offset cannot be set freely because the area controls the valid offset value

● fully support DST and handle daylight saving time adjustment

● it is very convenient to display the date and time field in the user's specific time zone

OffsetDateTime:

● store all date and time fields with nanosecond accuracy and offset from GMT / UTC (no time zone information)

● it should be used to store dates in the database or communicate over the network

Clock is time zone information, so it is not necessary to specify zoneid to construct offsetdatetime from clock. An example is as follows:

OffsetDateTime.now(Clock.systemDefaultZone());

When constructing offsetdatetime, you can also call its from (temporalaccessor temporary) method, but pay attention to the implementation class containing time zone or offset information, otherwise the operation will report an exception. The prompt message is similar to: “unable to obtain zoneoffset from temporalaccessor”

OffsetDateTime.from(OffsetDateTime.now());// correct
OffsetDateTime.from(ZonedDateTime.now());// correct
OffsetDateTime.from(LocalDateTime.now());// Operation error
OffsetDateTime.from(LocalTime.now());// Operation error
OffsetDateTime.from(LocalDate.now());// Operation error

Duration: calculates the interval between two “times”
Period: used to calculate the interval between two dates
Zoneoffset: time zone offset, for example: + 8:00
Zoneddatetime: you can get the date / time of a specific time zone

In short, 1. Time zone and offset can be converted, so they can be replaced sometimes, but try to use time zone zoneid
2. To convert a time zone free time into a time zone time, you need to specify zoneid. Conversely, it is not necessary.

Temporal interface, temporaladjuster interface and temporaladjusters tool class
Temporal can be expressed as date, time or a combination of both according to actual needs. Several implementation classes include:
Localdate – indicates a date without a time zone
Localdatetime – indicates a date and time without a time zone

Temporaladjuster is used for time correction. For example, you can get the last day of the current month and the first day of the next year. Generally, the with method of time and date is called, for example:

localDate.with(TemporalAdjusters.lastDayOfMonth());

The temporaladjusters tool class has many predefined temporaladjusters implementations.
For example:

Dayofweekenmonth() – a day of the week, for example, the second Tuesday in March
Firstdayofmonth() – the first day of the current month
Firstdayofnextmonth() – the first day of the next month
Firstdayofnextyear() – the first day of the next year
Firstdayofyear () – the first day of the year
Lastdayofmonth() – last day of the month
Nextorsame() – the next or day of the week

Customize the temporaladjuster implementation, such as obtaining the date 14 days later.

LocalDate localDate = LocalDate.of(2021, 04, 30);
 TemporalAdjuster temporalAdjuster = t -> t.plus(Period.ofDays(14));
 LocalDate result = localDate.with(temporalAdjuster);// Output 2021-05-14

Period and duration

LocalDate birthDay = LocalDate.of(2021, 02, 15);
 LocalDate localDate = LocalDate.now();
 //Difference between two dates
 Period period = Period.between(birthDay, localDate);
 //Get month or day from period
 period.getMonths(), period.getDays());
 //Plus 3 days
 birthDay.plus(Period.ofDays(3))//2021-02-18
 //Calculate time difference
 Instant instant = Instant.now();
 Instant instant1 = instant.plus(Duration.ofMinutes(2));
 Duration duration = Duration.between(instant, instant1);