❤️ About the author: Hello, I'm Xiao xuzhu. High quality creators in Java 🏆, CSDN blog expert 🏆
❤️ Technical work should be rewarded
❤️ give the thumbs-up 👍 Collection ⭐ Look again and form a habit
What is the JSR specification
Explanation from Baidu Encyclopedia:
JSR is the abbreviation of Java Specification Requests, which means Java specification proposal. It is a formal request to add a standardized technical specification to the JCP(Java Community Process). Anyone can submit a JSR to add new API s and services to the Java platform. JSR has become an important standard in the Java world.
What mysterious organization is JCP
JCP (Java Community Process) is an open international organization, mainly composed of Java developers and licensees
So the standardization of JAVA is reviewed and released by this organization. I feel it's really great.
What are the members of JCP? The fire of gossip is burning
Information obtained from the official website:
For the 2020 elections, two ratifications and one electoral seat will be eliminated, thereby reducing the EC to 18 members
After the 2020 grade election, there will be 11 approved seats, 4 elected seats, 2 quasi seats (for individuals) and permanent seats held by Oracle America. The members have a staggered tenure of two years, so 8 or 9 of the 17 seats usually need approval / election every year.
Let's look at the list of approvals and elections in 2020
Those underlined are those approved and elected in 2020.
Alibaba: Alibaba was selected, and domestic enterprises were selected into JCP. It's awesome.
BellSoft: BellSoft publishes and supports the free and secure Unified Java Runtime, Liberica JDK. It can be used on most platforms and today's architectures, including microservice based architectures.
BNY Mellon: more than 11000 technical experts and developers worldwide support the bank as a leading provider of clearing, payment, custody and asset management services in global financial markets.
Java community participation
-Active approving member of the JCP Executive Committee (EC)
-Proposed Java Collections 2.0
-Committed to Java education through the working group
-Lead Java user group
-Interact with the community through presentations, blogs, code seminars
-Open source participation
JetBrains: IDEA has used it. This product is developed by JetBrains.
MicroDoc: MicroDoc is a technology-oriented software development enterprise in Germany, which provides embedded Java virtual machines for the global customer base. MicroDoc is a supporter of open standards and commercially available open source software. It is an active contributor to OpenJDK. Since 2014, MicroDoc has occupied a place in JCP EC and decided to participate in the next election period to promote J The development of AVA focuses on embedded applications in automotive, healthcare and intelligent environments.
SAP SE: SAP has more than 250000 enterprise customers and is the world's leading commercial software supplier. A large number of these SAP customers run Java based sap. Sap has been involved in JCP since 2001 and has cooperated in more than 50 jsrs. Sap has contributed to OpenJDK since 2012. It currently participates in the OpenJDK 11 update project and provides sapmach Line, a free build of OpenJDK. Sap is committed to the continued success of Java.
London Java Community: London Java Community, representing the global JUG (London Java user group) community (400000 + developers). We run "adopt JSR" and "adopt OpenJDK" to improve developers' daily participation in Java standards.
Eclipse Foundation: the eclipse foundation has been participating in the JCP Executive Committee since 2007. As the seat of the Eclipse Java IDE, Jakarta EE, MicroProfile, adorium, Eclipse Java compiler and OpenJ9, we are very committed to the Java ecosystem. Our main contribution to JCP EC is to represent the interests of the open source community and the independent implementation of the Java specification.
Ken Fogel: I am a professor of computer science and technology at Dawson college in Montreal. The task of the program is to train students, mainly to become software developers preparing for work after graduating from high school. In 2019, I became Java Champion. Five years ago, I started a free one-day conference called DawsCon in Montreal. I attracted some of the best Speakers talk to students and the local developer community. I have also spoken at JavaOne/CodeOne over the past six years.
OK! The gossip is over and back to the point.
JSR specification content
Included in the standard set of three Java versions: JAVA SE, JAVA EE, and JAVA ME.
Some jsrs are included in one or more JAVA platforms.
The following is the corresponding official website address:
Click JAVA SE to come in and have a look
5 | The number of JSR, and the content of the same line is the name corresponding to the JSR number |
---|---|
Description: | Describe what this JSR is used for |
Status: | What is the current status of this JSR |
Latest Stage: | Latest stage |
Spec Lead: | Person in charge of specification |
Click the name corresponding to the JSR number to jump to the details page of the JSR content.
Status status:
Status | What it means |
---|---|
Active | Milestone jsrs have been released in the past 12 months. |
Final | JSR, which produced the final release milestone more than a year ago. |
Maintenance | The last JSR that produced a maintenance review or maintenance release milestone was more than a year ago |
Inactive | Jsrs that have not yet generated a final or maintenance version and have not released milestones last year |
Withdrawn | JSR withdrawn from the JCP by the specification owner prior to final release. |
Rejected | A JSR that has not been approved by the Executive Committee in one of the voting stages of the JSR |
Dormant | Jsrs voted "dormant" by the Executive Committee, or jsrs that have reached the end of their natural life |
Now you have a basic understanding of JSR.
JSR-310 introduction
Bloggers are studying the source code of JAVA date and time recently. Taking JSR-310 as the cut-off entrance, I will introduce JSR to you
Part I: timeline
JSR-310 took about 7 years from its inception to its release. From a small perspective, it can be seen that the release of each JSR is a fine product after careful polishing.
Part II: Team
List of specification principals and expert groups
Part III: development timeline details
Development timeline of JSR-310:
The API (JSR-310) is implemented by Stephen coleborne based on joda time project.
Stephen coleburne founded and led the joda time project and is a member of the Apache Software Foundation, focusing on Jakarta Commons. Michael Nascimento Santos founded and led the Genesis project and contributed to NetBeans, AspectWerkz and Thinlet. Michael also has five previous JSR experiences.
Part IV: Details
Description of JSR-310 specification (direct translation of official documents)
This JSR will provide java with a new and improved date and time API. The main goal is to provide a more advanced and comprehensive model for date and time operations, drawing on the lessons learned from the first two APIs of Java SE (date and calendar).
The new API will target all applications that require date and time data models. The model will override classes to replace dates and calendars, including representing dates without time, times without dates, durations, and intervals. This will improve the quality of the application code. For example, the date and time model will provide a class that explicitly defines it, instead of using int to store duration and using javadoc to describe it as days.
The new API will also address related date and time issues. These include formatting and parsing, taking into account the ISO8601 standard and its implementation, such as XML. In addition, the serialization and persistence domains will be considered.
The ultimate goal of the new API is simplicity and ease of use. The API will need to contain some powerful functionality, but it cannot obscure the standard use case. The easy-to-use part includes interaction with existing Date and Calendar classes, which will be the focus of the expert group.
Target Java platform
Java SE (Java EE also applies)
What will the proposed specification meet the needs of the Java community (direct translation of official documents)
- Currently, Java SE has two independent date and time APIs - java.util.date and java.util.Calendar. Java developers agree on blogs and forums that these two APIs are difficult to use. It is worth noting that both use the month index starting from 0, which is the cause of many errors. Over the years, calendars have also suffered from many errors and performance problems, mainly because they store their status internally in two different ways.
- A classic error (4639407) prevents the creation of certain dates in the Calendar object. You can write a series of code that can create dates in some years, but not in other years, preventing some users from entering the correct birth date. This is because the Calendar class only allows one hour of daylight saving time to be added in summer, while historically, it added two hours before and after World War II. Although this error has been fixed, if a country / region chooses to introduce a 3-hour daylight saving time gain in summer at some time in the future, the Calendar class will be destroyed again.
- The current Java SE API is also affected by a multithreaded environment. As we all know, immutable classes are thread safe in nature because their state cannot be changed. However, both Date and Calendar are variable, which requires programmers to explicitly consider cloning and threading. In addition, the lack of thread safety in DateTimeFormat is not well known and has become the cause of many thread problems that are difficult to track.
- Except for the problem of Java SE's datetime class, it has no classes for modeling other concepts. Non time zone date or time, duration, period, and interval are not represented by classes in Java se. Therefore, developers often use int to represent duration and javadoc to specify units.
- The lack of a comprehensive date and time model also makes many common operations more difficult than they should be. For example, calculating the number of days between two dates is a particularly difficult problem at present.
- The JSR will solve the problem of the complete date and time model, including date and time (with and without time zone), duration and time period, interval, format and parsing.
Part V: Download API and analysis
What is the core code contained in JSR-310
Download API document: as shown in the figure, click:
Select Download:
Open the index page
You are familiar with the directory package structure, aren't you
java.time What's in the bag java8 New date and time API
java.time contains the main API based on the ISO-8601 standard. The classes defined here represent the main date time concepts, including instant, duration, date, time, time zone and time period. They are based on the ISO calendar system, a de facto world calendar that follows the rules of the Gregorian calendar. All classes are immutable and thread safe.
The blogger recently wrote an API comparison article about the old and new date and time of java< Wanzi blog teaches you to understand the date and time related usage of java source code>
If you are interested, you can quickly understand the differences between the two sets of APIs and the advantages of the new API.
(1) JSR-310: ZoneId time zone and offset
Geographical knowledge review
time zone
Because countries and regions in the world have different longitude and local time, they will be divided into different time zones.
The formal time zone division includes 24 time zones, each time zone is represented by an English letter, and one time zone is divided every 15 ° longitude.
In order to overcome the confusion of time, an international longitude Conference (also known as the international meridian Conference) held in Washington 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), and Britain (the former site of Greenwich Observatory) was defined as the central time zone (zero time zone) East Zone 1-12 and West Zone 1-12. Each time zone spans 15 degrees longitude, and the time is exactly 1 hour. The last east zone and west zone 12 span 7.5 degrees longitude, with 180 degrees longitude in the East and West as the boundary. The time on the central longitude of each time zone is the time uniformly adopted in this time zone, which is called zone time. The time difference between the two adjacent time zones is 1 hour.
For example, the time in East 8 of China is always 1 hour earlier than that in East 7 of Thailand and 1 hour later than that in East 9 of Japan.
– quoted from Baidu Encyclopedia
The longitude distribution of time zone is shown in the list:
time zone | Longitude range of time zone | Time zone centerline |
---|---|---|
UTC(0 time zone) | 7.5°W~7.5°E | 0° |
UTC + 1 (East Zone 1) | 7.5°E~22.5°E | 15°E |
UTC + 2 (East Zone 2) | 22.5°E~37.5°E | 30°E |
UTC + 3 (East Zone 3) | 37.5°E~52.5°E | 45°E |
UTC + 4 (East Zone 4) | 52.5°E~67.5°E | 60°E |
UTC + 5 (East Zone 5) | 67.5°E~82.5°E | 75°E |
UTC + 6 (East Zone 6) | 82.5°E~97.5°E | 90°E |
UTC + 7 (East Zone 7) | 97.5°E~112.5°E | 105°E |
UTC + 8 (East Zone 8) | 112.5°E~127.5°E | 120°E |
UTC + 9 (East Zone 9) | 127.5°E~142.5°E | 135°E |
UTC + 10 (East zone 10) | 142.5°E~157.5°E | 150°E |
UTC + 11 (East Zone 11) | 157.5°E~172.5°E | 165°E |
Utc12 (East and west zone 12) | 172.5°E~172.5°W | 180° |
Utc-11 (West Zone 11) | 172.5°W~157.5°W | 165°W |
Utc-10 (West Zone 10) | 157.5°W~142.5°W | 150°W |
Utc-9 (West Zone 9) | 142.5°W~127.5°W | 135°W |
UTC-8 (West Zone 8) | 127.5°W~112.5°W | 120°W |
Utc-7 (west 7) | 112.5°W~97.5°W | 105°W |
Utc-6 (West Zone 6) | 97.5°W~82.5°W | 90°W |
Utc-5 (West Zone 5) | 82.5°W~67.5°W | 75°W |
Utc-4 (West Zone 4) | 67.5°W~52.5°W | 60°W |
Utc-3 (West Zone 3) | 52.5°W~37.5°W | 45°W |
Utc-2 (West Zone 2) | 37.5°W~22.5°W | 30°W |
Utc-1 (West Zone 1) | 22.5°W~7.5°W | 15°W |
In fact, one country or one province often spans two or more time zones at the same time. In order to take into account the administrative convenience, one country or one province is often divided together. For example, China has a wide territory and spans almost five time zones, but for convenience and simplicity, in fact, only the standard of Dongba time zone, namely Beijing time, is used.
UTC
Coordinated universal time, also known as world unified time, world standard time and international coordinated time. Due to the different abbreviations of English (CUT) and French (TUC), it is referred to as UTC as a compromise.
Coordinated universal time is a time measurement system based on atomic time and second length, which is as close to universal time as possible.
The accuracy of international atomic time is nanoseconds per day, while the accuracy of world time is milliseconds per day. Many application departments require the time system to be close to universal time UT. For this situation, a compromise time scale called coordinated universal time was published in 1972. In order to ensure that the difference between coordinated universal time and universal time does not exceed 0.9 seconds, positive or negative leap seconds will be added to coordinated universal time if necessary. Therefore, there will be several integer second differences between coordinated universal time and international atomic time, and the difference between them accumulates year by year. The method of second skipping (leap second) is adopted to make the time of coordinated time close to universal time, and the difference is no more than 1s. It not only maintains the uniformity of time scale, but also can approximately reflect the change of earth rotation.
– quoted from Baidu Encyclopedia
Coordinated universal time is not related to regional location and does not represent the time of a place at the current time, so the time zone should be added when saying a local time. For example, China is UTC+8.
UTC is the time standard, which divides the world into 24 time zones from UTC-12 to UTC + 12.
GMT
GMT(Greenwich Mean Time) alias: Greenwich time (sometimes translated as Greenwich), Chinese Name: universal time.
GMT refers to the standard time at Greenwich, and it is also a form of indicating the earth's rotation rate. A time measurement system based on the earth's rotation. The angle of the earth's rotation can be measured by the motion of the local meridian relative to the basic reference point on the earth. In order to measure the earth's rotation, two basic reference points are selected on the earth: the vernal equinox (see the equinox) and the solar point. The time determined from this is called stellar time and solar time respectively.
– quoted from Baidu Encyclopedia
GMT is not equal to UTC, but Greenwich is just in time zone 0. So GMT = UTC+0 is right.
CST
CST can be regarded as standard time in the United States, Australia, Cuba or China
Central Standard Time (USA) UT-6:00
Central Standard Time (Australia) UT+9:30
China Standard Time: UT + 8:00
Cuba Standard Time UT-4:00
– quoted from Baidu Encyclopedia
Therefore, pay attention to the corresponding time zone when converting CST time. This is a pit.
Central time: CST=UTC/GMT-6;
China Standard Time: CST=UTC/GMT+8;
DST
DST(Daylight Saving Time) Chinese Name: daylight saving time.
It means to set a man-made time in order to save energy. It is also called Daylight Saving Time (DST), also known as "Daylight Saving Time" and "Daylight Saving Time". The unified time adopted during the implementation of this system is called "Daylight Saving Time". Generally, in the summer when the morning is early, artificially adjust the time by one hour, which can make people get up early and go to bed early, reduce the amount of lighting, so as to make full use of lighting resources and save lighting power. The specific provisions of each country adopting Daylight Saving Time are different. Nearly 110 countries around the world implement Daylight Saving Time every year.
– quoted from Baidu Encyclopedia
The time frame for China to realize DST: 1986-1991.
ISO-8601
The international standard ISO 8601 of the international organization for standardization is the representation of date and time, which is fully known as data storage and exchange form · information exchange · representation of date and time. At present, the latest version is ISO8601:2004 in the third edition, ISO8601:1988 in the first edition and ISO8601:2000 in the second edition
– quoted from Baidu Encyclopedia
The year consists of four digits YYYY, or four or five digits with a sign represent ± YYYY. The first year of the Gregorian calendar is 0001, the first year of the Gregorian calendar is 0000, and the second year of the Gregorian calendar is - 0001.
Month and day are expressed in two digits: MM and DD.
Use only numbers as the basic format. Use the Dash "-" to interval the year, month and day as the extended format.
Hours, minutes and seconds are represented by two digits. Add a capital letter Z at the end of UTC time, and other time zones are represented by actual time and time difference. For example, 2:30:5 p.m. UTC time is expressed as 14:30:05Z or 143005Z, and Beijing time at that time is expressed as 22:30:05 + 08:00 or 223005 + 0800, which can also be simplified to 223005 + 08.
Note: do you remember the Date class of java? It is represented by ISO-8601 by default.
Before JDK8: TimeZone / offset TimeZone
Before JDK8, we used java.util.TimeZone to represent and process time zones and offsets.
**TimeZone.getDefault() * * get the time zone in which the current JVM is running. How does it get the default time zone? I have written an analysis article before. If you are interested, you can understand it. It will not be repeated here.
The JDK obtains the risks and best practices of the default time zone
Sometimes it is necessary to convert the time zone. For example, a time should be displayed in Beijing time and New York time. realization:
There is no SimpleDateFormat to format the time because it is thread unsafe. Select thread safe FastDateFormat,
Apache Commons Lang package support.
If you are interested, you can learn about the source code analysis of FastDateFormat: The SimpleDateFormat thread of java is unsafe. There is a problem. Virtual bamboo teaches you a variety of solutions
String patternStr = "yyyy-MM-dd HH:mm:ss"; // Beijing time (new is the time in the default time zone) Date bjDate = new Date(); // Get the time zone of New York TimeZone newYorkTimeZone = TimeZone.getTimeZone("America/New_York"); // Convert Beijing time to New York Date according to this time zone FastDateFormat fastDateFormat = FastDateFormat.getInstance(patternStr,newYorkTimeZone); System.out.println("This is Beijing time:" + FastDateFormat.getInstance(patternStr).format(bjDate)); System.out.println("This is New York time:" + fastDateFormat.format(bjDate));
19-7 = 12 Beijing time is 12 hours faster than New York time.
JDK8 starts to support: time zone / offset ZoneId/ZoneOffset
In JDK8, ZoneId represents the ID of the time zone, and ZoneOffset represents the offset of Greenwich/UTC.
ZoneId is used to replace java.util.TimeZone.
Let's study ZoneId. ZoneId represents the ID of a time zone, which is determined. However, the time zone ID has corresponding rules, which are determined by java.time.zone.ZoneRules. For example, the daylight saving time rules are set by governments of various countries and may change. They are different in different years. This is left to the underlying mechanism of JDK to keep pace. We callers do not need to care (no! Care! Only when the technology is no longer a black box can we have a bottom in mind!).
How to synchronize the time zone when the rules of the time zone change
Introduction to TZUpdater tool
The TZUpdater tool provided allows you to update the installed java development kit (JDK) and Java runtime environment (JRE) software with updated time zone data to adapt to daylight saving time (DST) changes in different countries / regions. Oracle relies on time zone data publicly available through IANA's time zone database.
If you cannot use the latest JDK or JRE update version of Oracle, or if the time zone data on the latest version is not the latest available, TZUpdater tool provides a method to update the time zone data while keeping other system configurations and dependencies unchanged
TZUpdater tool usage
The TZUpdater tool is used to execute the JDK/JRE software instance of the tool. JDK/JRE software will be modified every time. To manage tools to multiple instances of JDK/JRE software.
Before running the TZUpdater tool on the installed JDK/JRE software, you must stop any running services of the JDK/JRE software on the operating system.
Run the TZUpdater tool with the following command:
java -jar tzupdater.jar options
To successfully update the time zone data, you should ensure that you have sufficient permissions to modify the JDK_HOME /jre/lib or JRE_HOME /lib directory.
If no options are specified, a usage message is displayed. To update the time zone data, use the - l or - f option.
option | describe |
---|---|
-h, --help
| Print the usage to stdout and exit. If you specify this option, the other options are ignored. |
-V, --version | Print the tool version, the tzdata version in the JRE, and the tzdata version to which the tool will be updated, and exit. |
-l, --location url-link-to-archive-file | Compile, test, and update JRE time zone data from the provided tzdata.tar.gz package, such as - l https://www.iana.org/time-zones/repository/tzdata-latest.tar.gz. Supported URL protocols: http: / /, HTTPS: / /, file: / /. If no URL link is provided, the tool will use the latest IANA tzdata package located at https://www.iana.org/time-zones/repository/tzdata-latest.tar.gz . |
-f, --force | Force tzdata update. Use this option if updating to an older version of tzdata. |
-v, --verbose | Displays the detailed message stdout to. |
Manual upgrade
be careful:
1. Before running the TZUpdater tool on the installed JDK/JRE software, you must stop any running services of the JDK/JRE software on the operating system.
2. To successfully update the time zone data, you should ensure that you have sufficient permissions to modify the JDK_HOME /jre/lib or JRE_HOME /lib directory. (linux system: JRE directory should have write permission; windows system: run cmd as administrator)
3. If there are multiple JDK / jres on the system, the tool needs to be used in each JDK/JRE (each JDK/JRE needs to be operated once)
4. After the update is successful, restart the application service on this JDK/JRE instance (if it has not been updated, restart the server to try)
Operation steps:
1. Download the tzupdater.jar package officially provided by Oracle; Download address
https://www.oracle.com/java/technologies/javase-tzupdater-downloads.html
Put tzupdater.jar in the java directory bin directory, for example
"C:\Program Files\JAVA\java-1.8.0-openjdk-1.8.0.201\bin\tzupdater.jar";
2. Check the current time zone database version. Take windows as an example, run cmd as an administrator and switch to the directory corresponding to tzupdater.jar:
java -jar tzupdater.jar -V
3. For online update, take windows as an example, run cmd as an administrator and switch to the directory corresponding to tzupdater.jar: (choose one of the third and fourth update methods)
java -jar tzupdater.jar -l https://www.iana.org/time-zones/repository/tzdata-latest.tar.gz
As shown in the figure, it has been successfully updated to tzdata 2021a.
The updated file is placed in jre/lib/tzdb.dat, as shown in the figure. It has a backup history version.
4. Offline update: download the latest time zone data first. Download address:
https://data.iana.org/time-zones/releases/
Take windows as an example, run cmd as an administrator. Switch to the directory corresponding to tzupdater.jar:
java -jar tzupdater.jar -l file:///[path]/tzdata.tar.gz
Note:
windows recommends that you put it in the root directory of drive C, and the path directory should not have Chinese;
Run cmd as administrator (write permission is required);
As shown in the above command, the / after file is 3
5. After the above execution, use the command to view the current time zone database version in step 2 to check whether the update is successful.
Service automation upgrade
Thinking steps:
1. Set the scheduled task (just configure the operating system) and execute the command script of tzupdater to update the time zone;
2. A new time zone service is opened to provide time zone and daylight saving time rule reading services for external deployment;
3. In the time zone service, write a synchronization button to execute the command script of tzupdater to update the time zone;
4. In the time zone service, the timeZone data is regularly written to the user-defined time zone table. It provides maintenance functions, and you can customize the addition, modification and deletion of timeZone data.
Benefits of this idea:
1. Other services do not need to stop the service to update the time. The latest time zone data can be obtained directly by calling the data of the time zone service;
2. The advantage of automation avoids the tedious manual maintenance of time zone, and manual intervention has the risk of causing problems;
3. Time zone services and other business services are split to facilitate future expansion.
System default ZoneId
@Test public void timeZoneTest2(){ System.out.println("JDK 8 Previous practice:"+TimeZone.getDefault()); System.out.println("JDK 8 Subsequent practice:"+ZoneId.systemDefault()); }
ZoneId.systemDefault()Method implementation is called TimeZone: public static ZoneId systemDefault() { return TimeZone.getDefault().toZoneId(); }
So the two results are the same (Asia/Shanghai), which is normal.
TimeZone.toZoneId() is a method added after java8.
/** * Converts this {@code TimeZone} object to a {@code ZoneId}. * * @return a {@code ZoneId} representing the same time zone as this * {@code TimeZone} * @since 1.8 */ public ZoneId toZoneId() { String id = getID(); if (ZoneInfoFile.useOldMapping() && id.length() == 3) { if ("EST".equals(id)) return ZoneId.of("America/New_York"); if ("MST".equals(id)) return ZoneId.of("America/Denver"); if ("HST".equals(id)) return ZoneId.of("America/Honolulu"); } return ZoneId.of(id, ZoneId.SHORT_IDS); }
Specify the string to get ZoneId and get all zoneIds
System.out.println(ZoneId.of("America/New_York")); System.out.println(ZoneId.of("Asia/Shanghai"));
@Test public void ZoneIdTest2(){ Set<String> zoneIds = ZoneId.getAvailableZoneIds(); System.out.println("zoneIds Length:"+zoneIds.size()); for(String zoneId : zoneIds){ System.out.println(zoneId); } }
The specified string cannot be scribbled, or an error will be reported. It should be in the collection range of ZoneId.getAvailableZoneIds().
Get time zone from date
System.out.println(ZoneId.from(ZonedDateTime.now())); System.out.println(ZoneId.from(ZoneOffset.of("+8")));
Obtaining the time zone from the date only supports the TemporalAccessor with the time zone, such as LocalDateTime. LocalDate is not allowed and will report an error.
try { System.out.println(ZoneId.from(LocalDateTime.now())); }catch (Exception e){ e.printStackTrace(); } try { System.out.println(ZoneId.from(LocalDate.now())); }catch (Exception e){ e.printStackTrace(); }
ZoneId is an abstract class. It has two inheritance implementation classes:
- ZoneOffset: time zone offset
- ZoneRegion: geographic region
ZoneOffset (time zone offset)
The time zone offset is the time difference between the time zone and Greenwich/UTC, which is generally a fixed number of hours and minutes.
Min / max offset
@Test public void ZoneIdTest5(){ System.out.println("Minimum offset:" + ZoneOffset.MIN); System.out.println("Minimum offset:" + ZoneOffset.MAX); System.out.println("Center offset:" + ZoneOffset.UTC); // Maximum range exceeded System.out.println(ZoneOffset.of("+100")); }
If the maximum range is exceeded, an error will be reported
Time minute second construction offset
@Test public void ZoneIdTest6(){ System.out.println(ZoneOffset.ofHours(10)); System.out.println(ZoneOffset.ofHoursMinutes(10, 10)); System.out.println(ZoneOffset.ofHoursMinutesSeconds(10, 10, 10)); System.out.println(ZoneOffset.ofHours(-10)); }
Very convenient, simple and easy to understand. The offset can be accurate to seconds.
Zoneregion (geographic region)
ZoneRegion refers to a geographical region in the format of continent (state, country) / city. The most common regional classification is the time zone database (TZDB).
which defines regions such as' Europe/Paris' and 'Asia/Tokyo'
final class ZoneRegion extends ZoneId implements Serializable { ... }
According to the source code, the geographical region ZoneRegion is the inherited implementation class of ZoneId.
However, we found that this is not used externally. The modifier of ZoneRegion is default (which can only be called by classes under the same package). You can only operate through ZoneId.
@Test public void ZoneIdTest7(){ ZoneId zoneId = ZoneId.systemDefault(); System.out.println(zoneId); }
The blogger is in Xiamen, so the default time zone ID is Asia/Shanghai.
Instances of ZoneId are ZoneOffset or ZoneRegion
ZoneId of(String zoneId, boolean checkAvailable) source code analysis:
/** * Parses the ID, taking a flag to indicate whether {@code ZoneRulesException} * should be thrown or not, used in deserialization. * * @param zoneId the time-zone ID, not null * @param checkAvailable whether to check if the zone ID is available * @return the zone ID, not null * @throws DateTimeException if the ID format is invalid * @throws ZoneRulesException if checking availability and the ID cannot be found */ static ZoneId of(String zoneId, boolean checkAvailable) { Objects.requireNonNull(zoneId, "zoneId"); if (zoneId.length() <= 1 || zoneId.startsWith("+") || zoneId.startsWith("-")) { return ZoneOffset.of(zoneId); } else if (zoneId.startsWith("UTC") || zoneId.startsWith("GMT")) { return ofWithPrefix(zoneId, 3, checkAvailable); } else if (zoneId.startsWith("UT")) { return ofWithPrefix(zoneId, 2, checkAvailable); } return ZoneRegion.ofId(zoneId, checkAvailable); } private static ZoneId ofWithPrefix(String zoneId, int prefixLength, boolean checkAvailable) { String prefix = zoneId.substring(0, prefixLength); if (zoneId.length() == prefixLength) { return ofOffset(prefix, ZoneOffset.UTC); } ... }
From the source code:
- zoneId is less than or equal to 1 bit in length, or starts with "+" or "-". ZoneOffset instances are created
- Those that start with "UTC", "UT" or "GMT" create ZoneRegion instances
- If the above two conditions are not met, the ZoneRegion instance is created
@Test public void ZoneIdTest8(){ ZoneId zoneId1 = ZoneId.of("+8"); ZoneId zoneId2 = ZoneId.of("+08:00"); ZoneId zoneId3 = ZoneId.of("UT+8"); ZoneId zoneId4 = ZoneId.of("Asia/Shanghai"); System.out.println(); }
(2) JSR-310: common date time API
The following describes the date and time APIs commonly used by java8 API, in the order of classes in the java.time package:
- Clock: clock
- Instant: instant time.
- LocalDate: local date. Only indicates month, year and day
- LocalDateTime: local date time, LocalDate+LocalTime
- LocalTime: local time; only indicates hours, minutes and seconds
- OffsetDateTime: date time with time offset (excluding ZoneRegion based time offset)
- OffsetTime: time with time offset
- ZonedDateTime: date time with time offset (including time offset based on ZoneRegion)
Bloggers have opened these classes. They all belong to immutable classes. And the official also said that the classes under the java.time package are thread safe.
Clock
Clock class description
public abstract class Clock { ... }
Clock is an abstract class. It provides four internal classes, which are its internal implementation classes
- FixedClock: always returns the same instantaneous clock, which is usually used for testing.
- OffsetClock: offset clock. The unit of time offset is Duration.
- SystemClock: the default local clock of the system.
- TickClock: offset clock. The unit of time offset is nanosecond.
Clock provides the following common methods (these methods have corresponding implementations in the implementation class):
// Gets the current Instant object of the clock. public abstract Instant instant() // Gets the current millisecond value of the clock public long millis() // Gets the time zone used to create the clock. public abstract ZoneId getZone() // Returns a new instance of the current clock with the specified time zone public abstract Clock withZone(ZoneId zone)
FixedClock
Clock.fixed
public static Clock fixed(Instant fixedInstant, ZoneId zone)
You need to pass instant and zone and return a clock with a fixed instant.
Instant instant = Instant.now(); Clock fixedClock = Clock.fixed(instant, ZoneId.of("Asia/Shanghai")); Clock fixedClock1 = Clock.fixed(instant, ZoneId.of("GMT")); System.out.println("Chinese time zone Clock: "+fixedClock); System.out.println("GMT Time zone Clock:"+fixedClock1);
It can be seen from the running results that the returned result has a corresponding time zone.
Verify that the acquired clock changes:
Clock clock = Clock.systemDefaultZone(); Clock fixedClock = Clock.fixed(clock.instant(), ZoneId.of("Asia/Shanghai")); System.out.println(fixedClock.instant()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(fixedClock.instant());
Clock.fixed creates a fixed clock, and the clock object will always provide the same time as specified.. As shown in the figure, forced sleep for 1 second, but the time has not changed.
Clock.fixed is better matched with the Offset method
It can be seen from the above that Clock.fixed obtains a fixed clock, and the Offset method is used to add or subtract time
The example code is as follows
Clock clock = Clock.systemDefaultZone(); Clock fixedClock = Clock.fixed(clock.instant(), ZoneId.of("Asia/Shanghai")); System.out.println(fixedClock.instant()); Clock clockAdd = Clock.offset(clock, Duration.ofMinutes(20)); Clock clockSub = Clock.offset(clock, Duration.ofMinutes(-10)); System.out.println("Original: " + clock.instant()); System.out.println("Added 20 minutes: " + clockAdd.instant()); System.out.println("Ten minutes: " + clockSub.instant());
OffsetClock
OffsetClock is the offset clock, and the unit of time offset is Duration.
//Clock public static Clock offset(Clock baseClock, Duration offsetDuration) { Objects.requireNonNull(baseClock, "baseClock"); Objects.requireNonNull(offsetDuration, "offsetDuration"); if (offsetDuration.equals(Duration.ZERO)) { return baseClock; } return new OffsetClock(baseClock, offsetDuration); }
It can be seen from the source code that the OffsetClock instance object is returned by using the Clock.offset method
Clock clock = Clock.systemDefaultZone(); Clock fixedClock = Clock.fixed(clock.instant(), ZoneId.of("Asia/Shanghai")); System.out.println(fixedClock.instant()); Clock clockAdd = Clock.offset(clock, Duration.ofMinutes(20)); System.out.println("Original: " + clock.instant()); System.out.println("Added 20 minutes: " + clockAdd.instant());
SystemClock
SystemClock is the default local clock of the system.
Clock clock = Clock.systemDefaultZone(); System.out.println(clock.millis()); Clock utc = Clock.systemUTC(); System.out.println(utc.millis()); System.out.println(System.currentTimeMillis());
It's exactly the same. This depends on the source code
Clock.systemDefaultZone()
The system default time zone ZoneId.systemDefault() is used
public static Clock systemDefaultZone() { return new SystemClock(ZoneId.systemDefault()); }
Finally, System.currentTimeMillis() is called
Clock.systemUTC()
The UTC time zone ZoneOffset.UTC is used
public static Clock systemUTC() { return new SystemClock(ZoneOffset.UTC); }
Finally, System.currentTimeMillis() is called
conclusion
The millis() timestamp obtained by Clock.systemDefaultZone() and Clock.systemUTC() are the same, which is the difference between the corresponding time zones.
TickClock
TickClock is an offset clock, and the minimum unit of time offset is nanoseconds.
As shown in the figure, Clock mainly provides the following three methods
//The timing unit of the constructed clock is a custom offset unit public static Clock tick(Clock baseClock, Duration tickDuration); //The timing unit of the constructed clock is minutes public static Clock tickMinutes(ZoneId zone); //The timing unit of the constructed clock is seconds public static Clock tickSeconds(ZoneId zone) ;
Actual combat:
Clock tickClock = Clock.tick(Clock.systemDefaultZone(),Duration.ofHours(1L)); Clock tickMinutes = Clock.tickMinutes(ZoneId.of("Asia/Shanghai")); Clock tickSeconds = Clock.tickSeconds(ZoneId.of("Asia/Shanghai")); LocalDateTime tickClockLocalDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(tickClock.millis()),ZoneId.of("Asia/Shanghai")); LocalDateTime tickMinutesLocalDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(tickMinutes.millis()),ZoneId.of("Asia/Shanghai")); LocalDateTime tickSecondsLocalDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(tickSeconds.millis()),ZoneId.of("Asia/Shanghai")); System.out.println("tickClock :"+tickClock.millis() +" Turn into date Time:"+tickClockLocalDateTime); System.out.println("tickMinutes:"+tickMinutes.millis() +" Turn into date Time:"+tickMinutesLocalDateTime); System.out.println("tickSeconds:"+tickSeconds.millis() +" Turn into date Time:"+tickSecondsLocalDateTime);
The offset unit supports: day, hour, minute, second, haos, nanosecond
Instant
Instant class description
public final class Instant implements Temporal, TemporalAdjuster, Comparable<Instant>, Serializable { ... }
Instant represents the instantaneous time. It is also immutable and thread safe. In fact, the Java.time package is thread safe.
Instant is a new feature in java 8, which has two core fields
... private final long seconds; private final int nanos; ...
One is a timestamp in seconds, and the other is a timestamp in nanoseconds.
Is it very similar to the long timestamp returned by * * System.currentTimeMillis() * * System.currentTimeMillis() returns milliseconds, and Instant has more accurate nanosecond timestamps.
Common usage of Instant
Instant now = Instant.now(); System.out.println("now:"+now); System.out.println(now.getEpochSecond()); // second System.out.println(now.toEpochMilli()); // millisecond
Instant does not have a time zone, but it can be converted to ZonedDateTime after adding the time zone
Instant ins = Instant.now(); ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault()); System.out.println(zdt);
long timestamp to Instant
Pay attention to the time unit of long timestamp. Select the conversion method corresponding to Instant
//1626796436 is a second timestamp Instant ins = Instant.ofEpochSecond(1626796436); ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault()); System.out.println("Second timestamp conversion:"+zdt); //1626796436111l is a second timestamp Instant ins1 = Instant.ofEpochMilli(1626796436111l); ZonedDateTime zdt1 = ins1.atZone(ZoneId.systemDefault()); System.out.println("Millisecond timestamp conversion:"+zdt1);
Instant pit
The time obtained by Instant.now() differs from Beijing time by 8 time zones, which is a detail and should be avoided.
Look at the source code, using UTC time.
public static Instant now() { return Clock.systemUTC().instant(); }
Solution:
Instant now = Instant.now().plusMillis(TimeUnit.HOURS.toMillis(8)); System.out.println("now:"+now);
LocalDate
LocalDate class description
LocalDate represents the local date. Only indicates month, year and day. Equivalent to: yyyy mm DD.
Common usage of LocalDate
Get current date
LocalDate localDate1 = LocalDate.now(); LocalDate localDate2 = LocalDate.now(ZoneId.of("Asia/Shanghai")); LocalDate localDate3 = LocalDate.now(Clock.systemUTC()); System.out.println("now :"+localDate1); System.out.println("now by zone :"+localDate2); System.out.println("now by Clock:"+localDate3);
Get localDate object
LocalDate localDate1 = LocalDate.of(2021, 8, 14); LocalDate localDate2 = LocalDate.parse("2021-08-14"); System.out.println(localDate1); System.out.println(localDate2);
Gets the month, year, and day of the specified date
LocalDate localDate1 = LocalDate.of(2021, 8, 14); // Current date year: 2021 System.out.println(localDate1.getYear()); // Current date month object: AUGUST System.out.println(localDate1.getMonth()); // Current date month: August System.out.println(localDate1.getMonthValue()); // The date is the day of the current week: 6 System.out.println(localDate1.getDayOfWeek().getValue()); // The date is the day of the current month: 14 System.out.println(localDate1.getDayOfMonth()); // The date is the day of the current year: 226 System.out.println(localDate1.getDayOfYear());
Modification date
LocalDate localDate1 = LocalDate.of(2021, 8, 14); // Year of modifying this date: August 14, 2022 System.out.println(localDate1.withYear(2022)); // Month to modify this date: December 14, 2021 System.out.println(localDate1.withMonth(12)); // Modify the number of days of this date in the current month: 2021-08-01 System.out.println(localDate1.withDayOfMonth(1));
Comparison date
LocalDate localDate1 = LocalDate.of(2021, 8, 14); // Compare the specified date with the parameter date and return a positive number, then the specified date and time is later (the number is larger): 13 int i = localDate1.compareTo(LocalDate.of(2021, 8, 1)); System.out.println(i); // Compare whether the specified date is earlier than the parameter date (true is earlier): true System.out.println(localDate1.isBefore(LocalDate.of(2021,8,31))); // Compare whether the specified date is later than the parameter date (true is later): false System.out.println(localDate1.isAfter(LocalDate.of(2021,8,31))); // Compare whether two dates are equal: true System.out.println(localDate1.isEqual(LocalDate.of(2021, 8, 14)));
LocalDate and String are converted to each other, and Date and LocalDate are converted to each other
LocalDate and String are converted to each other
LocalDate localDate1 = LocalDate.of(2021, 8, 14); // LocalDate to String DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String dateString = localDate1.format(dateTimeFormatter); System.out.println("LocalDate turn String:"+dateString); // String to LocalDate String str = "2021-08-14"; DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate date = LocalDate.parse(str, fmt); System.out.println("String turn LocalDate:"+date);
Date and LocalDate are converted to each other
// Date to LocalDate Date now = new Date(); // First convert Date to ZonedDateTime Instant instant = now.toInstant(); ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Asia/Shanghai")); LocalDate localDate = zonedDateTime.toLocalDate(); // Sat Aug 14 23:16:28 CST 2021 System.out.println(now); // 2021-08-14 System.out.println(localDate); // LocalDate to Date LocalDate now1 = LocalDate.now(); ZonedDateTime dateTime = now1.atStartOfDay(ZoneId.of("Asia/Shanghai")); Date date1 = Date.from(dateTime.toInstant()); System.out.println(date1);
LocalDateTime
LocalDateTime class description
Represents the current date and time, equivalent to: yyyy mm ddthh: mm: SS
Common usage of LocalDateTime
Get current date and time
LocalDate d = LocalDate.now(); // current date LocalTime t = LocalTime.now(); // current time LocalDateTime dt = LocalDateTime.now(); // Current date and time System.out.println(d); // Print in strict accordance with ISO 8601 format System.out.println(t); // Print in strict accordance with ISO 8601 format System.out.println(dt); // Print in strict accordance with ISO 8601 format
The running result is feasible. The local date and time obtained through now() is always returned in the current default time zone
Gets the specified date and time
LocalDate d2 = LocalDate.of(2021, 07, 14); // July 14, 2021, note that July = July LocalTime t2 = LocalTime.of(13, 14, 20); // 13:14:20 LocalDateTime dt2 = LocalDateTime.of(2021, 07, 14, 13, 14, 20); LocalDateTime dt3 = LocalDateTime.of(d2, t2); System.out.println("Specify date and time:"+dt2); System.out.println("Specify date and time:"+dt3);
Addition, subtraction and modification of date and time
LocalDateTime currentTime = LocalDateTime.now(); // Current date and time System.out.println("------------------Addition and subtraction of time and its modification-----------------------"); //3. The addition and subtraction method of localdatetime includes all additions and subtractions of LocalDate and LocalTime. As mentioned above, only a brief introduction is given here System.out.println("3.Current time:" + currentTime); System.out.println("3.Current time plus 5 years:" + currentTime.plusYears(5)); System.out.println("3.Current time plus 2 months:" + currentTime.plusMonths(2)); System.out.println("3.Current time minus 2 days:" + currentTime.minusDays(2)); System.out.println("3.Current time minus 5 hours:" + currentTime.minusHours(5)); System.out.println("3.Current time plus 5 minutes:" + currentTime.plusMinutes(5)); System.out.println("3.Current time plus 20 seconds:" + currentTime.plusSeconds(20)); //It can also be used flexibly, such as adding one year back, subtracting one day forward, adding two hours back and subtracting five minutes forward System.out.println("3.Simultaneous modification(Add one year backward, one day forward, two hours backward and five minutes forward): " + currentTime.plusYears(1).minusDays(1).plusHours(2).minusMinutes(5)); System.out.println("3.The revised year is 2025:" + currentTime.withYear(2025)); System.out.println("3.Revised to December:" + currentTime.withMonth(12)); System.out.println("3.The revision date is 27th:" + currentTime.withDayOfMonth(27)); System.out.println("3.Modify the hour to 12:" + currentTime.withHour(12)); System.out.println("3.Modify the minutes to 12:" + currentTime.withMinute(12)); System.out.println("3.Modify the second to 12:" + currentTime.withSecond(12));
LocalDateTime and Date are converted to each other
Date to LocalDateTime
System.out.println("------------------Method 1: write step by step-----------------------"); //Instantiate a time object Date date = new Date(); //Returns a moment representing the same point on the timeline as a date object Instant instant = date.toInstant(); //Get the system default time zone ZoneId zoneId = ZoneId.systemDefault(); //Get the date and time with time zone according to the time zone ZonedDateTime zonedDateTime = instant.atZone(zoneId); //Convert to LocalDateTime LocalDateTime localDateTime = zonedDateTime.toLocalDateTime(); System.out.println("Method 1: Original Date = " + date); System.out.println("Method 1: transformed LocalDateTime = " + localDateTime); System.out.println("------------------Method 2: one step in place (recommended)-----------------------"); //Instantiate a time object Date todayDate = new Date(); //Instant.ofepochmili (long l) uses milliseconds in the era of 1970-01-01T00:00:00Z to obtain an instance of instant LocalDateTime ldt = Instant.ofEpochMilli(todayDate.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime(); System.out.println("Method 2: Original Date = " + todayDate); System.out.println("Method 2: transformed LocalDateTime = " + ldt);
LocalDateTime to Date
System.out.println("------------------Method 1: write step by step-----------------------"); //Gets the LocalDateTime object and the current time LocalDateTime localDateTime = LocalDateTime.now(); //Get the system default time zone ZoneId zoneId = ZoneId.systemDefault(); //Get the date and time with time zone according to the time zone ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId); //Returns a moment representing the same point on the timeline as a date object Instant instant = zonedDateTime.toInstant(); //Convert to Date Date date = Date.from(instant); System.out.println("Method 1: Original LocalDateTime = " + localDateTime); System.out.println("Method 1: transformed Date = " + date); System.out.println("------------------Method 2: one step in place (recommended)-----------------------"); //Instantiate a LocalDateTime object LocalDateTime now = LocalDateTime.now(); //Convert to date Date dateResult = Date.from(now.atZone(ZoneId.systemDefault()).toInstant()); System.out.println("Method 2: Original LocalDateTime = " + now); System.out.println("Method 2: transformed Date = " + dateResult);
LocalTime
LocalTime class description
LocalTime: local time; only indicates hours, minutes and seconds
Common usage of LocalTime
Get current time
LocalTime localTime1 = LocalTime.now(); LocalTime localTime2 = LocalTime.now(ZoneId.of("Asia/Shanghai")); LocalTime localTime3 = LocalTime.now(Clock.systemDefaultZone()); System.out.println("now :"+localTime1); System.out.println("now by zone :"+localTime2); System.out.println("now by Clock:"+localTime3);
Get LocalTime object
LocalTime localTime1 = LocalTime.of(23, 26, 30); LocalTime localTime2 = LocalTime.of(23, 26); System.out.println(localTime1); System.out.println(localTime2);
Gets the hour, minute, and second of the specified date
LocalTime localTime1 = LocalTime.of(23, 26, 30); //Hour of current time: 23 System.out.println(localTime1.getHour()); //Minute of current time: 26 System.out.println(localTime1.getMinute()); //Seconds of current time: 30 System.out.println(localTime1.getSecond());
Modify hours, minutes and seconds
LocalTime localTime1 = LocalTime.of(23, 26, 30); //Time of modification: 00:26:30 System.out.println(localTime1.withHour(0)); //Modification time: 23:30:30 System.out.println(localTime1.withMinute(30)); //Second of modification time: 23:26:59 System.out.println(localTime1.withSecond(59));
Comparison time
LocalTime localTime1 = LocalTime.of(23, 26, 30); LocalTime localTime2 = LocalTime.of(23, 26, 32); // When comparing the two times, the large returns 1, the small returns - 1, and the same returns 0: - 1 System.out.println(localTime1.compareTo(localTime2)); // Compare whether the specified time is earlier than the parameter time (true is earlier): true System.out.println(localTime1.isBefore(localTime2)); // Compare whether the specified time is later than the parameter time (true is later): false System.out.println(localTime1.isAfter(localTime2)); // Compare whether two times are equal: true System.out.println(localTime1.equals(LocalTime.of(23, 26, 30)));
OffsetDateTime
OffsetDateTime class description
OffsetDateTime: date time with time offset (excluding ZoneRegion based time offset)
public final class OffsetDateTime implements Temporal, TemporalAdjuster, Comparable<OffsetDateTime>, Serializable { //The minimum supported {@code OffsetDateTime}, '-999999999-01-01T00:00:00+18:00' public static final OffsetDateTime MIN = LocalDateTime.MIN.atOffset(ZoneOffset.MAX); // The maximum supported {@code OffsetDateTime}, '+999999999-12-31T23:59:59.999999999-18:00'. public static final OffsetDateTime MAX = LocalDateTime.MAX.atOffset(ZoneOffset.MIN); ... }
MIN and MAX above are public static variables.
Common usage of OffsetDateTime
Get current date and time
OffsetDateTime offsetDateTime1 = OffsetDateTime.now(); OffsetDateTime offsetDateTime2 = OffsetDateTime.now(ZoneId.of("Asia/Shanghai")); OffsetDateTime offsetDateTime3 = OffsetDateTime.now(Clock.systemUTC()); System.out.println("now :"+offsetDateTime1); System.out.println("now by zone :"+offsetDateTime2); System.out.println("now by Clock:"+offsetDateTime3);
Gets the OffsetDateTime object
LocalDateTime localDateTime1 = LocalDateTime.of(2021, 8, 15, 13, 14, 20); OffsetDateTime offsetDateTime1 = OffsetDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); OffsetDateTime offsetDateTime2 = OffsetDateTime. of(2021, 8, 15, 13, 14, 20,0, ZoneOffset.ofHours(8)); Instant now = Instant.now(); OffsetDateTime offsetDateTime3 = OffsetDateTime.ofInstant(now, ZoneId.of("Asia/Shanghai")); System.out.println(offsetDateTime1); System.out.println(offsetDateTime2); System.out.println(offsetDateTime3);
Gets the year, day, hour, minute and second of the specified date
LocalDateTime localDateTime1 = LocalDateTime.of(2021, 8, 15, 13, 14, 20); OffsetDateTime offsetDateTime1 = OffsetDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); //Year of current time: 2021 System.out.println(offsetDateTime1.getYear()); //Month of current time: 8 System.out.println(offsetDateTime1.getMonthValue()); //Day of current time: 15 System.out.println(offsetDateTime1.getDayOfMonth()); //Hour of current time: 13 System.out.println(offsetDateTime1.getHour()); //Minute of current time: 14 System.out.println(offsetDateTime1.getMinute()); //Seconds of current time: 20 System.out.println(offsetDateTime1.getSecond());
Modify month, day, hour, minute and second
LocalDateTime localDateTime1 = LocalDateTime.of(2021, 8, 15, 13, 14, 20); OffsetDateTime offsetDateTime1 = OffsetDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); //Year of revision: 2022-08-15T13:14:20+08:00 System.out.println(offsetDateTime1.withYear(2022)); //Month of modification time: 2021-09-15T13:14:20+08:00 System.out.println(offsetDateTime1.withMonth(9)); //Date of modification: 2021-08-30T13:14:20+08:00 System.out.println(offsetDateTime1.withDayOfMonth(30)); //Modification time: 2021-08-15T00:14:20+08:00 System.out.println(offsetDateTime1.withHour(0)); //Modification time: 2021-08-15T13:30:20+08:00 System.out.println(offsetDateTime1.withMinute(30)); //Second of modification time: 2021-08-15T13:14:59+08:00 System.out.println(offsetDateTime1.withSecond(59));
Compare date and time
LocalDateTime localDateTime1 = LocalDateTime.of(2021, 8, 15, 13, 14, 20); OffsetDateTime offsetDateTime1 = OffsetDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); OffsetDateTime offsetDateTime3 = OffsetDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); LocalDateTime localDateTime2 = LocalDateTime.of(2021, 8, 15, 13, 14, 30); OffsetDateTime offsetDateTime2 = OffsetDateTime.of(localDateTime2, ZoneOffset.ofHours(8)); // When comparing the two times, the large returns 1, the small returns - 1, and the same returns 0: - 1 System.out.println(offsetDateTime1.compareTo(offsetDateTime2)); // Compare whether the specified time is earlier than the parameter time (true is earlier): true System.out.println(offsetDateTime1.isBefore(offsetDateTime2)); // Compare whether the specified time is later than the parameter time (true is later): false System.out.println(offsetDateTime1.isAfter(offsetDateTime2)); // Compare whether two times are equal: true System.out.println(offsetDateTime1.equals(offsetDateTime3));
Convert string to OffsetDateTime object
String str = "2021-08-15T10:15:30+08:00"; OffsetDateTime offsetDateTime1 = OffsetDateTime.parse(str); OffsetDateTime offsetDateTime2 = OffsetDateTime.parse(str,DateTimeFormatter.ISO_OFFSET_DATE_TIME); System.out.println(offsetDateTime1); System.out.println(offsetDateTime2);
OffsetTime
OffsetTime class description
OffsetTime: time with time offset
public final class OffsetTime implements Temporal, TemporalAdjuster, Comparable<OffsetTime>, Serializable { //The minimum supported {@code OffsetTime}, '00:00:00+18:00'. public static final OffsetTime MIN = LocalTime.MIN.atOffset(ZoneOffset.MAX); //The maximum supported {@code OffsetTime}, '23:59:59.999999999-18:00'. public static final OffsetTime MAX = LocalTime.MAX.atOffset(ZoneOffset.MIN); ... }
MIN and MAX above are public static variables.
Common usage of OffsetTime
Get current time
OffsetTime offsetTime1 = OffsetTime.now(); OffsetTime offsetTime2 = OffsetTime.now(ZoneId.of("Asia/Shanghai")); OffsetTime offsetTime3 = OffsetTime.now(Clock.systemUTC()); System.out.println("now :"+offsetTime1); System.out.println("now by zone :"+offsetTime2); System.out.println("now by Clock:"+offsetTime3);
Get OffsetTime object
LocalTime localTime1 = LocalTime.of(13, 14, 20); OffsetTime offsetTime1 = OffsetTime.of(localTime1, ZoneOffset.ofHours(8)); OffsetTime offsetTime2 = OffsetTime. of(13, 14, 20,0, ZoneOffset.ofHours(8)); Instant now = Instant.now(); OffsetTime offsetTime3 = OffsetTime.ofInstant(now, ZoneId.of("Asia/Shanghai")); System.out.println(offsetTime1); System.out.println(offsetTime2); System.out.println(offsetTime3);
Gets the hour, minute, and second of the specified time
LocalTime localTime1 = LocalTime.of( 13, 14, 20); OffsetTime offsetTime1 = OffsetTime.of(localTime1, ZoneOffset.ofHours(8)); //Hour of current time: 13 System.out.println(offsetTime1.getHour()); //Minute of current time: 14 System.out.println(offsetTime1.getMinute()); //Seconds of current time: 20 System.out.println(offsetTime1.getSecond());
Modify hours, minutes and seconds
LocalTime localTime1 = LocalTime.of( 13, 14, 20); OffsetTime offsetTime1 = OffsetTime.of(localTime1, ZoneOffset.ofHours(8)); //Modification time: 00:14:20 + 08:00 System.out.println(offsetTime1.withHour(0)); //Modification time: 13:30:20 + 08:00 System.out.println(offsetTime1.withMinute(30)); //Second of modification time: 13:14:59 + 08:00 System.out.println(offsetTime1.withSecond(59));
Comparison time
LocalTime localTime1 = LocalTime.of( 13, 14, 20); OffsetTime offsetTime1 = OffsetTime.of(localTime1, ZoneOffset.ofHours(8)); OffsetTime offsetTime3 = OffsetTime.of(localTime1, ZoneOffset.ofHours(8)); LocalTime localTime2 = LocalTime.of(13, 14, 30); OffsetTime offsetTime2 = OffsetTime.of(localTime2, ZoneOffset.ofHours(8)); // When comparing the two times, the large returns 1, the small returns - 1, and the same returns 0: - 1 System.out.println(offsetTime1.compareTo(offsetTime2)); // Compare whether the specified time is earlier than the parameter time (true is earlier): true System.out.println(offsetTime1.isBefore(offsetTime2)); // Compare whether the specified time is later than the parameter time (true is later): false System.out.println(offsetTime1.isAfter(offsetTime2)); // Compare whether two times are equal: true System.out.println(offsetTime1.equals(offsetTime3));
ZonedDateTime
ZonedDateTime class description
Represents a date and time with time zone. ZonedDateTime can be understood as LocalDateTime+ZoneId
As can be seen from the source code, the ZonedDateTime class defines two variables, LocalDateTime and ZoneId.
The ZonedDateTime class is also immutable and thread safe.
public final class ZonedDateTime implements Temporal, ChronoZonedDateTime<LocalDate>, Serializable { /** * Serialization version. */ private static final long serialVersionUID = -6260982410461394882L; /** * The local date-time. */ private final LocalDateTime dateTime; /** * The time-zone. */ private final ZoneId zone; ... }
Common usage of ZonedDateTime
Get current date and time
// The default time zone gets the current time ZonedDateTime zonedDateTime = ZonedDateTime.now(); // Use the specified time zone to obtain the current time. Asia/Shanghai is the Shanghai time zone ZonedDateTime zonedDateTime1 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai")); //Withzonesameeinstant is the conversion time zone, and the parameter is ZoneId ZonedDateTime zonedDateTime2 = zonedDateTime.withZoneSameInstant(ZoneId.of("America/New_York")); System.out.println(zonedDateTime); System.out.println(zonedDateTime1); System.out.println(zonedDateTime2);
ZonedDateTime zonedDateTime1 = ZonedDateTime.now(); ZonedDateTime zonedDateTime2 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai")); ZonedDateTime zonedDateTime3 = ZonedDateTime.now(Clock.systemUTC()); System.out.println("now :"+zonedDateTime1); System.out.println("now by zone :"+zonedDateTime2); System.out.println("now by Clock:"+zonedDateTime3);
Get ZonedDateTime object
LocalDateTime localDateTime1 = LocalDateTime.of(2021, 8, 15, 13, 14, 20); ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); ZonedDateTime zonedDateTime2 = ZonedDateTime. of(2021, 8, 15, 13, 14, 20,0, ZoneOffset.ofHours(8)); Instant now = Instant.now(); ZonedDateTime zonedDateTime3 = ZonedDateTime.ofInstant(now, ZoneId.of("Asia/Shanghai")); System.out.println(zonedDateTime1); System.out.println(zonedDateTime2); System.out.println(zonedDateTime3);
Gets the year, day, hour, minute and second of the specified date
LocalDateTime localDateTime1 = LocalDateTime.of(2021, 8, 15, 13, 14, 20); ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); //Year of current time: 2021 System.out.println(zonedDateTime1.getYear()); //Month of current time: 8 System.out.println(zonedDateTime1.getMonthValue()); //Day of current time: 15 System.out.println(zonedDateTime1.getDayOfMonth()); //Hour of current time: 13 System.out.println(zonedDateTime1.getHour()); //Minute of current time: 14 System.out.println(zonedDateTime1.getMinute()); //Seconds of current time: 20 System.out.println(zonedDateTime1.getSecond());
Modify month, day, hour, minute and second
LocalDateTime localDateTime1 = LocalDateTime.of(2021, 8, 15, 13, 14, 20); ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); //Year of revision: 2022-08-15T13:14:20+08:00 System.out.println(zonedDateTime1.withYear(2022)); //Month of modification time: 2021-09-15T13:14:20+08:00 System.out.println(zonedDateTime1.withMonth(9)); //Date of modification: 2021-08-30T13:14:20+08:00 System.out.println(zonedDateTime1.withDayOfMonth(30)); //Modification time: 2021-08-15T00:14:20+08:00 System.out.println(zonedDateTime1.withHour(0)); //Modification time: 2021-08-15T13:30:20+08:00 System.out.println(zonedDateTime1.withMinute(30)); //Second of modification time: 2021-08-15T13:14:59+08:00 System.out.println(zonedDateTime1.withSecond(59));
Compare date and time
LocalDateTime localDateTime1 = LocalDateTime.of(2021, 8, 15, 13, 14, 20); ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); ZonedDateTime zonedDateTime3 = ZonedDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); LocalDateTime localDateTime2 = LocalDateTime.of(2021, 8, 15, 13, 14, 30); ZonedDateTime zonedDateTime2 = ZonedDateTime.of(localDateTime2, ZoneOffset.ofHours(8)); // When comparing the two times, the large returns 1, the small returns - 1, and the same returns 0: - 1 System.out.println(zonedDateTime1.compareTo(zonedDateTime2)); // Compare whether the specified time is earlier than the parameter time (true is earlier): true System.out.println(zonedDateTime1.isBefore(zonedDateTime2)); // Compare whether the specified time is later than the parameter time (true is later): false System.out.println(zonedDateTime1.isAfter(zonedDateTime2)); // Compare whether two times are equal: true System.out.println(zonedDateTime1.equals(zonedDateTime3));
LocalDateTime+ZoneId becomes ZonedDateTime
LocalDateTime localDateTime = LocalDateTime.now(); ZonedDateTime zonedDateTime1 = localDateTime.atZone(ZoneId.systemDefault()); ZonedDateTime zonedDateTime2 = localDateTime.atZone(ZoneId.of("America/New_York")); System.out.println(zonedDateTime1); System.out.println(zonedDateTime2);
The above example shows that LocalDateTime can be converted into ZonedDateTime.
(3) JSR-310: formatting and parsing
DateTimeFormatter
DateTimeFormatter class description
DateTimeFormatter is used to format date and time display, and DateTimeFormatter is an immutable class and thread safe.
public final class DateTimeFormatter { ... }
When it comes to the formatted display of time, we have to say that the old friend SimpleDateFormat needs to be used before formatting Date. However, we know that SimpleDateFormat is thread unsafe, which is not clear. Please see this article The SimpleDateFormat thread of java is unsafe. There is a problem. Virtual bamboo teaches you a variety of solutions
Common usage of DateTimeFormatter
format
ZonedDateTime zonedDateTime = ZonedDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm ZZZZ"); System.out.println(formatter.format(zonedDateTime)); DateTimeFormatter usFormatter = DateTimeFormatter.ofPattern("E, MMMM/dd/yyyy HH:mm", Locale.US); System.out.println(usFormatter.format(zonedDateTime)); DateTimeFormatter chinaFormatter = DateTimeFormatter.ofPattern("yyyy MMM dd EE HH:mm", Locale.CHINA); System.out.println(chinaFormatter.format(zonedDateTime));
analysis
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy year MM month dd day HH Time mm branch ss second"); String dateTime = "2021 August 22, 2013 13:14:20"; LocalDateTime localDateTime = LocalDateTime.parse(dateTime, formatter); System.out.println(localDateTime);
Have you noticed that the parse method is placed in the LocalDateTime class instead of the DateTimeFormatter class. This design is in line with the normal idea. If you want to parse the date and time of LocalDateTime, use LocalDateTime. If you want to parse other date and time objects of JSR-310, use the corresponding date and time object to parse.
Bloggers have read the commonly used date and time API s. Except for Clock (which does not need to be parsed), there are other methods to implement parse.
Pit of DateTimeFormatter
1. In normal configuration, string dates in standard format can be converted normally. If the month, day, hour, minute and second are less than two digits, you need to fill in 0. Otherwise, the conversion will fail and an exception will be thrown.
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); LocalDateTime dt1 = LocalDateTime.parse("2021-7-20 23:46:43.946", DATE_TIME_FORMATTER); System.out.println(dt1);
Error will be reported:
java.time.format.DateTimeParseException: Text '2021-7-20 23:46:43.946' could not be parsed at index 5
Analysis reason: the format string does not match the actual time
"yyyy-MM-dd HH:mm:ss.SSS"
"2021-7-20 23:46:43.946"
The middle month format is MM, and the actual time is 7
Solution: keep the format string matching the actual time
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); LocalDateTime dt1 = LocalDateTime.parse("2021-07-20 23:46:43.946", DATE_TIME_FORMATTER); System.out.println(dt1);
2. YYYY and DD are used with caution
LocalDate date = LocalDate.of(2020,12,31); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYYMM"); // The result is 202112 System.out.println( formatter.format(date));
Java's DateTimeFormatter pattern "YYYY" gives you the week-based-year, (by default, ISO-8601 standard) the year of the Thursday of that week.
YYYY is the year of the current week, and the week based year is specified in ISO 8601. December 31, 2020, the weekly year, is 2021
private static void tryit(int Y, int M, int D, String pat) { DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pat); LocalDate dat = LocalDate.of(Y,M,D); String str = fmt.format(dat); System.out.printf("Y=%04d M=%02d D=%02d " + "formatted with " + "\"%s\" -> %s\n",Y,M,D,pat,str); } public static void main(String[] args){ tryit(2020,01,20,"MM/DD/YYYY"); tryit(2020,01,21,"DD/MM/YYYY"); tryit(2020,01,22,"YYYY-MM-DD"); tryit(2020,03,17,"MM/DD/YYYY"); tryit(2020,03,18,"DD/MM/YYYY"); tryit(2020,03,19,"YYYY-MM-DD"); }
Y=2020 M=01 D=20 formatted with "MM/DD/YYYY" -> 01/20/2020 Y=2020 M=01 D=21 formatted with "DD/MM/YYYY" -> 21/01/2020 Y=2020 M=01 D=22 formatted with "YYYY-MM-DD" -> 2020-01-22 Y=2020 M=03 D=17 formatted with "MM/DD/YYYY" -> 03/77/2020 Y=2020 M=03 D=18 formatted with "DD/MM/YYYY" -> 78/03/2020 Y=2020 M=03 D=19 formatted with "YYYY-MM-DD" -> 2020-03-79
The last three dates are problematic, because the capitalized DD represents the day of the year, not the day of the month, but DD is no problem.
Examples refer to: https://www.cnblogs.com/tonyY/p/12153335.html
Therefore, yyyy and dd are recommended.
3. DateTimeFormatter.format(Instant) will report an error
Error message:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfEra
Analysis reason:
How is the code * * DateTimeFormatter.format(Instant) * * handled?
public String format(TemporalAccessor temporal) { StringBuilder buf = new StringBuilder(32); formatTo(temporal, buf); return buf.toString(); }
First, a new StringBuilder object is created to splice strings;
Then call **formatTo(temporal, buf) * method.
public void formatTo(TemporalAccessor temporal, Appendable appendable) { Objects.requireNonNull(temporal, "temporal"); Objects.requireNonNull(appendable, "appendable"); try { DateTimePrintContext context = new DateTimePrintContext(temporal, this); if (appendable instanceof StringBuilder) { printerParser.format(context, (StringBuilder) appendable); } else { // buffer output to avoid writing to appendable in case of error StringBuilder buf = new StringBuilder(32); printerParser.format(context, buf); appendable.append(buf); } } catch (IOException ex) { throw new DateTimeException(ex.getMessage(), ex); } }
**The formatto (temporary, buf) * * method also judges that the two input parameters are null first.
Then, the Instant object is encapsulated in a new DateTimePrintContext object
If there is a problem running the demo, check it
//Format the date according to a specific format DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String dateStr = DateUtil.format(new Date(),dtf); System.out.println(dateStr);
Here is the source code of jdk. DateTimeFormatter.format
As can be seen from the above, numberprinterparser. Format() will be called. Numberprinterparser is in the DateTimeFormatterBuilder class.
An error will be reported at this step
Why are errors reported? Let's look at what happened to context.getValue(field):
From the above code, temporary is actually an Instant object, and Instant.getLong only supports four field types..
NANO_OF_SECOND MICRO_OF_SECOND MILLI_OF_SECOND INSTANT_SECONDS
If it is not the above field types, an exception is thrown
DateUtil.format when DateTimeFormatter is encountered, it will first convert the Date object to Instant. Because of the lack of time zone, an error will be reported.
Solution:
/** * Format the date according to a specific format * * @param date Formatted date * @param format * @return Formatted string * @since 5.0.0 */ public static String format(Date date, DateTimeFormatter format) { if (null == format || null == date) { return null; } Instant instant = date.toInstant(); ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault()); LocalDateTime localDateTime = zonedDateTime.toLocalDateTime(); return format.format(localDateTime); }
First convert the date type to the LocalDateTime type, and then format the DateTimeFormatter.format(LocalDateTime)
Test demo
//Format the date according to a specific format String str = "2021-07-25 20:11:25"; DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:dd"); Date date = DateUtil.parse(str); String dateStr = DateUtil.format(date,dtf); System.out.println(dateStr); Assert.assertEquals(str, dateStr);
DateTimeFormatterBuilder
DateTimeFormatterBuilder class description
All formatters for DateTimeFormatter are created using the DateTimeFormatterBuilder builder class.
Look at the following two ofPattern source codes:
//DateTimeFormatter public static DateTimeFormatter ofPattern(String pattern) { return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(); } public static DateTimeFormatter ofPattern(String pattern, Locale locale) { return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(locale); }
Parsing style configuration
Four parsing style configurations are officially provided. The SettingsParser is enumerated as follows:
static enum SettingsParser implements DateTimePrinterParser { // Case sensitive SENSITIVE, // Case insensitive INSENSITIVE, //strict STRICT, //easy LENIENT; ... }
Corresponding methods in DateTimeFormatterBuilder class:
// Case sensitive public DateTimeFormatterBuilder parseCaseSensitive() // Case insensitive public DateTimeFormatterBuilder parseCaseInsensitive() // strict public DateTimeFormatterBuilder parseStrict() // easy public DateTimeFormatterBuilder parseLenient()
The corresponding source codes of the four methods are as follows:
// Case sensitive public DateTimeFormatterBuilder parseCaseSensitive() { appendInternal(SettingsParser.SENSITIVE); return this; } // Case insensitive public DateTimeFormatterBuilder parseCaseInsensitive() { appendInternal(SettingsParser.INSENSITIVE); return this; } // strict public DateTimeFormatterBuilder parseStrict() { appendInternal(SettingsParser.STRICT); return this; } // easy public DateTimeFormatterBuilder parseLenient() { appendInternal(SettingsParser.LENIENT); return this; }
As you can see, they all call the appendInternal method.
Next, look at the appendInternal source code:
private int appendInternal(DateTimePrinterParser pp) { Objects.requireNonNull(pp, "pp"); if (active.padNextWidth > 0) { if (pp != null) { pp = new PadPrinterParserDecorator(pp, active.padNextWidth, active.padNextChar); } active.padNextWidth = 0; active.padNextChar = 0; } active.printerParsers.add(pp); active.valueParserIndex = -1; return active.printerParsers.size() - 1; }
active is a DateTimeFormatterBuilder instance, and the DateTimeFormatterBuilder instance has a list list < DateTimePrinterParser >. After reading the source code, we can see that the real parsing work is done by the corresponding instance of DateTimePrinterParser.
Source code of DateTimePrinterParser:
interface DateTimePrinterParser { boolean format(DateTimePrintContext context, StringBuilder buf); int parse(DateTimeParseContext context, CharSequence text, int position); }
There are 16 instances of DateTimePrinterParser in the source code.
//1.Composite printer and parser. static final class CompositePrinterParser implements DateTimePrinterParser {...} //2.Pads the output to a fixed width. static final class PadPrinterParserDecorator implements DateTimePrinterParser {...} //3.Enumeration to apply simple parse settings. static enum SettingsParser implements DateTimePrinterParser{...} //4. Defaults a value into the parse if not currently present. static class DefaultValueParser implements DateTimePrinterParser {...} //5.Prints or parses a character literal. static final class CharLiteralPrinterParser implements DateTimePrinterParser {...} //6.Prints or parses a string literal. static final class StringLiteralPrinterParser implements DateTimePrinterParser {...} //7.Prints and parses a numeric date-time field with optional padding. static class NumberPrinterParser implements DateTimePrinterParser {...} //8.Prints and parses a numeric date-time field with optional padding. static final class FractionPrinterParser implements DateTimePrinterParser {...} //9.Prints or parses field text. static final class TextPrinterParser implements DateTimePrinterParser {...} //10.Prints or parses an ISO-8601 instant. static final class InstantPrinterParser implements DateTimePrinterParser {...} //11.Prints or parses an offset ID. static final class OffsetIdPrinterParser implements DateTimePrinterParser {...} //12.Prints or parses an offset ID. static final class LocalizedOffsetIdPrinterParser implements DateTimePrinterParser {...} //13.Prints or parses a zone ID. static class ZoneIdPrinterParser implements DateTimePrinterParser {...} //14. Prints or parses a chronology. static final class ChronoPrinterParser implements DateTimePrinterParser {...} //15.Prints or parses a localized pattern. static final class LocalizedPrinterParser implements DateTimePrinterParser {...} //16.Prints or parses a localized pattern from a localized field. static final class WeekBasedFieldPrinterParser implements DateTimePrinterParser {...}
(4) JSR-310: common calculation tools
The following describes several classes commonly used for calculation in java8:
- Duration: represents the amount of time in seconds and nanoseconds
- Period: indicates the amount of time on mm / DD / yy
- TemporalUnit: the basic unit of date and time
- TemporalField: attribute of date and time
- ValueRange: indicates the value range
Duration
Duration class description
Package path: java.time.Duration
public final class Duration implements TemporalAmount, Comparable<Duration>, Serializable { private final long seconds; private final int nanos; ... }
Duration is the implementation class of TemporalAmount. The class contains two variables, seconds and nanos, so duration is a time quantity composed of seconds and nanoseconds.
A Duration instance is immutable. After an object is created, its value cannot be changed.
Common usage of Duration
Create Duration object
Duration is suitable for shorter processing time and requires higher accuracy. We can use the between() method to compare the difference between two moments:
Instant first = Instant.now(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Instant second = Instant.now(); Duration duration = Duration.between(first, second); System.out.println(duration);
The Duration object can be obtained through the LocalDateTime class
LocalDateTime first = LocalDateTime.of(2021, 8, 30, 23, 14, 20); LocalDateTime second = LocalDateTime.of(2021, 8, 30, 23, 13, 0); Duration duration = Duration.between(first, second); System.out.println(duration);
Time to access Duration
The second and nanosecond attributes can be obtained from the Duration object. But there is no millisecond attribute, which is different from System.getCurrentTimeMillis().
Instant first = Instant.now(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Instant second = Instant.now(); Duration duration = Duration.between(first, second); System.out.println(duration); System.out.println("second:"+duration.getSeconds()); System.out.println("Nanosecond:"+duration.getNano());
The whole time can be converted into other units, such as nanosecond, millisecond, minute, hour and day
Instant first = Instant.now(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Instant second = Instant.now(); Duration duration = Duration.between(first, second); System.out.println(duration); System.out.println("second:"+duration.getSeconds()); System.out.println("Nanosecond:"+duration.getNano()); System.out.println("nanosecond:"+duration.toNanos()); System.out.println("millisecond:"+duration.toMillis()); System.out.println("Points:"+duration.toMinutes()); System.out.println("Hours:"+duration.toHours()); System.out.println("Days:"+duration.toDays());
It can be seen from the figure that the getNano method is different from the toNanos method. The former is to obtain the part of the time less than 1s, and the latter is to convert the whole time into nanoseconds.
Duration calculation
plusNanos() plusMillis() plusSeconds() plusMinutes() plusHours() plusDays() minusNanos() minusMillis() minusSeconds() minusMinutes() minusHours() minusDays()
Take plusSeconds and minusSeconds as examples:
LocalDateTime first = LocalDateTime.of(2021, 8, 30, 23, 14, 20); LocalDateTime second = LocalDateTime.of(2021, 8, 30, 23, 13, 0); Duration duration = Duration.between(first, second); System.out.println(duration); Duration duration1 = duration.plusSeconds(10); System.out.println("plusSeconds After:"+duration); System.out.println("plusSeconds Post new Duration Object:"+duration1); Duration duration2 = duration.minusSeconds(10); System.out.println("minusSeconds After:"+duration); System.out.println("minusSeconds Post new Duration Object:"+duration2);
It can be seen from the above verification that after these calculation methods are executed, a new Duration object will be returned, and the original Duration object will remain unchanged.
Period
Period class description
Package path: java.time.Period
public final class Period implements ChronoPeriod, Serializable { /** * The number of years. */ private final int years; /** * The number of months. */ private final int months; /** * The number of days. */ private final int days; ... }
Period is the implementation class of ChronoPeriod. The class contains two variables: years, months and days. Therefore, period is a time quantity composed of year, month and day.
Common usage of Period
Create Period object
LocalDate first = LocalDate.of(2021, 8, 29); LocalDate second = LocalDate.of(2022, 9, 30); Period period = Period.between(first, second); System.out.println(period);
Time to access Period
LocalDate first = LocalDate.of(2021, 8, 28); LocalDate second = LocalDate.of(2022, 10, 31); Period period = Period.between(first, second); System.out.println(period); System.out.println("year:"+period.getYears()); System.out.println("Month:"+period.getMonths()); System.out.println("Date:"+period.getDays());
You can convert the whole time into other units, months
LocalDate first = LocalDate.of(2021, 8, 29); LocalDate second = LocalDate.of(2022, 9, 30); Period period = Period.between(first, second); System.out.println(period); System.out.println("month:"+period.toTotalMonths());
It can be seen from the figure that the getMonths method is different from the totalmonths method. The former is to obtain the month of this period, and the latter is to convert the whole time into the length in months.
Totalmonths source code:
public long toTotalMonths() { return years * 12L + months; // no overflow }
Duration calculation
plusDays() plusMonths() plusYears() minusDays() minusMonths() minusYears()
Take plusMonths and minusMonths as examples:
LocalDate first = LocalDate.of(2021, 8, 28); LocalDate second = LocalDate.of(2022, 10, 31); Period period = Period.between(first, second); System.out.println(period); Period period1 = period.plusMonths(1); System.out.println("plusMonths After:"+period); System.out.println("plusMonths Post new Period Object:"+period1); Period period2 = period.minusMonths(1); System.out.println("minusMonths After:"+period); System.out.println("minusMonths Post new Period Object:"+period2);
It can be seen from the above verification that after these calculation methods are executed, a new Period object will be returned, and the original Period object will remain unchanged.
TemporalUnit
TemporalUnit class description
Package path: java.time.temporary.temporalunit
public interface TemporalUnit { ... } public enum ChronoUnit implements TemporalUnit { private final String name; private final Duration duration; ... }
The main implementation class of TemporalUnit is the enumeration type chrononunit
A chrononunit member maintains a string name attribute name and an instance of the Duration type.
Chrononunit enumerates the standard date time unit collection, that is, the commonly used year, month, day, hour, minute, second, millisecond, microsecond and nanosecond. The time amount of these time units and the time represented are defined in this enumeration class.
public enum ChronoUnit implements TemporalUnit { NANOS("Nanos", Duration.ofNanos(1)), MICROS("Micros", Duration.ofNanos(1000)), MILLIS("Millis", Duration.ofNanos(1000_000)), SECONDS("Seconds", Duration.ofSeconds(1)), MINUTES("Minutes", Duration.ofSeconds(60)), HOURS("Hours", Duration.ofSeconds(3600)), HALF_DAYS("HalfDays", Duration.ofSeconds(43200)), DAYS("Days", Duration.ofSeconds(86400)), WEEKS("Weeks", Duration.ofSeconds(7 * 86400L)), MONTHS("Months", Duration.ofSeconds(31556952L / 12)), YEARS("Years", Duration.ofSeconds(31556952L)), DECADES("Decades", Duration.ofSeconds(31556952L * 10L)), CENTURIES("Centuries", Duration.ofSeconds(31556952L * 100L)), MILLENNIA("Millennia", Duration.ofSeconds(31556952L * 1000L)), ERAS("Eras", Duration.ofSeconds(31556952L * 1000_000_000L)), FOREVER("Forever", Duration.ofSeconds(Long.MAX_VALUE, 999_999_999)); private final String name; private final Duration duration; private ChronoUnit(String name, Duration estimatedDuration) { this.name = name; this.duration = estimatedDuration; } ··· }
Common usage of chrononunit
LocalDateTime localDateTime = LocalDateTime.of(2021, 8, 30, 23, 14, 20); LocalDateTime offset = localDateTime.plus(1, ChronoUnit.DAYS); // Not the same object Assert.assertNotSame(localDateTime, offset); System.out.println(offset);
TemporalField
TemporalField class description
Package path: java.time.temporary.temporalfield
public interface TemporalField { ... } public enum ChronoField implements TemporalField { private final String name; private final TemporalUnit baseUnit; private final TemporalUnit rangeUnit; private final ValueRange range; ... }
The main implementation class of TemporalField is the enumeration type ChronoField
A ChronoField member will maintain a string name attribute name, a TemporalUnit base unit baseUnit, a TemporalUnit range unit and a ValueRange type range to represent the range of the current attribute.
public enum ChronoField implements TemporalField { //Nanoseconds per second NANO_OF_SECOND("NanoOfSecond", NANOS, SECONDS, ValueRange.of(0, 999_999_999)) //Seconds in a minute SECOND_OF_MINUTE("SecondOfMinute", SECONDS, MINUTES, ValueRange.of(0, 59), "second") //Minutes in an hour MINUTE_OF_HOUR("MinuteOfHour", MINUTES, HOURS, ValueRange.of(0, 59), "minute") //How many hours are there in a morning or an afternoon CLOCK_HOUR_OF_AMPM("ClockHourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(1, 12)) //Hours of the day CLOCK_HOUR_OF_DAY("ClockHourOfDay", HOURS, DAYS, ValueRange.of(1, 24)) //Morning or afternoon AMPM_OF_DAY("AmPmOfDay", HALF_DAYS, DAYS, ValueRange.of(0, 1), "dayperiod") //What day of the week DAY_OF_WEEK("DayOfWeek", DAYS, WEEKS, ValueRange.of(1, 7), "weekday") //Days of the current month DAY_OF_MONTH("DayOfMonth", DAYS, MONTHS, ValueRange.of(1, 28, 31), "day") //Number of days in the current year DAY_OF_YEAR("DayOfYear", DAYS, YEARS, ValueRange.of(1, 365, 366)) //Weeks of the current month ALIGNED_WEEK_OF_MONTH("AlignedWeekOfMonth", WEEKS, MONTHS, ValueRange.of(1, 4, 5)) //Number of weeks in the current year ALIGNED_WEEK_OF_YEAR("AlignedWeekOfYear", WEEKS, YEARS, ValueRange.of(1, 53)) //Take the first day of each month as Monday, and then calculate the day of the week ALIGNED_DAY_OF_WEEK_IN_MONTH("AlignedDayOfWeekInMonth", DAYS, WEEKS, ValueRange.of(1, 7)) //Take the first day of each month as Monday, and then calculate the day of the week ALIGNED_DAY_OF_WEEK_IN_YEAR("AlignedDayOfWeekInYear", DAYS, WEEKS, ValueRange.of(1, 7)) //Number of months in the current year MONTH_OF_YEAR("MonthOfYear", MONTHS, YEARS, ValueRange.of(1, 12), "month") private final TemporalUnit baseUnit; private final String name; private final TemporalUnit rangeUnit; private final ValueRange range; private final String displayNameKey; ... }
Common usage of ChronoField
ALIGNED_WEEK_OF_MONTH and ALIGNED_DAY_OF_WEEK_IN_MONTH usage example
//Every seven days a week, 2021-08-31 is Tuesday, and the corresponding value is 3 int num = LocalDate.of(2021, 8, 31).get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH); System.out.println(num); //The fifth week of this month 2021-08-31 num = LocalDate.of(2021, 8, 31).get(ChronoField.ALIGNED_WEEK_OF_MONTH); System.out.println(num);
ValueRange
ValueRange class description
ValueRange indicates the value range.
public final class ValueRange implements Serializable { /** * The smallest minimum value.minimum value */ private final long minSmallest; /** * The largest minimum value.Maximum possible minimum */ private final long minLargest; /** * The smallest maximum value.Minimum possible maximum */ private final long maxSmallest; /** * The largest maximum value.Maximum */ private final long maxLargest; ... }
Common usage of ValueRange
ValueRange valueRange = ValueRange.of(1L, 10000L); System.out.println(valueRange); valueRange = ValueRange.of(1L, 5L, 10000L, 50000L); System.out.println(valueRange);
LocalDateTime localDateTime = LocalDateTime.of(2021, 8, 30, 23, 14, 20); ValueRange valueRange = localDateTime.range(ChronoField.DAY_OF_MONTH); System.out.println(valueRange.getMinimum()); System.out.println(valueRange.getMaximum()); System.out.println(valueRange.getLargestMinimum()); System.out.println(valueRange.getSmallestMaximum());
Chronology determines whether a leap year
To judge whether leap years are provided by Chronology, we usually use the Chronology under ISO, which is IsoChronology.
Look at the code implementation
@Override public boolean isLeapYear(long prolepticYear) { return ((prolepticYear & 3) == 0) && ((prolepticYear % 100) != 0 || (prolepticYear % 400) == 0); }
Good refined code, worthy of our study
Basic judgment method of leap year:
1. Non integral hundred years: leap years are those that can be divided by 4. (for example, 2004 is a leap year, and 2001 is not a leap year)
2. Whole hundred years: leap years can be divided by 400. (for example, 2000 is a leap year and 1900 is not a leap year)
((prolepticYear & 3) == 0) && ((prolepticYear % 100) != 0 || (prolepticYear % 400) == 0);
This code uses two conditions. If both conditions are met, it is a leap year.
-
(prolepticYear & 3) == 0
-
(prolepticYear % 100) != 0 || (prolepticYear % 400) == 0
(prolepticyear & 3) = = 0 uses the and operator "&", and its usage law is as follows:
If the median of both operands is 1, the result is 1, otherwise the result is 0.
The binary of 3 is 011, and the purpose of prolepticyear & 3 is to retain the last two binary digits, and then judge whether the last two binary digits are equal to 0. If it is equal to 0, it is proved that it can be divided by 4. Leap years must meet the condition that they are multiples of 4;
(prolepticYear % 100) != 0 | (prolepticyear% 400) = = 0, which is easy to understand. See whether it is a multiple of 100 or 400.
Moreover, Xiao xuzhu found that the implementation code logic used by java.time.Year#isLeap() is the same
public static boolean isLeap(long year) { return ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0); }
Even the code written by the giant has the problem of reusability
IsoChronology above is the implementation of isLeapYear for the Chronology interface, and isLeapYear for implementation classes such as MinguoChronology, which uses the isLeapYear method of IsoChronology.
//MinguoChronology public boolean isLeapYear(long prolepticYear) { return IsoChronology.INSTANCE.isLeapYear(prolepticYear + YEARS_DIFFERENCE); }
Giant has considered reuse. It has been reused in MinguoChronology and other implementation classes.
java.time.Year#isLeap() has high priority because it is a static method. isoChronology * * you can quote Year.isLeap**
Year * * cannot quote Chronology.isLeapYear * *.
Bloggers found that there is already a reference to Year.isLeap in resolveYMD * * of IsoChronology * *.
In order to reduce the external class dependency, some tool classes will rewrite the underlying methods to avoid the class dependency of external classes (or not under a package). This has been used and can not be justified. Therefore, the code has the problem of reusability.
actual combat
int year = 2020; System.out.println(Year.isLeap(year)); System.out.println(IsoChronology.INSTANCE.isLeapYear(year)); LocalDate localDate = LocalDate.of(2021,9,7); LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDate.isLeapYear()); System.out.println(localDateTime.toLocalDate().isLeapYear());
Compare the sequence of dates and times
Basically, there are four comparison methods: compareTo(), isBefore(), isAfter(), and equals()
Compare - LocalDate
LocalDate localDate1 = LocalDate.of(2021, 8, 14); // Compare the specified date with the parameter date and return a positive number, then the specified date and time is later (the number is larger): 13 int i = localDate1.compareTo(LocalDate.of(2021, 8, 1)); System.out.println(i); // Compare whether the specified date is earlier than the parameter date (true is earlier): true System.out.println(localDate1.isBefore(LocalDate.of(2021,8,31))); // Compare whether the specified date is later than the parameter date (true is later): false System.out.println(localDate1.isAfter(LocalDate.of(2021,8,31))); // Compare whether two dates are equal: true System.out.println(localDate1.isEqual(LocalDate.of(2021, 8, 14)));
Compare - LocalTime
LocalTime localTime1 = LocalTime.of(23, 26, 30); LocalTime localTime2 = LocalTime.of(23, 26, 32); // When comparing the two times, the large returns 1, the small returns - 1, and the same returns 0: - 1 System.out.println(localTime1.compareTo(localTime2)); // Compare whether the specified time is earlier than the parameter time (true is earlier): true System.out.println(localTime1.isBefore(localTime2)); // Compare whether the specified time is later than the parameter time (true is later): false System.out.println(localTime1.isAfter(localTime2)); // Compare whether two times are equal: true System.out.println(localTime1.equals(LocalTime.of(23, 26, 30)));
Compare - OffsetDateTime
LocalDateTime localDateTime1 = LocalDateTime.of(2021, 8, 15, 13, 14, 20); OffsetDateTime offsetDateTime1 = OffsetDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); OffsetDateTime offsetDateTime3 = OffsetDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); LocalDateTime localDateTime2 = LocalDateTime.of(2021, 8, 15, 13, 14, 30); OffsetDateTime offsetDateTime2 = OffsetDateTime.of(localDateTime2, ZoneOffset.ofHours(8)); // When comparing the two times, the large returns 1, the small returns - 1, and the same returns 0: - 1 System.out.println(offsetDateTime1.compareTo(offsetDateTime2)); // Compare whether the specified time is earlier than the parameter time (true is earlier): true System.out.println(offsetDateTime1.isBefore(offsetDateTime2)); // Compare whether the specified time is later than the parameter time (true is later): false System.out.println(offsetDateTime1.isAfter(offsetDateTime2)); // Compare whether two times are equal: true System.out.println(offsetDateTime1.equals(offsetDateTime3));
Compare - OffsetTime
LocalTime localTime1 = LocalTime.of( 13, 14, 20); OffsetTime offsetTime1 = OffsetTime.of(localTime1, ZoneOffset.ofHours(8)); OffsetTime offsetTime3 = OffsetTime.of(localTime1, ZoneOffset.ofHours(8)); LocalTime localTime2 = LocalTime.of(13, 14, 30); OffsetTime offsetTime2 = OffsetTime.of(localTime2, ZoneOffset.ofHours(8)); // When comparing the two times, the large returns 1, the small returns - 1, and the same returns 0: - 1 System.out.println(offsetTime1.compareTo(offsetTime2)); // Compare whether the specified time is earlier than the parameter time (true is earlier): true System.out.println(offsetTime1.isBefore(offsetTime2)); // Compare whether the specified time is later than the parameter time (true is later): false System.out.println(offsetTime1.isAfter(offsetTime2)); // Compare whether two times are equal: true System.out.println(offsetTime1.equals(offsetTime3));
Compare ZonedDateTime
LocalDateTime localDateTime1 = LocalDateTime.of(2021, 8, 15, 13, 14, 20); ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); ZonedDateTime zonedDateTime3 = ZonedDateTime.of(localDateTime1, ZoneOffset.ofHours(8)); LocalDateTime localDateTime2 = LocalDateTime.of(2021, 8, 15, 13, 14, 30); ZonedDateTime zonedDateTime2 = ZonedDateTime.of(localDateTime2, ZoneOffset.ofHours(8)); // When comparing the two times, the large returns 1, the small returns - 1, and the same returns 0: - 1 System.out.println(zonedDateTime1.compareTo(zonedDateTime2)); // Compare whether the specified time is earlier than the parameter time (true is earlier): true System.out.println(zonedDateTime1.isBefore(zonedDateTime2)); // Compare whether the specified time is later than the parameter time (true is later): false System.out.println(zonedDateTime1.isAfter(zonedDateTime2)); // Compare whether two times are equal: true System.out.println(zonedDateTime1.equals(zonedDateTime3));
Calculate the interval between dates and times
Both Duration and * * Period * * have * * between * * methods
This is not repeated. It is introduced in the common usage of Duration and Period above.
TemporalAdjuster date calibrator
Serial number | method | describe |
---|---|---|
1 | dayOfWeekInMonth | Returns the day ordinal of the week in the same month |
2 | firstDayOfMonth | Returns the first day of the month |
3 | firstDayOfNextMonth | Return to the first day of next month |
4 | firstDayOfNextYear | Return to the first day of the next year |
5 | firstDayOfYear | Return to the first day of the year |
6 | firstInMonth | Returns the first day of the week in the same month |
7 | lastDayOfMonth | Returns the last day of the month |
8 | lastDayOfNextMonth | Return to the last day of next month |
9 | lastDayOfNextYear | Return to the last day of the next year |
0 | lastDayOfYear | Return to the last day of the year |
11 | lastInMonth | Returns the last day of the week in the same month |
12 | next / previous | Returns the given day of the week after / before |
13 | nextOrSame / previousOrSame | Returns the last / previous given day of the week. If this value meets the conditions, it will be returned directly |
LocalDateTime now = LocalDateTime.of(2021,9,8,0,20,13); System.out.println("Current time:" + now + "======>" + now.getDayOfWeek()); System.out.println("Next Monday:" + now.with(TemporalAdjusters.next(DayOfWeek.MONDAY))); System.out.println("Last Monday:" + now.with(TemporalAdjusters.previous(DayOfWeek.MONDAY))); System.out.println("Next Friday:" + now.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))); System.out.println("Last Friday:" + now.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY))); System.out.println("Last Friday of the month:" + now.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY))); System.out.println("The first Friday of this month:" + now.with(TemporalAdjusters.firstInMonth(DayOfWeek.FRIDAY))); System.out.println("First day of the month:" + now.with(TemporalAdjusters.firstDayOfMonth())); System.out.println("Last day of the month:" + now.with(TemporalAdjusters.lastDayOfMonth())); System.out.println("First day of next month:" + now.with(TemporalAdjusters.firstDayOfNextMonth())); System.out.println("First day of the year:" + now.with(TemporalAdjusters.firstDayOfYear())); System.out.println("Last day of the year:" + now.with(TemporalAdjusters.lastDayOfYear())); System.out.println("The first day of the following year:" + now.with(TemporalAdjusters.firstDayOfNextYear())); System.out.println("The second Friday of the month:" + now.with(TemporalAdjusters.dayOfWeekInMonth(2,DayOfWeek.FRIDAY))); System.out.println("Two weeks later:" + now.with(TemporalAdjusters.ofDateAdjuster(date -> date.plusWeeks(2))));
(5) JSR-310: actual combat + source code analysis
Usage scenario
Encapsulate the date and time tool class in JDK8 +
Project reference
The basis of this blog post: hutool-5.6.5 version source code
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-core</artifactId> <version>5.6.5</version> </dependency>
Method summary
method | describe |
---|---|
cn.hutool.core.date.LocalDateTimeUtil.now() |
Current time, default time zone
|
cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant) |
{@ link Instant} to {@ link LocalDateTime}, using the default time zone
|
cn.hutool.core.date.LocalDateTimeUtil.ofUTC(java.time.Instant) |
{@ link Instant} to {@ link LocalDateTime}, using UTC time zone
|
cn.hutool.core.date.LocalDateTimeUtil.of(java.time.ZonedDateTime) |
{@ link ZonedDateTime} to {@ link LocalDateTime}
|
cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant, java.time.ZoneId) |
{@ link Instant} to {@ link LocalDateTime}
|
cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant, java.util.TimeZone) |
{@ link Instant} to {@ link LocalDateTime}
|
cn.hutool.core.date.LocalDateTimeUtil.of(long) |
Milliseconds to {@ link LocalDateTime}, using the default time zone
Note: this method uses the default time zone. If it is not UTC, it will produce a time offset |
cn.hutool.core.date.LocalDateTimeUtil.ofUTC(long) |
MS to {@ link LocalDateTime}, using UTC time zone
|
cn.hutool.core.date.LocalDateTimeUtil.of(long, java.time.ZoneId) |
Milliseconds to {@ link LocalDateTime}. Depending on the time zone, the result will have a time offset
|
cn.hutool.core.date.LocalDateTimeUtil.of(long, java.util.TimeZone) |
Milliseconds to {@ link LocalDateTime}, resulting in a time offset
|
cn.hutool.core.date.LocalDateTimeUtil.of(java.util.Date) |
{@ link Date} to {@ link LocalDateTime}, using the default time zone
|
cn.hutool.core.date.LocalDateTimeUtil.of(java.time.temporal.TemporalAccessor) |
{@ link TemporalAccessor} go to {@ link LocalDateTime} and use the default time zone
|
cn.hutool.core.date.LocalDateTimeUtil.ofDate(java.time.temporal.TemporalAccessor) |
{@ link TemporalAccessor} to {@ link LocalDate}, using the default time zone
|
cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence) |
The parsed date time string is {@ link LocalDateTime}. Only yyyy MM DD'T 'HH:mm:ss format is supported, for example: 2007-12-03T10:15:30
|
cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence, java.time.format.DateTimeFormatter) |
The parsed date time string is {@ link LocalDateTime}. The format supports date time, date and time
|
cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence, java.lang.String) |
Resolve the date time string to {@ link LocalDateTime}
|
cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence) |
The parsed date and time string is {@ link LocalDate}. Only yyyy MM DD'T 'HH:mm:ss format is supported, for example: 2007-12-03T10:15:30
|
cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence, java.time.format.DateTimeFormatter) |
The parsed date time string is {@ link LocalDate}, and the format supports date
|
cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence, java.lang.String) |
Parse date string as {@ link LocalDate}
|
cn.hutool.core.date.LocalDateTimeUtil.formatNormal(java.time.LocalDateTime) |
Format the date and time in yyyy MM DD HH: mm: SS format
|
cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDateTime, java.time.format.DateTimeFormatter) |
Format the date and time in the specified format
|
cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDateTime, java.lang.String) |
Format the date and time in the specified format
|
cn.hutool.core.date.LocalDateTimeUtil.formatNormal(java.time.LocalDate) |
Format the date and time in yyyy MM DD format
|
cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDate, java.time.format.DateTimeFormatter) |
Format the date and time in the specified format
|
cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDate, java.lang.String) |
Format the date and time in the specified format
|
cn.hutool.core.date.LocalDateTimeUtil.offset(java.time.LocalDateTime, long, java.time.temporal.TemporalUnit) |
Date offset: add different values according to different field s (offset will modify the incoming objects)
|
cn.hutool.core.date.LocalDateTimeUtil.between(java.time.LocalDateTime, java.time.LocalDateTime) |
Gets the difference between two dates. If the end time is earlier than the start time, the result is negative.
The returned result is the {@ link Duration} object, and the phase difference unit is returned by calling the toXXX method |
cn.hutool.core.date.LocalDateTimeUtil.between(java.time.LocalDateTime, java.time.LocalDateTime, java.time.temporal.ChronoUnit) |
Gets the difference between two dates. If the end time is earlier than the start time, the result is negative.
The return result is a long value of time difference |
cn.hutool.core.date.LocalDateTimeUtil.betweenPeriod(java.time.LocalDate, java.time.LocalDate) |
Get the apparent time difference between two dates. If the end time is earlier than the start time, the result is negative.
For example, February 1, 2011 and August 11, 2021 differ by 10 days and 6 months respectively |
cn.hutool.core.date.LocalDateTimeUtil.beginOfDay(java.time.LocalDateTime) |
Modify to the start time of the day, for example: 2020-02-02 00:00:00000
|
cn.hutool.core.date.LocalDateTimeUtil.endOfDay(java.time.LocalDateTime) |
Modify to the end time of the day, for example: 2020-02-02 23:59:59999
|
cn.hutool.core.date.LocalDateTimeUtil.toEpochMilli(java.time.temporal.TemporalAccessor) |
{@ link TemporalAccessor} converted to timestamp (number of milliseconds from 1970-01-01T00:00:00Z)
|
Method details - now()
Method name: cn.hutool.core.date.LocalDateTimeUtil.now()
Method description
Current time, default time zone
Supported version and above
Parameter Description:
Parameter name | describe |
---|
Return value:
{@link LocalDateTime}
Reference case:
Assert.assertNotNull(LocalDateTimeUtil.now()); System.out.println(LocalDateTimeUtil.now());
Source code analysis:
/** * Current time, default time zone * * @return {@link LocalDateTime} */ public static LocalDateTime now() { return LocalDateTime.now(); }
Source code of LocalDateTime.now()
public static LocalDateTime now() { return now(Clock.systemDefaultZone()); }
Clock.systemDefaultZone()
The system default time zone ZoneId.systemDefault() is used
public static Clock systemDefaultZone() { return new SystemClock(ZoneId.systemDefault()); }
Finally, System.currentTimeMillis() is called
Method details - of(java.time.Instant)
Method name: cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant)
Method description
{@ link Instant} to {@ link LocalDateTime}, using the default time zone
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
Instant instant |
instant {@link Instant}
|
Return value:
{@link LocalDateTime}
Reference case:
String dateStr = "2020-01-23 12:23:56"; final DateTime dt = DateUtil.parse(dateStr); LocalDateTime of = LocalDateTimeUtil.of(dt.toInstant()); System.out.println(of);
Source code analysis:
public static LocalDateTime of(Instant instant) { return of(instant, ZoneId.systemDefault()); }
The default time zone is used here, so the printed date and time is with time zone.
public static LocalDateTime of(Instant instant, ZoneId zoneId) { if (null == instant) { return null; } return LocalDateTime.ofInstant(instant, ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault())); }
Method details - ofUTC(java.time.Instant)
Method name: cn.hutool.core.date.LocalDateTimeUtil.ofUTC(java.time.Instant)
Method description
{@ link Instant} to {@ link LocalDateTime}, using UTC time zone
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
Instant instant |
instant {@link Instant}
|
Return value:
{@link LocalDateTime}
Reference case:
String dateStr = "2020-01-23T12:23:56"; final DateTime dt = DateUtil.parse(dateStr); LocalDateTime of = LocalDateTimeUtil.ofUTC(dt.toInstant()); Assert.assertEquals(dateStr, of.toString()); System.out.println(of);
Source code analysis:
public static LocalDateTime ofUTC(Instant instant) { return of(instant, ZoneId.of("UTC")); }
The UTC time zone is used here, and the next LocalDateTime.ofInstant is called.
public static LocalDateTime of(Instant instant, ZoneId zoneId) { if (null == instant) { return null; } return LocalDateTime.ofInstant(instant, ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault())); }
Method details - of(java.time.ZonedDateTime)
Method name: cn.hutool.core.date.LocalDateTimeUtil.of(java.time.ZonedDateTime)
Method description
{@ link ZonedDateTime} to {@ link LocalDateTime}
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
ZonedDateTime zonedDateTime |
zonedDateTime {@link ZonedDateTime}
|
Return value:
{@link LocalDateTime}
Reference case:
String dateStr = "2021-05-21T11:23:56"; final DateTime dt = DateUtil.parse(dateStr); //Use default time zone LocalDateTime localDateTime = LocalDateTimeUtil.of(dt); System.out.println(localDateTime); ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault()); System.out.println(zonedDateTime); zonedDateTime = localDateTime.atZone( ZoneId.of("Asia/Shanghai")); System.out.println(zonedDateTime); LocalDateTime of = LocalDateTimeUtil.of(zonedDateTime); Assert.assertNotNull(of); Assert.assertEquals("2021-05-21T11:23:56", of.toString());
Source code analysis:
public static LocalDateTime of(ZonedDateTime zonedDateTime) { if (null == zonedDateTime) { return null; } return zonedDateTime.toLocalDateTime(); }
Here, first judge whether the parameter is null
Then call zonedDateTime.toLocalDateTime().
We know that zonedDateTime and LocalDateTime can be directly converted
Method details - of(java.time.Instant, java.time.ZoneId)
Method name: cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant, java.time.ZoneId)
Method description
{@ link Instant} to {@ link LocalDateTime}
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
Instant instant |
instant {@link Instant}
|
ZoneId zoneId |
zoneId time zone
|
Return value:
{@link LocalDateTime}
Reference case:
String dateStr = "2021-05-21T11:23:56"; final DateTime dt = DateUtil.parse(dateStr); LocalDateTime of = LocalDateTimeUtil.of(dt.getTime(), ZoneId.of("UTC")); Assert.assertNotNull(of); Assert.assertEquals(dateStr, of.toString()); of = LocalDateTimeUtil.of(dt.getTime(), ZoneId.of("Asia/Shanghai")); Assert.assertNotNull(of); Assert.assertEquals("2021-05-21T19:23:56", of.toString());
Source code analysis:
public static LocalDateTime of(Instant instant, ZoneId zoneId) { if (null == instant) { return null; } return LocalDateTime.ofInstant(instant, ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault())); }
Here, first judge whether the parameter is null
Then, execute LocalDateTime.ofInstant(instant, ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault()))
There are two parts:
1,ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault())
2,LocalDateTime.ofInstant(instant, zoneId)
ObjectUtil.defaultIfNull(zoneId, ZoneId.systemDefault())
public static <T> T defaultIfNull(final T object, final T defaultValue) { return (null != object) ? object : defaultValue; }
This is easy to understand. Judge whether the value is null. If it is, return the default value. If not, return the original value.
**LocalDateTime.ofInstant(instant, zoneId) * * is jdk8's own source generated method
Method details - of(java.time.Instant, java.util.TimeZone)
Method name: cn.hutool.core.date.LocalDateTimeUtil.of(java.time.Instant, java.util.TimeZone)
Method description
{@ link Instant} to {@ link LocalDateTime}
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
Instant instant |
instant {@link Instant}
|
TimeZone timeZone |
timeZone time zone
|
Return value:
{@link LocalDateTime}
Reference case:
String dateStr = "2021-05-21T11:23:56"; // The Instant obtained through conversion is UTC time Instant instant1 = DateUtil.parse(dateStr).toInstant(); LocalDateTime localDateTime = LocalDateTimeUtil.of(instant1,TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai"))); Assert.assertEquals("2021-05-21T19:23:56", localDateTime.toString()); System.out.println(localDateTime);
Source code analysis:
public static LocalDateTime of(Instant instant, TimeZone timeZone) { if (null == instant) { return null; } return of(instant, ObjectUtil.defaultIfNull(timeZone, TimeZone.getDefault()).toZoneId()); }
Here, first judge whether the parameter is null
Then, execute LocalDateTime.ofInstant(timeZone, zoneId)
There are two parts:
1,ObjectUtil.defaultIfNull(timeZone, ObjectUtil.defaultIfNull(timeZone, TimeZone.getDefault()).toZoneId())
2,LocalDateTime.ofInstant(timeZone, zoneId)
ObjectUtil.defaultIfNull(timeZone, ObjectUtil.defaultIfNull(timeZone, TimeZone.getDefault()).toZoneId())
public static <T> T defaultIfNull(final T object, final T defaultValue) { return (null != object) ? object : defaultValue; }
This is easy to understand. Judge whether the value is null. If it is, return the default value. If not, return the original value.
**LocalDateTime.ofInstant(instant, zoneId) * * is jdk8's own source generated method
Method details - of(long)
Method name: cn.hutool.core.date.LocalDateTimeUtil.of(long)
Method description
Milliseconds to {@ link LocalDateTime}, using the default time zone
Note: this method uses the default time zone. If it is not UTC, it will produce a time offset
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
long epochMilli |
epochMilli the number of milliseconds counted from 1970-01-01T00:00:00Z
|
Return value:
{@link LocalDateTime}
Reference case:
String dateStr = "2021-05-22 10:23:56"; Long time = DateUtil.parse(dateStr).getTime(); // Use default time zone LocalDateTime localDateTime = LocalDateTimeUtil.of(time); Assert.assertEquals("2021-05-22T10:23:56", localDateTime.toString()); System.out.println(localDateTime);
Source code analysis:
public static LocalDateTime of(long epochMilli) { return of(Instant.ofEpochMilli(epochMilli)); }
This is to convert long into Instant
public static Instant ofEpochMilli(long epochMilli) { long secs = Math.floorDiv(epochMilli, 1000); int mos = (int)Math.floorMod(epochMilli, 1000); return create(secs, mos * 1000_000); }
Then call of(Instant)
public static LocalDateTime of(Instant instant) { return of(instant, ZoneId.systemDefault()); }
Method details - ofUTC(long)
Method name: cn.hutool.core.date.LocalDateTimeUtil.ofUTC(long)
Method description
MS to {@ link LocalDateTime}, using UTC time zone
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
long epochMilli |
epochMilli the number of milliseconds counted from 1970-01-01T00:00:00Z
|
Return value:
{@link LocalDateTime}
Reference case:
String dateStr = "2021-05-22T10:23:56"; Long time = DateUtil.parse(dateStr).getTime(); // Use UTC time zone LocalDateTime localDateTime = LocalDateTimeUtil.ofUTC(time); Assert.assertEquals("2021-05-22T10:23:56", localDateTime.toString()); System.out.println(localDateTime);
Source code analysis:
public static LocalDateTime ofUTC(long epochMilli) { return ofUTC(Instant.ofEpochMilli(epochMilli)); }
This is to convert long into Instant
public static Instant ofEpochMilli(long epochMilli) { long secs = Math.floorDiv(epochMilli, 1000); int mos = (int)Math.floorMod(epochMilli, 1000); return create(secs, mos * 1000_000); }
Then call ofUTC(Instant)
public static LocalDateTime ofUTC(Instant instant) { return of(instant, ZoneId.of("UTC")); }
Method details - of(long, java.time.ZoneId)
Method name: cn.hutool.core.date.LocalDateTimeUtil.of(long, java.time.ZoneId)
Method description
Milliseconds to {@ link LocalDateTime}. Depending on the time zone, the result will have a time offset
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
long epochMilli |
epochMilli the number of milliseconds counted from 1970-01-01T00:00:00Z
|
ZoneId zoneId |
zoneId time zone
|
Return value:
{@link LocalDateTime}
Reference case:
String dateStr = "2021-05-22T10:23:56"; Long time = DateUtil.parse(dateStr).getTime(); LocalDateTime localDateTime = LocalDateTimeUtil.of(time,ZoneId.of("Asia/Shanghai")); Assert.assertEquals("2021-05-22T18:23:56", localDateTime.toString());
Source code analysis:
/** * Milliseconds to {@ link LocalDateTime}. Depending on the time zone, the result will have a time offset * * @param epochMilli Number of milliseconds counted from 1970-01-01T00:00:00Z * @param zoneId time zone * @return {@link LocalDateTime} */ public static LocalDateTime of(long epochMilli, ZoneId zoneId) { return of(Instant.ofEpochMilli(epochMilli), zoneId); }
This is to convert long into Instant
public static Instant ofEpochMilli(long epochMilli) { long secs = Math.floorDiv(epochMilli, 1000); int mos = (int)Math.floorMod(epochMilli, 1000); return create(secs, mos * 1000_000); }
Then call of(Instant, zoneId)
The above method has been analyzed many times, so the number of water words will not be repeated.
Method details - of(long, java.util.TimeZone)
Method name: cn.hutool.core.date.LocalDateTimeUtil.of(long, java.util.TimeZone)
Method description
Milliseconds to {@ link LocalDateTime}, resulting in a time offset
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
long epochMilli |
epochMilli the number of milliseconds counted from 1970-01-01T00:00:00Z
|
TimeZone timeZone |
timeZone time zone
|
Return value:
{@link LocalDateTime}
Reference case:
String dateStr = "2021-05-22T10:23:56"; Long time = DateUtil.parse(dateStr).getTime(); LocalDateTime localDateTime = LocalDateTimeUtil.of(time, TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai"))); Assert.assertEquals("2021-05-22T18:23:56", localDateTime.toString());
Source code analysis:
public static LocalDateTime of(long epochMilli, TimeZone timeZone) { return of(Instant.ofEpochMilli(epochMilli), timeZone); }
This is to convert long into Instant
public static Instant ofEpochMilli(long epochMilli) { long secs = Math.floorDiv(epochMilli, 1000); int mos = (int)Math.floorMod(epochMilli, 1000); return create(secs, mos * 1000_000); }
Then call of(Instant, timeZone)
The above method has been analyzed many times, so the number of water words will not be repeated.
Method details -of(java.util.Date)
Method name: cn.hutool.core.date.LocalDateTimeUtil.of(java.util.Date)
Method description
{@ link Date} to {@ link LocalDateTime}, using the default time zone
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
Date date |
Date object
|
Return value:
{@link LocalDateTime}
Reference case:
String dateStr = "2021-05-22 10:23:56"; DateTime date = DateUtil.parse(dateStr); //Use default time zone LocalDateTime localDateTime = LocalDateTimeUtil.of(date); Assert.assertEquals("2021-05-22T10:23:56", localDateTime.toString());
Source code analysis:
public static LocalDateTime of(Date date) { if (null == date) { return null; } if (date instanceof DateTime) { return of(date.toInstant(), ((DateTime) date).getZoneId()); } return of(date.toInstant()); }
This method is to strongly convert Date to LocalDateTime
Good habit. First judge whether the parameter date is empty
if (date instanceof DateTime) { return of(date.toInstant(), ((DateTime) date).getZoneId()); }
This DateTime is an object encapsulated by hutool. It inherits from Date and encapsulates some common methods
If it is not the first two, of(date.Instant) is called
Method details - of (Java. Time. Temporary. Temporalaccessor)
Method name: cn.hutool.core.date.localdatetimeutil.of (Java. Time. Temporary. Temporalaccessor)
Method description
{@ link TemporalAccessor} go to {@ link LocalDateTime} and use the default time zone
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
TemporalAccessor temporalAccessor |
temporalAccessor {@link TemporalAccessor}
|
Return value:
{@link LocalDateTime}
Reference case:
String dateStr = "2021-05-22T10:23:56"; //Use default time zone TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE_TIME.parse(dateStr); LocalDateTime localDateTime = LocalDateTimeUtil.of(temporalAccessor); Assert.assertEquals("2021-05-22T10:23:56", localDateTime.toString());
Source code analysis:
public static LocalDateTime of(TemporalAccessor temporalAccessor) { if (null == temporalAccessor) { return null; } if(temporalAccessor instanceof LocalDate){ return ((LocalDate)temporalAccessor).atStartOfDay(); } return LocalDateTime.of( TemporalAccessorUtil.get(temporalAccessor, ChronoField.YEAR), TemporalAccessorUtil.get(temporalAccessor, ChronoField.MONTH_OF_YEAR), TemporalAccessorUtil.get(temporalAccessor, ChronoField.DAY_OF_MONTH), TemporalAccessorUtil.get(temporalAccessor, ChronoField.HOUR_OF_DAY), TemporalAccessorUtil.get(temporalAccessor, ChronoField.MINUTE_OF_HOUR), TemporalAccessorUtil.get(temporalAccessor, ChronoField.SECOND_OF_MINUTE), TemporalAccessorUtil.get(temporalAccessor, ChronoField.NANO_OF_SECOND) ); }
Because the implementation classes of TemporalAccessor time are commonly used as follows (provided by java8):
- LocalDateTime
- LocalDate
- LocalTime
Good habit. First judge whether the parameter temporalAccessor is empty
Then judge whether the temporalAccessor is a localDate object. If so, call LocalDate.atStartOfDay(), and the return value is localDate + '00:00'
//LocalDate public LocalDateTime atStartOfDay() { return LocalDateTime.of(this, LocalTime.MIDNIGHT); }
/** * The time of midnight at the start of the day, '00:00'. */ public static final LocalTime MIDNIGHT;
public static LocalDateTime of(LocalDate date, LocalTime time) { Objects.requireNonNull(date, "date"); Objects.requireNonNull(time, "time"); return new LocalDateTime(date, time); }
Finally, get the value of the LocalDateTime object through the LocalDateTime.of method.
However, the blogger found a problem. There is no month, year and day in LocalTime. How to convert it into LocalDateTime? Let's write a demo to see the effect
LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTimeUtil.of(localTime); System.out.println(localDateTime);
Why didn't you report an error
return LocalDateTime.of( TemporalAccessorUtil.get(temporalAccessor, ChronoField.YEAR), TemporalAccessorUtil.get(temporalAccessor, ChronoField.MONTH_OF_YEAR), TemporalAccessorUtil.get(temporalAccessor, ChronoField.DAY_OF_MONTH), TemporalAccessorUtil.get(temporalAccessor, ChronoField.HOUR_OF_DAY), TemporalAccessorUtil.get(temporalAccessor, ChronoField.MINUTE_OF_HOUR), TemporalAccessorUtil.get(temporalAccessor, ChronoField.SECOND_OF_MINUTE), TemporalAccessorUtil.get(temporalAccessor, ChronoField.NANO_OF_SECOND) );
Here are also the methods encapsulated by hutool. They all call * * public static int get (temporalaccessor, temporalaccessor, temporalfield) * * the source code is as follows
public static int get(TemporalAccessor temporalAccessor, TemporalField field) { if (temporalAccessor.isSupported(field)) { return temporalAccessor.get(field); } return (int)field.range().getMinimum(); }
This code is easy to understand. It is to take the property value corresponding to the temporalAccessor object. If it does not exist, take the minimum value of this property value.
To see the effect:
1. localtime does not have the year attribute
2. Take the minimum value of this field.
Other fields are obtained in the same way.
Method details - ofdate (Java. Time. Temporary. Temporalaccessor)
Method name: cn.hutool.core.date.localdatetimeutil.ofdate (Java. Time. Temporary. Temporalaccessor)
Method description
{@ link TemporalAccessor} to {@ link LocalDate}, using the default time zone
Supported version and above
5.3.10
Parameter Description:
Parameter name | describe |
---|---|
TemporalAccessor temporalAccessor |
temporalAccessor {@link TemporalAccessor}
|
Return value:
{@link LocalDate}
Reference case:
String dateStr = "2021-05-22T10:23:56"; //Use default time zone TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE_TIME.parse(dateStr); LocalDate localDate = LocalDateTimeUtil.ofDate(temporalAccessor); Assert.assertEquals("2021-05-22", localDate.toString());
Source code analysis:
public static LocalDate ofDate(TemporalAccessor temporalAccessor) { if (null == temporalAccessor) { return null; } if(temporalAccessor instanceof LocalDateTime){ return ((LocalDateTime)temporalAccessor).toLocalDate(); } return LocalDate.of( TemporalAccessorUtil.get(temporalAccessor, ChronoField.YEAR), TemporalAccessorUtil.get(temporalAccessor, ChronoField.MONTH_OF_YEAR), TemporalAccessorUtil.get(temporalAccessor, ChronoField.DAY_OF_MONTH) ); }
Because the implementation classes of TemporalAccessor time are commonly used as follows (provided by java8):
- LocalDateTime
- LocalDate
- LocalTime
Good habit. First judge whether the parameter temporalAccessor is empty
Then judge whether the temporalAccessor is a LocalDateTime object. If so, call LocalDateTime.toLocalDate(), and the return value is localDate, because LocalDateTime=localDate+LocalTime
Finally, get the value of the LocalDate object through the LocalDate.of method.
Method details - parse(java.lang.CharSequence)
Method name: cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence)
Method description
The parsed date time string is {@ link LocalDateTime}. Only yyyy MM DD'T 'HH:mm:ss format is supported, for example: 2007-12-03T10:15:30
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
CharSequence text |
Textdate time string
|
Return value:
{@link LocalDateTime}
Reference case:
final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56"); Assert.assertEquals("2020-01-23T12:23:56", localDateTime.toString());
Source code analysis:
/** * The parsed date time string is {@ link LocalDateTime}. Only yyyy MM DD't'hh: mm: SS format is supported, for example: 2007-12-03T10:15:30 * * @param text Date time string * @return {@link LocalDateTime} */ public static LocalDateTime parse(CharSequence text) { return parse(text, (DateTimeFormatter)null); }
Please see the source code analysis below.
Method details - parse(java.lang.CharSequence, java.time.format.DateTimeFormatter)
Method name: cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence, java.time.format.DateTimeFormatter)
Method description
The parsed date time string is {@ link LocalDateTime}. The format supports date time, date and time
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
CharSequence text |
Textdate time string when the formatter is null, the string should conform to the format 2020-01-23T12:23:56
|
DateTimeFormatter formatter |
Formatter date formatter. See {@ link DateTimeFormatter} for the predefined format
|
Return value:
{@link LocalDateTime}
Reference case:
final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56", DateTimeFormatter.ISO_DATE_TIME); Assert.assertEquals("2020-01-23T12:23:56", localDateTime.toString()); System.out.println(localDateTime);
Source code analysis:
public static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter) { if (null == text) { return null; } if (null == formatter) { return LocalDateTime.parse(text); } return of(formatter.parse(text)); }
If some students are unfamiliar with CharSequence object, they should not be unfamiliar with String, which is the implementation interface of CharSequence
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { ... }
DateTimeFormatter is a date and time formatter provided by jdk8 to replace our old friend simpledateformat.
Good habit. First judge whether the parameter CharSequence is empty
Then judge whether the parameter DateTimeFormatter is empty. If it is empty, call LocalDateTime.parse(text) directly
Let's look at the source code
public static LocalDateTime parse(CharSequence text) { return parse(text, DateTimeFormatter.ISO_LOCAL_DATE_TIME); }
The date format string used here should be in this format:
such as '2011-12-03T10:15:30'
What happens if the passed CharSequence parameter is not a string in this format
//According to format 2020-01-23T12:23:56 LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56", DateTimeFormatter.ISO_DATE_TIME); Assert.assertEquals("2020-01-23T12:23:56", localDateTime.toString()); System.out.println(localDateTime); //Unformatted DateTimeFormatter dateTimeFormatter = null; localDateTime = LocalDateTimeUtil.parse("2020-01-23", dateTimeFormatter); System.out.println(localDateTime);
The result of the implementation is expected, and the error is reported directly. This is a pit. Everyone should pay attention to it
java.time.format.DateTimeParseException: Text '2020-01-23' could not be parsed at index 10
Finally, call of(formatter.parse(text)).
formatter.parse(text) returns TemporalAccessor, not necessarily the LocalDateTime we want, so we need to turn it through of again
formatter.parse(text) is a native JDK8 method.
Method details - parse(java.lang.CharSequence, java.lang.String)
Method name: cn.hutool.core.date.LocalDateTimeUtil.parse(java.lang.CharSequence, java.lang.String)
Method description
Resolve the date time string to {@ link LocalDateTime}
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
CharSequence text |
Textdate time string
|
String format |
Format date format, similar to yyyy MM DD HH: mm: SS, SSS
|
Return value:
{@link LocalDateTime}
Reference case:
final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23", DatePattern.NORM_DATE_PATTERN); Assert.assertEquals("2020-01-23T00:00", localDateTime.toString());
Source code analysis:
public static LocalDateTime parse(CharSequence text, String format) { if (null == text) { return null; } DateTimeFormatter formatter = null; if(StrUtil.isNotBlank(format)){ // Fix the problem that yyyyMMddHHmmssSSS format cannot be resolved // fix issue#1082 //see https://stackoverflow.com/questions/22588051/is-java-time-failing-to-parse-fraction-of-second // jdk8 bug at: https://bugs.openjdk.java.net/browse/JDK-8031085 if(StrUtil.startWithIgnoreEquals(format, DatePattern.PURE_DATETIME_PATTERN)){ final String fraction = StrUtil.removePrefix(format, DatePattern.PURE_DATETIME_PATTERN); if(ReUtil.isMatch("[S]{1,2}", fraction)){ //Replace the dates of yyyyMMddHHmmssS and yyyyMMddHHmmssS with yyyyMMddHHmmssS format, and supplement with 0 text += StrUtil.repeat('0', 3-fraction.length()); } formatter = new DateTimeFormatterBuilder() .appendPattern(DatePattern.PURE_DATETIME_PATTERN) .appendValue(ChronoField.MILLI_OF_SECOND, 3) .toFormatter(); } else{ formatter = DateTimeFormatter.ofPattern(format); } } return parse(text, formatter); }
Form a good habit. First judge whether the parameters CharSequence and format are empty
Here, a bug in jdk8 is handled compatibly
1. In normal configuration, string dates in standard format can be converted normally. If the month, day, hour, minute and second are less than two digits, you need to fill in 0. Otherwise, the conversion will fail and an exception will be thrown.
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); LocalDateTime dt1 = LocalDateTime.parse("2021-7-20 23:46:43.946", DATE_TIME_FORMATTER); System.out.println(dt1);
Error will be reported:
java.time.format.DateTimeParseException: Text '2021-7-20 23:46:43.946' could not be parsed at index 5
Analysis reason: the format string does not match the actual time
"yyyy-MM-dd HH:mm:ss.SSS"
"2021-7-20 23:46:43.946"
The middle month format is MM, and the actual time is 7
Solution: keep the format string matching the actual time
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); LocalDateTime dt1 = LocalDateTime.parse("2021-07-20 23:46:43.946", DATE_TIME_FORMATTER); System.out.println(dt1);
Method details - parseDate(java.lang.CharSequence)
Method name: cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence)
Method description
The parsed date and time string is {@ link LocalDate}. Only yyyy MM DD'T 'HH:mm:ss format is supported, for example: 2007-12-03T10:15:30
Supported version and above
5.3.10
Parameter Description:
Parameter name | describe |
---|---|
CharSequence text |
Textdate time string
|
Return value:
{@link LocalDate}
Reference case:
LocalDate localDate = LocalDateTimeUtil.parseDate("2020-01-23"); Assert.assertEquals("2020-01-23", localDate.toString());
Source code analysis:
/** * The parsed date and time string is {@ link LocalDate}. Only yyyy mm dd't'hh: mm: SS format is supported, for example: 2007-12-03T10:15:30 * * @param text Date time string * @return {@link LocalDate} * @since 5.3.10 */ public static LocalDate parseDate(CharSequence text) { return parseDate(text, (DateTimeFormatter)null); }
Please see the source code analysis below.
Method details - parseDate(java.lang.CharSequence, java.time.format.DateTimeFormatter)
Method name: cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence, java.time.format.DateTimeFormatter)
Method description
The parsed date time string is {@ link LocalDate}, and the format supports date
Supported version and above
5.3.10
Parameter Description:
Parameter name | describe |
---|---|
CharSequence text |
Textdate time string
|
DateTimeFormatter formatter |
Formatter date formatter. See {@ link DateTimeFormatter} for the predefined format
|
Return value:
{@link LocalDate}
Reference case:
final LocalDateTime localDateTime = LocalDateTimeUtil.parse("12:23:56", DatePattern.NORM_TIME_PATTERN); Assert.assertEquals("12:23:56", localDateTime.toLocalTime().toString());
Source code analysis:
public static LocalDate parseDate(CharSequence text, DateTimeFormatter formatter) { if (null == text) { return null; } if (null == formatter) { return LocalDate.parse(text); } return ofDate(formatter.parse(text)); }
If some students are unfamiliar with CharSequence object, they should not be unfamiliar with String, which is the implementation interface of CharSequence
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { ... }
DateTimeFormatter is a date and time formatter provided by jdk8 to replace our old friend simpledateformat.
Good habit. First judge whether the parameter CharSequence is empty
Then judge whether the parameter DateTimeFormatter is empty. If it is empty, call LocalDate.parse(text) directly
Let's look at the source code
public static LocalDate parse(CharSequence text) { return parse(text, DateTimeFormatter.ISO_LOCAL_DATE); }
The date format string used here should be in this format:
such as '2011-12-03'
Finally, call of(formatter.parse(text)).
formatter.parse(text) returns TemporalAccessor, not necessarily the LocalDate we want, so we need to turn it through of again
formatter.parse(text) is a native JDK8 method.
Method details - parseDate(java.lang.CharSequence, java.lang.String)
Method name: cn.hutool.core.date.LocalDateTimeUtil.parseDate(java.lang.CharSequence, java.lang.String)
Method description
Parse date string as {@ link LocalDate}
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
CharSequence text |
Textdate string
|
String format |
Format date format, similar to yyyy MM DD
|
Return value:
{@link LocalDateTime}
Reference case:
//The format of the first parameter is consistent with that of the second parameter LocalDate localDate = LocalDateTimeUtil.parseDate("2020-01-23 12:23:56","yyyy-MM-dd hh:mm:ss"); Assert.assertEquals("2020-01-23", localDate.toString()); localDate = LocalDateTimeUtil.parseDate("2020/01/23 12:23:56","yyyy/MM/dd hh:mm:ss"); Assert.assertEquals("2020-01-23", localDate.toString());
Source code analysis:
public static LocalDate parseDate(CharSequence text, String format) { if (null == text) { return null; } return parseDate(text, DateTimeFormatter.ofPattern(format)); }
Please see the source code analysis above.
Method details - formatNormal(java.time.LocalDateTime)
Method name: cn.hutool.core.date.LocalDateTimeUtil.formatNormal(java.time.LocalDateTime)
Method description
Format the date and time in yyyy MM DD HH: mm: SS format
Supported version and above
5.3.11
Parameter Description:
Parameter name | describe |
---|---|
LocalDateTime time |
time {@link LocalDateTime}
|
Return value:
Formatted string
Reference case:
final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56"); String format = LocalDateTimeUtil.formatNormal(localDateTime); Assert.assertEquals("2020-01-23 12:23:56", format);
Source code analysis:
/** * Format the date and time in yyyy MM DD HH: mm: SS format * * @param time {@link LocalDateTime} * @return Formatted string * @since 5.3.11 */ public static String formatNormal(LocalDateTime time) { return format(time, DatePattern.NORM_DATETIME_FORMATTER); } //------------------------------ public static String format(LocalDateTime time, DateTimeFormatter formatter) { return TemporalAccessorUtil.format(time, formatter); }
TemporalAccessorUtil class is a tool class encapsulated by hutool. It is easy to understand from the following source code.
//TemporalAccessorUtil /** * Format the date and time in the specified format * * @param time {@link TemporalAccessor} * @param formatter Date formatter. For the predefined format, see: {@ link DateTimeFormatter} * @return Formatted string * @since 5.3.10 */ public static String format(TemporalAccessor time, DateTimeFormatter formatter) { if (null == time) { return null; } if(null == formatter){ formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; } try { return formatter.format(time); } catch (UnsupportedTemporalTypeException e){ if(time instanceof LocalDate && e.getMessage().contains("HourOfDay")){ // The user passed in LocalDate, but it is required to format the part with time. Convert it to LocalDateTime and try again return formatter.format(((LocalDate) time).atStartOfDay()); }else if(time instanceof LocalTime && e.getMessage().contains("YearOfEra")){ // The user passed in LocalTime, but it is required to format the part with date. Convert it to LocalDateTime and try again return formatter.format(((LocalTime) time).atDate(LocalDate.now())); } throw e; } }
Form a good habit. First judge whether the parameters TemporalAccessor and DateTimeFormatter are empty
If DateTimeFormatter is empty, the default value is DateTimeFormatter.ISO_LOCAL_DATE_TIME
such as '2011-12-03T10:15:30'
Then call the formatting method formatter.format(time). If time is not a LocalDateTime object, it will report errors, then do compatibility processing in catch, LocalDate and LocalTime objects can be formatted, and others will return to the exception directly.
Method details - format(java.time.LocalDateTime, java.time.format.DateTimeFormatter)
Method name: cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDateTime, java.time.format.DateTimeFormatter)
Method description
Format the date and time in the specified format
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
LocalDateTime time |
time {@link LocalDateTime}
|
DateTimeFormatter formatter |
Formatter date formatter. See {@ link DateTimeFormatter} for the predefined format
|
Return value:
Formatted string
Reference case:
LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56"); String format = LocalDateTimeUtil.format(localDateTime, DateTimeFormatter.ISO_DATE_TIME); Assert.assertEquals("2020-01-23T12:23:56", format);
Source code analysis:
/** * Format the date and time in the specified format * * @param time {@link LocalDateTime} * @param formatter Date formatter. For the predefined format, see: {@ link DateTimeFormatter} * @return Formatted string */ public static String format(LocalDateTime time, DateTimeFormatter formatter) { return TemporalAccessorUtil.format(time, formatter); }
Please see the source code analysis above.
Method details - format(java.time.LocalDateTime, java.lang.String)
Method name: cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDateTime, java.lang.String)
Method description
Format the date and time in the specified format
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
LocalDateTime time |
time {@link LocalDateTime}
|
String format |
Format date format, similar to yyyy MM DD HH: mm: SS, SSS
|
Return value:
Formatted string
Reference case:
final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56"); String format = LocalDateTimeUtil.format(localDateTime, DatePattern.NORM_DATETIME_PATTERN); Assert.assertEquals("2020-01-23 12:23:56", format);
Source code analysis:
public static String format(LocalDateTime time, String format) { if (null == time) { return null; } return format(time, DateTimeFormatter.ofPattern(format)); }
DateTimeFormatter.ofPattern(format) will return DateTimeFormatter after execution
The format(time, DateTimeFormatter method is then called
Please see the source code analysis above.
Method details - formatNormal(java.time.LocalDate)
Method name: cn.hutool.core.date.LocalDateTimeUtil.formatNormal(java.time.LocalDate)
Method description
Format the date and time in yyyy MM DD format
Supported version and above
5.3.11
Parameter Description:
Parameter name | describe |
---|---|
LocalDate date |
date {@link LocalDate}
|
Return value:
Formatted string
Reference case:
final LocalDate date = LocalDate.parse("2020-01-23"); String format = LocalDateTimeUtil.format(date, DatePattern.NORM_DATE_PATTERN); Assert.assertEquals("2020-01-23", format); format = LocalDateTimeUtil.formatNormal(date); Assert.assertEquals("2020-01-23", format);
Source code analysis:
public static String formatNormal(LocalDate date) { return format(date, DatePattern.NORM_DATE_FORMATTER); }
Please see the source code analysis above.
Method details - format(java.time.LocalDate, java.time.format.DateTimeFormatter)
Method name: cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDate, java.time.format.DateTimeFormatter)
Method description
Format the date and time in the specified format
Supported version and above
5.3.10
Parameter Description:
Parameter name | describe |
---|---|
LocalDate date |
date {@link LocalDate}
|
DateTimeFormatter formatter |
Formatter date formatter. See {@ link DateTimeFormatter} for the predefined format
|
Return value:
Formatted string
Reference case:
final LocalDate date = LocalDate.parse("2021-05-22"); String format = LocalDateTimeUtil.format(date, DateTimeFormatter.ISO_DATE); Assert.assertEquals("2021-05-22", format);
Source code analysis:
public static String format(LocalDate date, DateTimeFormatter formatter) { return TemporalAccessorUtil.format(date, formatter); }
Please see the source code analysis above.
Method details - format(java.time.LocalDate, java.lang.String)
Method name: cn.hutool.core.date.LocalDateTimeUtil.format(java.time.LocalDate, java.lang.String)
Method description
Format the date and time in the specified format
Supported version and above
5.3.10
Parameter Description:
Parameter name | describe |
---|---|
LocalDate date |
date {@link LocalDate}
|
String format |
Format date format, similar to yyyy MM DD
|
Return value:
Formatted string
Reference case:
final LocalDate date = LocalDate.parse("2020-01-23"); String format = LocalDateTimeUtil.format(date, DatePattern.NORM_DATE_PATTERN); Assert.assertEquals("2020-01-23", format);
Source code analysis:
public static String format(LocalDate date, String format) { if (null == date) { return null; } return format(date, DateTimeFormatter.ofPattern(format)); }
Please see the source code analysis above.
Method details - offset (Java. Time. Localdatetime, long, Java. Time. Temporary. Temporalunit)
Method name: cn.hutool.core.date.localdatetimeutil.offset (java.time.localdatetime, long, java.time.temporary.temporalunit)
Method description
Date offset: add different values according to different field s (offset will modify the incoming objects)
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
LocalDateTime time |
time {@link LocalDateTime}
|
long number |
Number offset, a positive number is a backward offset, and a negative number is a forward offset
|
TemporalUnit field |
field offset unit, see {@ link chrononunit}, cannot be null
|
Return value:
Date and time after offset
Reference case:
final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56"); LocalDateTime offset = LocalDateTimeUtil.offset(localDateTime, 1, ChronoUnit.DAYS); // Not the same object Assert.assertNotSame(localDateTime, offset); Assert.assertEquals("2020-01-24T12:23:56", offset.toString());
Source code analysis:
/** * Date offset: add different values according to different field s (offset will modify the incoming objects) * * @param time {@link LocalDateTime} * @param number Offset. Positive numbers are backward offsets and negative numbers are forward offsets * @param field Offset unit, see {@ link chrononunit}, cannot be null * @return Date and time after offset */ public static LocalDateTime offset(LocalDateTime time, long number, TemporalUnit field) { if (null == time) { return null; } return time.plus(number, field); }
time.plus(number, field) is the method provided by jdk8
LocalDateTime localDateTime = LocalDateTime.of(2021, 8, 30, 23, 14, 20); LocalDateTime offset = localDateTime.plus(1, ChronoUnit.DAYS); // Not the same object Assert.assertNotSame(localDateTime, offset); System.out.println(offset);
Method details - between(java.time.LocalDateTime, java.time.LocalDateTime)
Method name: cn.hutool.core.date.LocalDateTimeUtil.between(java.time.LocalDateTime, java.time.LocalDateTime)
Method description
Gets the difference between two dates. If the end time is earlier than the start time, the result is negative.
The returned result is the {@ link Duration} object. The phase difference unit ### supported version and above is returned by calling the toXXX method
Parameter Description:
Parameter name | describe |
---|---|
LocalDateTime startTimeInclude |
startTimeInclude start time (inclusive)
|
LocalDateTime endTimeExclude |
endTimeExclude end time (not included)
|
Return value:
Time difference {@ link Duration} object
Reference case:
final Duration between = LocalDateTimeUtil.between( LocalDateTimeUtil.parse("2019-02-02T00:00:00"), LocalDateTimeUtil.parse("2020-02-02T00:00:00")); Assert.assertEquals(365, between.toDays());
Source code analysis:
public static Duration between(LocalDateTime startTimeInclude, LocalDateTime endTimeExclude) { return TemporalUtil.between(startTimeInclude, endTimeExclude); }
TemporalUtil is a tool class encapsulated by hutool. The source code is as follows:
/** * Gets the difference between two dates. If the end time is earlier than the start time, the result is negative. * <p> * The returned result is the {@ link Duration} object, and the phase difference unit is returned by calling the toXXX method * * @param startTimeInclude Start time (inclusive) * @param endTimeExclude End time (not included) * @return Time difference {@ link Duration} object */ public static Duration between(Temporal startTimeInclude, Temporal endTimeExclude) { return Duration.between(startTimeInclude, endTimeExclude); }
Duration is suitable for shorter processing time and requires higher accuracy. We can use the between() method to compare the difference between two moments.
Duration.between is a method provided by JDK8.
Method details - between (Java. Time. Localdatetime, Java. Time. Localdatetime, Java. Time. Temporary. Chrononunit)
Method name: cn.hutool.core.date.localdatetimeutil.between (java.time.localdatetime, java.time.localdatetime, Java. Time. Temporary. Chrononunit)
Method description
Gets the difference between two dates. If the end time is earlier than the start time, the result is negative.
The return result is a long value of time difference
Supported version and above
5.4.5
Parameter Description:
Parameter name | describe |
---|---|
LocalDateTime startTimeInclude |
startTimeInclude start time (inclusive)
|
LocalDateTime endTimeExclude |
endTimeExclude end time (excluding)
|
ChronoUnit unit |
Unit time difference unit
|
Return value:
time difference
Reference case:
final long betweenWeek = DateUtil.betweenWeek( DateUtil.parse("2020-11-21"), DateUtil.parse("2020-11-23"), false); final long betweenWeek2 = LocalDateTimeUtil.between( LocalDateTimeUtil.parse("2020-11-21", "yyy-MM-dd"), LocalDateTimeUtil.parse("2020-11-23", "yyy-MM-dd"), ChronoUnit.WEEKS); Assert.assertEquals(betweenWeek, betweenWeek2);
Source code analysis:
public static long between(LocalDateTime startTimeInclude, LocalDateTime endTimeExclude, ChronoUnit unit) { return TemporalUtil.between(startTimeInclude, endTimeExclude, unit); }
One more time unit option
public static long between(Temporal startTimeInclude, Temporal endTimeExclude, ChronoUnit unit) { return unit.between(startTimeInclude, endTimeExclude); }
The returned data is 0
The returned data is 1
The data of these two demo s reflect that the results are generated in units of time difference.
Method details - betweenPeriod(java.time.LocalDate, java.time.LocalDate)
Method name: cn.hutool.core.date.LocalDateTimeUtil.betweenPeriod(java.time.LocalDate, java.time.LocalDate)
Method description
Get the apparent time difference between two dates. If the end time is earlier than the start time, the result is negative.
For example, February 1, 2011 and August 11, 2021 differ by 10 days and 6 months respectively
Supported version and above
5.4.5
Parameter Description:
Parameter name | describe |
---|---|
LocalDate startTimeInclude |
startTimeInclude start time (inclusive)
|
LocalDate endTimeExclude |
endTimeExclude end time (excluding)
|
Return value:
time difference
Reference case:
final LocalDate localDate1= LocalDate.parse("2021-05-22"); final LocalDate localDate2= LocalDate.parse("2021-06-23"); Period period = LocalDateTimeUtil.betweenPeriod(localDate1,localDate2); Assert.assertEquals(1, period.getMonths()); Assert.assertEquals(1, period.getDays()); period = LocalDateTimeUtil.betweenPeriod(localDate2,localDate1); Assert.assertEquals(-1, period.getMonths()); Assert.assertEquals(-1, period.getDays()); final LocalDate localDate3= LocalDate.parse("2021-06-22"); period = LocalDateTimeUtil.betweenPeriod(localDate1,localDate3); Assert.assertEquals(1, period.getMonths()); Assert.assertEquals(0, period.getDays());
Source code analysis:
public static Period betweenPeriod(LocalDate startTimeInclude, LocalDate endTimeExclude) { return Period.between(startTimeInclude, endTimeExclude); }
Period.between is the method provided by JDK8
Period is the implementation class of ChronoPeriod. The class contains two variables: years, months and days. Therefore, period is a time quantity composed of year, month and day.
LocalDate first = LocalDate.of(2021, 8, 29); LocalDate second = LocalDate.of(2022, 9, 30); Period period = Period.between(first, second); System.out.println(period);
Method details - beginOfDay(java.time.LocalDateTime)
Method name: cn.hutool.core.date.LocalDateTimeUtil.beginOfDay(java.time.LocalDateTime)
Method description
Modify to the start time of the day, for example: 2020-02-02 00:00:00000
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
LocalDateTime time |
Time date time
|
Return value:
Start time of the day
Reference case:
final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56"); final LocalDateTime beginOfDay = LocalDateTimeUtil.beginOfDay(localDateTime); Assert.assertEquals("2020-01-23T00:00", beginOfDay.toString());
Source code analysis:
/** * Modify to the start time of the day, for example: 2020-02-02 00:00:00000 * * @param time Date time * @return Start time of the day */ public static LocalDateTime beginOfDay(LocalDateTime time) { return time.with(LocalTime.MIN); }
LocalDateTime.with is the method provided by jdk8.
Addition, subtraction and modification of date and time
LocalDateTime currentTime = LocalDateTime.now(); // Current date and time System.out.println("------------------Addition and subtraction of time and its modification-----------------------"); //3. The addition and subtraction method of localdatetime includes all additions and subtractions of LocalDate and LocalTime. As mentioned above, only a brief introduction is given here System.out.println("3.Current time:" + currentTime); System.out.println("3.Current time plus 5 years:" + currentTime.plusYears(5)); System.out.println("3.Current time plus 2 months:" + currentTime.plusMonths(2)); System.out.println("3.Current time minus 2 days:" + currentTime.minusDays(2)); System.out.println("3.Current time minus 5 hours:" + currentTime.minusHours(5)); System.out.println("3.Current time plus 5 minutes:" + currentTime.plusMinutes(5)); System.out.println("3.Current time plus 20 seconds:" + currentTime.plusSeconds(20)); //It can also be used flexibly, such as adding one year back, subtracting one day forward, adding two hours back and subtracting five minutes forward System.out.println("3.Simultaneous modification(Add one year backward, one day forward, two hours backward and five minutes forward): " + currentTime.plusYears(1).minusDays(1).plusHours(2).minusMinutes(5)); System.out.println("3.The revised year is 2025:" + currentTime.withYear(2025)); System.out.println("3.Revised to December:" + currentTime.withMonth(12)); System.out.println("3.The revision date is 27th:" + currentTime.withDayOfMonth(27)); System.out.println("3.Modify the hour to 12:" + currentTime.withHour(12)); System.out.println("3.Modify the minutes to 12:" + currentTime.withMinute(12)); System.out.println("3.Modify the second to 12:" + currentTime.withSecond(12));
Method details - endOfDay(java.time.LocalDateTime)
Method name: cn.hutool.core.date.LocalDateTimeUtil.endOfDay(java.time.LocalDateTime)
Method description
Modify to the end time of the day, for example: 2020-02-02 23:59:59999
Supported version and above
Parameter Description:
Parameter name | describe |
---|---|
LocalDateTime time |
Time date time
|
Return value:
End of day
Reference case:
final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56"); final LocalDateTime endOfDay = LocalDateTimeUtil.endOfDay(localDateTime); Assert.assertEquals("2020-01-23T23:59:59.999999999", endOfDay.toString());
Source code analysis:
/** * Modify to the end time of the day, for example: 2020-02-02 23:59:59999 * * @param time Date time * @return End of day */ public static LocalDateTime endOfDay(LocalDateTime time) { return time.with(LocalTime.MAX); }
Please see the source code analysis above.
Method details - toepochmili (Java. Time. Temporary. Temporalaccessor)
Method name: cn.hutool.core.date.localdatetimeutil.toepochmili (Java. Time. Temporary. Temporalaccessor)
Method description
{@ link TemporalAccessor} converted to timestamp (number of milliseconds from 1970-01-01T00:00:00Z)
Supported version and above
5.4.1
Parameter Description:
Parameter name | describe |
---|---|
TemporalAccessor temporalAccessor |
temporalAccessor Date object
|
Return value:
{@ link Instant} object
Reference case:
String dateStr = "2021-05-22"; //The implementation class of TemporalAccessor contains Instant LocalDateTime ZonedDateTime OffsetDateTime LocalDate LocalTime OffsetTime LocalDate localDate = LocalDate.parse(dateStr); //Date object long time = LocalDateTimeUtil.toEpochMilli(localDate); Assert.assertEquals(DateUtil.parse(dateStr).getTime(), time);
Source code analysis:
public static long toEpochMilli(TemporalAccessor temporalAccessor) { return TemporalAccessorUtil.toEpochMilli(temporalAccessor); }
Temporalaccessorutil. Toepochmili (temporary accessor) is a method encapsulated by hutool.
public static long toEpochMilli(TemporalAccessor temporalAccessor) { return toInstant(temporalAccessor).toEpochMilli(); }
Convert the temporalAccessor object into an Instant object. Let's see how it is converted
public static Instant toInstant(TemporalAccessor temporalAccessor) { if (null == temporalAccessor) { return null; } Instant result; if (temporalAccessor instanceof Instant) { result = (Instant) temporalAccessor; } else if (temporalAccessor instanceof LocalDateTime) { result = ((LocalDateTime) temporalAccessor).atZone(ZoneId.systemDefault()).toInstant(); } else if (temporalAccessor instanceof ZonedDateTime) { result = ((ZonedDateTime) temporalAccessor).toInstant(); } else if (temporalAccessor instanceof OffsetDateTime) { result = ((OffsetDateTime) temporalAccessor).toInstant(); } else if (temporalAccessor instanceof LocalDate) { result = ((LocalDate) temporalAccessor).atStartOfDay(ZoneId.systemDefault()).toInstant(); } else if (temporalAccessor instanceof LocalTime) { // The specified local time is converted to Instant, and the date of the current day is taken result = ((LocalTime) temporalAccessor).atDate(LocalDate.now()).atZone(ZoneId.systemDefault()).toInstant(); } else if (temporalAccessor instanceof OffsetTime) { // The specified local time is converted to Instant, and the date of the current day is taken result = ((OffsetTime) temporalAccessor).atDate(LocalDate.now()).toInstant(); } else { result = Instant.from(temporalAccessor); } return result; }
It is the corresponding temporalAccessor implementation class. From this source code, we can learn how to convert different time types into Instant objects.
Then convert the Instant object into millisecond long data
Instant now = Instant.now(); System.out.println("now:"+now); System.out.println(now.getEpochSecond()); // second System.out.println(now.toEpochMilli()); // millisecond
reference resources:
JSR
JCP official website: https://www.jcp.org/en/home/index
2020 Executive Committee (EC) elections: https://www.jcp.org/aboutJava/communityprocess/elections/2020.html
Nominees for 2020 Executive Committee Election: https://www.jcp.org/aboutJava/communityprocess/elections/2020-nominees.html
JSR-310: new date time API (I)
Time zone: https://baike.baidu.com/item/%E6%97%B6%E5%8C%BA/491122?fr=aladdin
UTC:https://baike.baidu.com/item/%E5%8D%8F%E8%B0%83%E4%B8%96%E7%95%8C%E6%97%B6/787659?fromtitle=UTC&fromid=5899996&fr=aladdin
GMT:https://baike.baidu.com/item/%E4%B8%96%E7%95%8C%E6%97%B6/692237?fromtitle=GMT&fromid=6026868&fr=aladdin
CST:https://baike.baidu.com/item/CST/14822063?fr=aladdin
DST:https://baike.baidu.com/item/%E5%A4%8F%E4%BB%A4%E6%97%B6/1809579?fromtitle=DST&fromid=1203186&fr=aladdin
ISO-8601:https://baike.baidu.com/item/ISO%208601/3910715?fr=aladdin
TZUpdater :https://www.oracle.com/java/technologies/javase/tzupdater-readme.html
IANA time zone data version: https://data.iana.org/time-zones/releases/
Time zone data version in JRE software: https://www.oracle.com/java/technologies/tzdata-versions.html
JSR-310: common calculation tools (IV)
duration: http://tutorials.jenkov.com/java-date-time/duration.html
ChronoUnit: https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/time/temporal/ChronoUnit.html
ValueRange:https://nowjava.com/docs/java-api-11/java.base/java/time/temporal/ValueRange.html#getMinimum()
Recommend relevant articles
JSR-310 series articles
hutool date time series
1dateutil (time tool class) - current time and current timestamp
3dateutil (time tool class) - get various contents of the date
4dateutil (time tool class) - format time
5dateutil (time tool class) - resolves the formatted time
6dateutil (time tool class) - time offset acquisition
7dateutil (time tool class) - date calculation
8chinesedate (lunar date tool)
9localdatetimeutil (encapsulated by {@ link LocalDateTime} tool class in jdk8 +)
10TemporalAccessorUtil{@link TemporalAccessor} tool class encapsulation
other
To explore the core underlying source code of JDK, you must master the usage of native
Wanzi blog teaches you to understand the date and time related usage of java source code
Source code analysis: risks and best practices for JDK to obtain the default time zone
Today is the 13th / 100th day of continuous writing.
You can pay attention to me, praise me, comment on me and collect me.