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 developing a reminder application to find out how many days there are to be before some specific dates such as birthday, Sunday anniversary, next billing day, next premium day or credit card expiration time.
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.
LocalDate today = LocalDate.now(); System.out.println("Today's Local date : " + today); Output Today's Local date : 2014-01-14You 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 attribute you need, without using classes like java.util.Calendar:
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-14Year : 2014 Month : 1 day : 14As 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 takes the parameter of the 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.
LocalDate dateOfBirth = LocalDate.of(2010, 01, 14); System.out.println("Your Date of birth is : " + dateOfBirth); Output: Your Date of birth is : 2010-01-14It 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:
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 dateIn 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 and Thanksgiving, and in India it may be 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:
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.
LocalTime time = LocalTime.now(); System.out.println("local time now : " + time); Output local time now : 16:33:33.369 // in hour, minutes, seconds, nano secondsAs 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.
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.369You 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.
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-14Date after 1 week : 2014-01-21You 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 to 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.
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-14Date after 1 year : 2015-01-14It 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. You can use Clock to replace the System.currentTimeInMillis() and TimeZone.getDefault() methods.
// 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:
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.
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 todayIt 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:
// 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:
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.
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: 31Your credit card expires on 2018-02Example 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.
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 yearYou 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.
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 : 2As 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.
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: 2014-01-14T19:30+05:30You 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:
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.379ZIt 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 convert between these two types. 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.
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-16You 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.
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-18You 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 to 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.
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", arrivalDate); ex.printStackTrace(); } Output : Arriving at : Jan 14 2014 04:33 PMIt 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. Key classes like java.util.Date and SimpleDateFormat 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:
6. 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.
7. 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.
8. The 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, minute, nanosecond).
9. 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 the 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.
10. To put it another way, the two date formats of "MMM d yyyy" and "MMm dd yyyy" are also slightly different. The former can recognize the two strings "Jan 2 2014" and "Jan 14 2014", and the latter will report an error if the "Jan 2 2014" is transmitted in, because it expects that the two characters will be transmitted in 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.