1 SimpleDateFormat pit

1.1 the formatting

1.1.1 case

  • Initialize a Calendar and set the date to December 29, 2020

  • The log

This is due to confusing SimpleDateFormat’s various formatting modes:

  • Little y is the year

  • Uppercase Y is week year, which is the year of the week

The first week of the year

From getFirstDayOfWeek (), a full seven days, and contains the year at least getMinimalDaysInFirstWeek () day. The calculation method is region-dependent. For zh_CN region, conditions for the first week of 2020: the full 7 days starting from Sunday, including 1 day in 2020. Sunday, December 27, 2019, to Saturday, January 2, 2020 is the first week of 2020.

If I change the region to France

Locale.setDefault(Locale.FRANCE);
Copy the code

Week Yeay is still 2020, because the first day of the week starts on Monday, the first week of 2020 starts on Monday, December 28, 2019, and the 27th is still last year:

summary

No special requirements, use “Y” instead of “y” when formatting dates for years.

Thread safety

Using a thread pool of 100 threads, loop 20 times to submit the time formatting task to the thread pool for processing, loop 10 times for parsing each task:

  • After running the program, a large number of errors are reported. Even if no errors are reported, the output result is abnormal, for example, the year 2020 is resolved to 57728

SimpleDateFormat is used to define the schema for parsing and formatting dates and times. It looks like a one-time job and should be reused, but its parsing and formatting operations are not thread-safe.

Analysis of the source code

SimpleDateFormat inherits from DateFormat, which has field Calendar;

  • SimpleDateFormat#parsecallCalendarBuilder#establishBuild a Calendar

The establish method clears Calendar and builds Calendar without locking.

Obviously, using a thread pool to call parse, where multiple threads concurrently manipulate a Calendar, can result in one thread clearing the Calendar before it can be processed by another thread. The format method is used in the same way. So you can only reuse SimpleDateFormat in the same thread,

The solution

Store SimpleDateFormat with ThreadLocal:

  • The log output is correct

1.2 When the string to be parsed does not match the format, SimpleDateFormat can still get the result

case

Parse 20160901 string using yyyyMM:

  • Actually output 2112, this is because 1111 as a month

For these holes in SimpleDateFormat, use the DateTimeFormatter in Java 8 to avoid them.

DateTimeFormatter in Java 8

2.1 Formatting Strings

First, use the DateTimeFormatterBuilder to define the formatting string without memorizing capital Y or lowercase Y, capital M or lowercase M:

2.2 Thread Safety

Can be defined as static

2.3 An error is reported if the string to be parsed does not match the format

  • The log

    2020/11/11 11:11:11. 789 Exception in the thread “is the main” Java. Time. The format. DateTimeParseException: Text ‘20201111’ could not be parsed at index 0 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1777) at org.javaedge.time.commonmistakes.datetime.dateformat.CommonMistakesApplication.better(CommonMistakesApplication.java:96) at org.javaedge.time.commonmistakes.datetime.dateformat.CommonMistakesApplication.main(CommonMistakesApplication.java:47)

3 Java8 Calculates the date and time

  • Some people like to use time stamps to calculate, such as want to get the current time 30 days later: thenew Date().getTimeThe resulting timestamp plus 30 days corresponds to milliseconds

  • The date is actually earlier than the current date, not 30 days later at all

Because int overflowed! .

  • 30 should be changed to 30L to make it long:

  • The correct output

  • Java 8 pre-code, Calendar is recommended:

  • Using Java 8’s date-time type, you can perform all kinds of calculations directly, which is more concise and convenient:

For date and time calculations, the date and time API is much more powerful than Calendar.

3.1 Minus /plus Directly adds and subtracts dates

3.2 With Quick time adjustment

  • TemporalAdjusters firstDayOfMonth get on the first day of the current month

  • TemporalAdjusters. FirstDayOfYear () to get the first day of the year

  • TemporalAdjusters. Previous (DayOfWeek. SATURDAY) get on a SATURDAY

  • TemporalAdjusters. LastInMonth (DayOfWeek. FRIDAY) for this month last FRIDAY

3.3 Time adjustment using Lambda custom

  • Add random days within 100 days to the current time:

Determine if a date meets a condition

Query Indicates whether the query matches the condition

Java 8 has a special class called Period that defines the interval between dates. Period. Between returns the difference between two localdates, which is years, months, and days. If you want to know how many days there is between two dates, calling getDays() on a Period gives you only the last “zero days”, not the total number of days between dates.

For example, if you calculate the interval between December 12, 2020 and October 1, 2020, it is clear that the difference is 2 months and 11 days, but the getDays method yields 11 days instead of 72:

To solve this problem, use chronounit.days. between:

4 summarizes

You might think that java.util.Date is similar to LocalDateTime in the new API. Not really, although none of them have a time zone concept

  • The java.util.Date class has no time zone concept because it is represented in UTC. It is essentially a timestamp

  • LocalDateTime, strictly speaking, is a date-time representation, not a point in time

Therefore, when converting a Date to a LocalDateTime, you need to use Date’s toInstant method to get a UTC timestamp and provide the current time zone in order to convert the UTC time to a LocalDateTime. Datetime = ZonedDateTime = ZonedDateTime = ZonedDateTime = ZonedDateTime

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
Copy the code

Some people say that the new API is cumbersome, and you need to consider the time zone, really cumbersome. But not because the API is forced to be cumbersome, but because to convert UTC time to local time, time zones must be considered!

———————

Why are Alibaba’s programmers growing so fast?

Top GitHub Offer comes to principle + framework, open sharing;

50W annual salary programmer need technology stack analysis

Three things to watch ❤️

If you find this article helpful, I’d like to invite you to do three small favors for me:

Like, forward, have your “like and comment”, is the motivation of my creation.

Follow the public account “Java Doudi” to share original knowledge from time to time.

Also look forward to the follow-up article ing🚀