In addition to lambda expressions, streams and several minor improvements, Java 8 also introduced a new set of time and date APIs. In this tutorial, we will learn how to use Java 8 through a few simple task examples. Set of APIs. Java's processing of dates, calendars and time has always been criticized, especially its decision to define java.util.Date as modifiable and implement SimpleDateFormat as non-thread-safe. It seems Java has realized that it needs to provide better support for the time and date functionality, which is also a good thing for communities that are used to using the Joda time and date library. The biggest advantage of this new time and date library is that it clearly defines some concepts related to time and date, such as instant time (Instant), duration (duration), date (date), time (time), time zone (time-zone) and time period (period). It also draws on some of the advantages of the Joda library, such as distinguishing the understanding of time and date between humans and machines. Java 8 still uses ISO's calendar system, and unlike its predecessors, the classes in the java.time package are immutable and thread-safe. The new time and date API is located in the java.time package. Here are some key classes inside:
1.Instant-It represents a time stamp
2. LocalDate—Date that does not include the specific time, such as 2014-01-14. It can be used to store birthdays, anniversary, induction dates, and more.
3.LocalTime - It represents a time without dates
4.LocalDateTime-It contains date and time, but there is still no offset information or time zone.
5.ZonedDateTime - This is a complete date and time containing the time zone, and the offset is based on UTC/Greenwich time.
The new library also adds ZoneOffset and Zoned, which can provide better support for time zones. With the new DateTimeFormatter, the parsing and formatting of dates have also become new. Just mentioning this article, I wrote this article when Java was about to launch this new feature at this time last year, so you will find that the time in the examples is still from last year. If you run these examples, the values they return are definitely correct.
How does Java 8 handle time and date
Someone asked me what is the best way to learn a new library? My answer is, it is to use it in actual projects. There will be a variety of needs in a real project, which will prompt developers to explore and research this new library. In short, only the task itself will really encourage you to explore and learn. The same is true for the new date and time API of java 8. To learn this new library of Java 8, here I have created 20 task-oriented examples. Let's start with a simple task, such as how to use the Java 8 time and date library to represent today, and then further generate a complete date with time and time zone, and then study how to complete some more practical tasks, such as Develop a reminder application to find out how many days there are to be before certain dates such as birthdays, Sunday anniversary, next billing day, next premium day, or credit card expiration date.
Example 1 How to get the date of the day in Java 8
There is a class in Java 8 called LocalDate, which can be used to represent today's date. This class is slightly different from java.util.Date because it only contains dates and no time. So if you only need to represent the date without including the time, you can use it.
The code copy is as follows:
LocalDate today = LocalDate.now(); System.out.println("Today's Local date : " + today);
Output
Today's Local date : 2014-01-14
You can see that it creates today's date without time information. It also formats the date and then outputs it. Unlike the previous Date class, the printed data is unformatted.
Example 2 How to get the current year, month, day in Java 8
The LocalDate class provides some convenient methods to extract year, month, day and other date attributes. Using these methods, you can get any date attributes you need, without using classes like java.util.Calendar:
The code copy is as follows:
LocalDate today = LocalDate.now();
int year = today.getYear();
int month = today.getMonthValue();
int day = today.getDayOfMonth();
System.out.printf("Year : %d Month : %d day : %d /t %n", year, month, day);
Output
Today's Local date : 2014-01-14
Year : 2014 Month : 1 day : 14
As you can see, it is very simple to obtain year and month information in Java 8. Just use the corresponding getter method, without memory, and it is very intuitive. You can compare it with the old writing method of obtaining the current year, month and day in Java.
Example 3 How to get a specific date in Java 8
In the first example, we see that it is very simple to generate the date of the day through the static method now(), but through another very useful factory method LocalDate.of(), you can create any date, which accepts The parameter of year, month and day, and then returns an equivalent LocalDate instance. There is another good news about this method that it did not make any mistakes in the previous API. For example, the year can only start in 1900, the month must start at 0, etc. Whatever you write about the date here is, for example, in the example below, it represents January 14th, and there is no hidden logic.
The code copy is as follows:
LocalDate dateOfBirth = LocalDate.of(2010, 01, 14);
System.out.println("Your Date of birth is : " + dateOfBirth);
Output : Your Date of birth is : 2010-01-14
It can be seen that the date of creation is what we wrote, January 14, 2014.
Example 4 How to check if two dates are equal in Java 8
If you talk about the actual task of processing time and date in reality, one common thing is to check whether the two dates are equal. You may often encounter questions about whether today is a special day, such as birthday, anniversary, or holidays. Sometimes, you will be given a date to check if it is a certain day, for example, a holiday. The following example will help you complete this type of task in Java 8. As you might think, LocalDate overrides the equals method to compare dates as follows:
The code copy is as follows:
LocalDate date1 = LocalDate.of(2014, 01, 14); if(date1.equals(today)){
System.out.printf("Today %s and date1 %s are same date %n", today, date1);
}
Output
today 2014-01-14 and date1 2014-01-14 are same date
In this case, the two dates we compare are equal. At the same time, if you get a formatted date string in the code, you have to parse it into a date before you can compare it. You can compare this example with the way Java compares dates before, and you will find that it is so exciting.
Example 5 How to check for duplicate events in Java 8, say birthday
There is another practical task related to time and date in Java, which is to check duplicate events, such as monthly billing days, wedding anniversary, monthly repayment days, or the day when you pay insurance premiums every year. If you work in an e-commerce company, there will definitely be a module that will send birthday wishes to users and send greetings to them on every important holiday, such as Christmas, Thanksgiving, and in India, it may be It is the Deepawali Festival. How to determine whether it is a festival or a duplicate event in Java? Use the MonthDay class. This class is composed of month and day, and does not contain year information, which means you can use it to represent some days that appear repeatedly every year. Of course, there are some other combinations, such as the YearMonth class. It is also immutable and thread-safe like other classes in the new time and date library, and it is also a value class. Let's use an example to see how to use MonthDay to check a duplicate date:
The code copy is as follows:
LocalDate dateOfBirth = LocalDate.of(2010, 01, 14);
MonthDay birthday = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth());
MonthDay currentMonthDay = MonthDay.from(today);
if(currentMonthDay.equals(birthday)){
System.out.println("Many Many happy returns of the day !!");
}else{
System.out.println("Sorry, today is not your birthday");
}
Output: Many Many happy returns of the day !!
Although the years are different, today is the birthday, so you will see a birthday wish in the output. You can adjust the system time and run the program to see if it reminds you when your next birthday is. You can also try to write a JUnit unit test with your next birthday to see if the code can run correctly.
Example 6 How to get the current time in Java 8
This is very similar to getting the current date in the first example. This time we are using a class called LocalTime, which is a time without a date and is a close relative to LocalDate. Here you can also use the static factory method now() to get the current time. The default format is hh:mm:ss:nnn, where nnn is nanoseconds. You can compare it with how to get the current time in Java 8 before.
The code copy is as follows:
LocalTime time = LocalTime.now(); System.out.println("local time now : " + time);
Output
local time now : 16:33:33.369 // in hour, minutes, seconds, nano seconds
As you can see, the current time does not include dates, because LocalTime only has time and no dates.
Example 7 How to increase the number of hours in time
Many times we need to add hours, minutes or seconds to calculate the future time. Java 8 not only provides immutable and thread-safe classes, it also provides some more convenient methods such as plusHours() to replace the original add() method. By the way, these methods return a reference to a new LocalTime instance, because LocalTime is immutable, don't forget to store this new reference.
The code copy is as follows:
LocalTime time = LocalTime.now();
LocalTime newTime = time.plusHours(2); // adding two hours
System.out.println("Time after 2 hours : " + newTime);
Output:
Time after 2 hours : 18:33:33.369
You can see that the current time is 16:33:33.369 after 2 hours. Now you can compare it with the old way of adding or decreasing hours in Java. You can tell which method is better at first glance.
Example 8 How to get a date after 1 week
This is similar to the previous example of getting the time after 2 hours, here we will learn how to get the date after 1 week. LocalDate is used to represent dates without time. It has a plus() method that can be used to add day, week, or month, and ChronoUnit is used to represent this time unit. Since LocalDate is also immutable, any modification operation returns a new instance, so don't forget to save it.
The code copy is as follows:
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
System.out.println("Today is : " + today);
System.out.println("Date after 1 week : " + nextWeek);
Output:
Today is : 2014-01-14
Date after 1 week : 2014-01-21
You can see what the date will be in 7 days, that is, a week. You can use this method to add a month, year, hour, minute, or even ten years, and check out the ChronoUnit class in the Java API to get more options.
Example 9 Date around one year
This is a sequel to the previous example. In the above example, we learned how to use LocalDate's plus() method to add a date, week or month to a date. Now let's learn how to use the minus() method to find the day a year ago.
The code copy is as follows:
LocalDate previousYear = today.minus(1, ChronoUnit.YEARS);
System.out.println("Date before 1 year : " + previousYear);
LocalDate nextYear = today.plus(1, YEARS);
System.out.println("Date after 1 year : " + nextYear);
Output:
Date before 1 year : 2013-01-14
Date after 1 year : 2015-01-14
It can be seen that there are two years now, one in 2013, the other in 2015, and the years around 2014.
Example 10 Using Clock in Java 8
Java 8 comes with a Clock class, which you can use to get the current instant time, date or time in a certain time zone. Clock can be used instead of System.currentTimeInMillis() and TimeZone.getDefault() methods.
The code copy is as follows:
// Returns the current time based on your system clock and set to UTC.
Clock clock = Clock.systemUTC();
System.out.println("Clock : " + clock);
// Returns time based on system clock zone Clock defaultClock =
Clock.systemDefaultZone();
System.out.println("Clock : " + clock);
Output:
Clock : SystemClock[Z]
Clock : SystemClock[Z]
You can compare this clock with the specified date, such as:
The code copy is as follows:
public class MyClass {
private Clock clock; // dependency inject...
public void process(LocalDate eventDate) {
if(eventDate.isBefore(LocalDate.now(clock)) {
...
}
}
}
This is quite convenient if you need to process dates in different time zones.
Example 11 How to determine whether a date is before or after another date in Java
This is also a common task in actual projects. How do you tell whether a date is before or after another date, or exactly equal? In Java 8, the LocalDate class has an isBefore() and isAfter() method that can be used to compare two dates. If the date of calling the method is earlier than the given date, the isBefore() method will return true.
The code copy is as follows:
LocalDate tomorrow = LocalDate.of(2014, 1, 15); , if(tommorow.isAfter(today)){
System.out.println("Tomorrow comes after today");
}
LocalDate yesterday = today.minus(1, DAYS);
if(yesterday.isBefore(today)){
System.out.println("Yesterday is day before today");
}
Output:
Tomorrow comes after today
Yesterday is day before today
It can be seen that the date in Java 8 is quite simple. There is no need to use another class like Calendar to complete similar tasks.
Example 12 Handling different time zones in Java 8
Java 8 not only separates dates and times, but also has a time zone. There are now several sets of time zone-related classes. For example, ZonId represents a specific time zone, while ZonedDateTime represents time with time zone. It is equivalent to the GregorianCalendar class before Java 8. Using this class, you can convert the local time into the corresponding time in another time zone, such as the following example:
The code copy is as follows:
// Date and time with timezone in Java 8 ZoneId america = ZoneId.of("America/New_York");
LocalDateTime localtDateAndTime = LocalDateTime.now();
ZonedDateTime dateAndTimeInNewYork = ZonedDateTime.of(localtDateAndTime, america);
System.out.println("Current date and time in a particular timezone : " + dateAndTimeInNewYork);
Output:
Current date and time in a particular timezone : 2014-01-14T16:33:33.373-05:00[America/New_York]
You can compare it with the previous method of converting local time to GMT time. By the way, just like before Java 8, don't make the text corresponding to the time zone wrong, otherwise you will encounter such an exception:
The code copy is as follows:
Exception in thread "main" java.time.zone.ZoneRulesException: Unknown time-zone ID: ASIA/Tokyo
at java.time.zone.ZoneRulesProvider.getProvider(ZoneRulesProvider.java:272)
at java.time.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java:227)
at java.time.ZoneRegion.ofId(ZoneRegion.java:120)
at java.time.ZoneId.of(ZoneId.java:403)
at java.time.ZoneId.of(ZoneId.java:351)
Example 13 How to represent a fixed date, such as credit card expiration time
Just as MonthDay represents a recurring day, YearMonth is another combination, which represents dates such as credit card repayment date, fixed deposit maturity date, options maturity date. You can use this class to find out how many days there are in that month. The lengthOfMonth() method returns how many days there are in this YearMonth instance. This is very useful for checking whether February is 28 or 29 days.
The code copy is as follows:
YearMonth currentYearMonth = YearMonth.now(); System.out.printf("Days in month year %s: %d%n", currentYearMonth, currentYearMonth.lengthOfMonth());
YearMonth creditCardExpiry = YearMonth.of(2018, Month.FEBRUARY);
System.out.printf("Your credit card expires on %s %n", creditCardExpiry);
Output:
Days in month year 2014-01: 31
Your credit card expires on 2018-02
Example 14 How to check leap year in Java 8
This is not complicated. The LocalDate class has an isLeapYear() method that can return whether the year corresponding to the current LocalDate is a leap year. If you still want to recreate the wheel, you can look at this code. This is the logic of judging whether a year is a leap year written purely in Java.
The code copy is as follows:
if(today.isLeapYear()){
System.out.println("This year is Leap year");
}else {
System.out.println("2014 is not a Leap year");
}
Output: 2014 is not a Leap year
You can check for a few more years to see if the results are correct. It is best to write a unit test to test the normal year and leap year.
Example 15 How many days and months are included between two dates
Another common task is to calculate how many days, weeks, or years are included between two given dates. You can use the java.time.Period class to complete this function. In the following example, we will calculate how many months the current date is separated from a future date.
The code copy is as follows:
LocalDate java8Release = LocalDate.of(2014, Month.MARCH, 14);
Period periodToNextJavaRelease =
Period.between(today, java8Release);
System.out.println("Months left between today and Java 8 release : " + periodToNextJavaRelease.getMonths() );
Output:
Months left between today and Java 8 release : 2
As you can see, this month is January, and Java 8's release date is March, so there are 2 months between them.
Example 16 Date and time with time zone offset
In Java 8, you can use the ZoneOffset class to represent a certain time zone, such as India is GMT or UTC5:30, and you can use its static method ZoneOffset.of() method to get the corresponding time zone. As long as you get this offset, you can use LocalDateTime and this offset to create an OffsetDateTime.
The code copy is as follows:
LocalDateTime datetime = LocalDateTime.of(2014, Month.JANUARY, 14, 19, 30);
ZoneOffset offset = ZoneOffset.of("+05:30");
OffsetDateTime date = OffsetDateTime.of(datetime, offset);
System.out.println("Date and Time with timezone offset in Java : " + date);
Output:
Date and Time with timezone offset in Java : 2014-01-14T19:30+05:30
You can see that the current time and date are related to the time zone. Another point is that OffSetDateTime is mainly for machines to understand. If it is for people to see, you can use the ZoneDateTime class.
Example 17 How to get the current timestamp in Java 8
If you still remember how to get the current timestamp before Java 8, it's a piece of cake now. The Instant class has a static factory method now() that can return the current timestamp, as follows:
The code copy is as follows:
Instant timestamp = Instant.now();
System.out.println("What is value of this instant " + timestamp);
Output:
What is value of this instant 2014-01-14T08:33:33.379Z
It can be seen that the current timestamp contains date and time, which is very similar to java.util.Date. In fact, Instant is the Date before Java 8. You can use the methods in these two classes to use these two types. Convert between them, for example, Date.from(Instant) is used to convert Instant to java.util.Date, and Date.toInstant() converts Date to Instant.
Example 18 How to parse/format dates using a predefined formatter in Java 8
Before Java 8, time and date formatting was a technical job. Our good partner SimpleDateFormat is not thread-safe, and it seems a bit bulky if used as a local variable to format. Thanks to thread-local variables, this makes it workable in a multi-threaded environment, but Java has maintained this state for a long time. This time it introduces a brand new thread-safe date and time formatter. It also comes with some predefined formatters, including commonly used date formats. For example, in this example we use the predefined BASICISODATE format, which will format February 14, 2014 into 20140114.
The code copy is as follows:
String dayAfterTommorrow = "20140116";
LocalDate formatted = LocalDate.parse(dayAfterTommorrow,
DateTimeFormatter.BASIC_ISO_DATE);
System.out.printf("Date generated from String %s is %s %n", dayAfterTommorrow, formatted);
Output:
Date generated from String 20140116 is 2014-01-16
You can see that the generated date matches the value of the specified string, which means that the date format is slightly different.
Example 19 How to use a custom formatter to parse dates in Java
In the above example, we used the built-in time-date formatter to parse the date string. Of course, the predefined formatter is indeed good, but sometimes you may still need to use a custom date format. At this time, you have to create a custom date formatter instance yourself. The date format in the following example is "MMM dd yyyy". You can pass any pattern to the DateTimeFormatter's ofPattern static method(), which returns an instance, with the literal value of this pattern being the same as in the previous example. For example, M still represents the month, while m is still the segment. An invalid mode will throw a DateTimeParseException exception, but if it is a logical error, such as using m when it is time to use M, there is nothing to do.
The code copy is as follows:
String goodFriday = "Apr 18 2014";
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy");
LocalDate holiday = LocalDate.parse(goodFriday, formatter);
System.out.printf("Successfully parsed String %s, date is %s%n", goodFriday, holiday);
} catch (DateTimeParseException ex) {
System.out.printf("%s is not parsable!%n", goodFriday);
ex.printStackTrace();
}
Output:
Successfully parsed String Apr 18 2014, date is 2014-04-18
You can see that the value of the date does match the string passed in, but the format is different.
Example 20 How to format dates and convert them into strings in Java 8
In the previous two examples, although we used the DateTimeFormatter class, we mainly parse the date string. In this example, we are going to do the opposite. Here we have an instance of LocalDateTime class, which we want to convert into a formatted date string. This is by far the easiest and most convenient way to convert dates into strings in Java. The following example will return a formatted string. The same as the previous example is that we still need to use the specified pattern string to create an instance of the DateTimeFormatter class, but the call is not the parse method of the LocalDate class, but its format() method. This method will return a string representing the current date, and the corresponding pattern is defined in the incoming DateTimeFormatter instance.
The code copy is as follows:
LocalDateTime arrivalDate = LocalDateTime.now();
try {
DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy hh:mm a");
String landing = arrivalDate.format(format);
System.out.printf("Arriving at : %s %n", landing);
} catch (DateTimeException ex) {
System.out.printf("%s can't be formatted!%n", arriveDate);
ex.printStackTrace();
}
Output : Arriving at : Jan 14 2014 04:33 PM
It can be seen that the current time is represented by the given "MMM dd yyyy hh:mm a" pattern, which contains the month represented by three letters and the time represented by AM and PM.
Several key points of the date and time API in Java 8
After reading these examples, I believe you have a certain understanding of Java 8's new time and date API. Now let's review some key elements about this new API.
1. It provides javax.time.ZoneId to handle time zones.
2. It provides LocalDate and LocalTime classes
3. All classes in the new Time and Date API in Java 8 are immutable and thread-safe, which is exactly the opposite of the previous Date and Calendar APIs, where they are like java.util.Date and SimpleDateFormat. Classes are not thread-safe.
4. A very important point in the new Time and Date API is that it clearly defines the basic concepts of time and date, such as instantaneous time, duration, date, time, time zone and time period. They are all based on the ISO calendar system.
5. Every Java developer should know at least these five classes in this new API:
5.1) Instant It represents a timestamp, like 2014-01-14T02:20:13.592Z, which can be obtained from the java.time.Clock class, like this: Instant current = Clock.system(ZoneId.of("Asia /Tokyo")).instant();
5.2) LocalDate It represents a date without time, such as 2014-01-14. It can be used to store birthdays, anniversary, induction dates, and more.
5.3) LocalTime It represents a time without a date
5.4) LocalDateTime It contains time and date, but there is no offset with time zone
5.5) ZonedDateTime This is a full time with time zone adjustment based on UTC/Greenwich time
1. The main package of this library is java.time, which contains classes representing date, time, instant and duration. It has two subpackages, one is java.time.foramt, which is obvious what this is used for, and the other is java.time.temporal, which can access various fields from a lower level.
2. Time zone refers to the region on the earth that shares the same standard time. Each time zone has a unique identifier, and there is also a region/city (Asia/Tokyo) format and an offset time starting from Greenwich time. For example, the offset time in Tokyo is +09:00.
3.OffsetDateTime class actually contains LocalDateTime and ZoneOffset. It is used to represent a complete date (year, month, day) and time (hour, minute, nanosecond) containing the Greenwich time offset (+/-hour:minute, for example +06:00 or -08:00) .
4. The DateTimeFormatter class is used to format and parse dates in Java. Unlike SimpleDateFormat, it is immutable and thread-safe, and can be assigned to a static variable if needed. The DateTimeFormatter class provides many predefined formatters, and you can also customize the format you want. Of course, according to the convention, it also has a parse() method used to convert a string to a date, and if there is any error during the conversion, it will throw a DateTimeParseException exception. Similarly, the DateFormatter class also has a format() method for formatting dates. If it fails, a DateTimeException will be thrown.
5. In other words, the two date formats of "MMM d yyyy" and "MMm dd yyyy" are also slightly different. The former can identify the two strings "Jan 2 2014" and "Jan 14 2014", and the latter if the The one who comes in "Jan 2 2014" will report an error because it expects two characters to come in from the month. To solve this problem, if the day is single digits, you have to make up 0 in front, for example, "Jan 2 2014" should be changed to "Jan 02 2014".
That's all about Java 8, the new time and date API. These short examples are enough to understand some of the new classes in this new API. Since it is explained based on actual tasks, when you encounter work in Java that needs to process time and date, you don’t have to search around anymore. We learned how to create and modify date instances. We also learned about the differences between pure dates, date plus time, date plus time zones, know how to compare two dates, and how to find a certain day to a specified date, such as the next birthday, anniversary or insurance date. We also learned how to parse and format dates in Java 8 in a thread-safe way without using thread-local variables or third-party libraries. The new API is competent for any time and date related tasks.