JAVA8 battle-date API

This is the 9th day of my participation in the August Wen Challenge.More challenges in August

preface

In this section we will look at the date class in JAVA8. The source code is actually written by joda-time, so you can see that many of the apis are similar to the Joda class. Date classes have always been difficult to use, but JAVA8 provides a new set of apis for date classes to make them easier to use.

This article is more code, it is recommended to run the code to understand.

Mind mapping:

Address: www.mubucm.com/doc/ck5ZCrg…

Content Overview:

  1. JDK8’s three core date classes: LocalDate, LocalTime, and LocalDateTime
  2. Machine time and date formatsInstantAnd other fine – grained time operations
  3. TemporalAdjusters is used for more complex date calculations, such as calculating the next business day. The class provides some implementation
  4. DateTimeFormatter, very flexible, belongs toSimpleDateFormatSubstitutes for.
  5. Some personal tool encapsulation examples of the date API, as well as some personal stumbles when using JDK8

Finally, I hope this article can help you get rid of new Date().

What is ISO-8601?

The date cannot be separated from ISO-8601. The following is a brief description of ISO-8601, referring to Baidu Encyclopedia:

  1. Iso-8601: Date and time representation method developed by the International Organization for Standardization, known as “Data storage and exchange forms, Information Exchange, date and time representation method”, abbreviated as ISO-8601.
  2. Representation of the day: hours, minutes, and seconds are represented by two digits, with a capital Z at the end of UTC time. Other time zones are represented by the actual time plus the time difference. For example, 2:30pm UTC time is represented as 14:30:05Z or 143005Z. Beijing time at that time is represented as 22:30:05+08:00 or 223005+0800, which can also be simplified to 223005+08.
  3. The combination of date and time is expressed as follows: add a capital letter T in front of the time. For example, to represent 5:30pm Beijing time on May 3, 2004, it can be written as 2004-05-03T17:30:08+08:00 or 20040503T173008+08.

LocalDate, LocalTime, LocalDateTime

JDK8 splits time into three parts, one is time, which represents the information of year, month and day, one is date, which represents the part of hour, minute and second, and finally, the specific time of the sum of these two objects.

LocalDate

LocalDate: The class represents a specific date, but does not contain a specific time and does not contain time zone information. You can create an instance of LocalDate using the static of() method. LocalDate also contains methods to get the year, month, day, day, and so on.


    @Test
    public void localDateTest(a) throws Exception {
        // Create a LocalDate:
        LocalDate of = LocalDate.of(2021.8.9);
        // Get the current time
        LocalDate now = LocalDate.now();
        / / format
        LocalDate parse1 = LocalDate.parse("2021-05-11");
        // Specify a date format
        LocalDate parse2 = LocalDate.parse("2021-05-11", DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        // The following code has a formatting exception
        // java.time.format.DateTimeParseException: Text '2021-05-11 11:53:53' could not be parsed, unparsed text found at index 10
// LocalDate parse3 = LocalDate.parse("2021-05-11 11:53:53", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        // Correct formatting methods
        LocalDate parse3 = LocalDate.parse("The 2021-05-11 11:53:53", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        // The current time
        System.out.println("now() => "+ now);
        // Get the month
        int dayOfMonth = parse1.getDayOfMonth();
        System.out.println("dayOfMonth => " + dayOfMonth);
        // Get the year
        int dayOfYear = parse1.getDayOfYear();
        System.out.println("getDayOfYear => " + dayOfYear);
        // Get that week, notice that we're getting objects here
        DayOfWeek dayOfWeek = parse1.getDayOfWeek();
        System.out.println("getDayOfWeek => " + dayOfWeek);
        // Get monthly data
        int monthValue = parse3.getMonthValue();
        System.out.println("getMonthValue => " + monthValue);
        // Get the year
        int year = parse3.getYear();
        System.out.println("getYear => " + year);
        // getChronology is the chronology of the current time, where the output is ISO
        System.out.println("getChronology => " + parse3.getChronology());
        System.out.println("getEra => " + parse3.getEra());


        TemporalField is an interface that defines how to access the value of TemporalField. ChronnoField implements this interface
        /* LocalDate supports the following formats: case DAY_OF_WEEK: return getDayOfWeek().getValue(); case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1; case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1; case DAY_OF_MONTH: return day; case DAY_OF_YEAR: return getDayOfYear(); case EPOCH_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'EpochDay' for get() method, use getLong() instead"); case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1; case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1) / 7) + 1; case MONTH_OF_YEAR: return month; case PROLEPTIC_MONTH: throw new UnsupportedTemporalTypeException("Invalid field 'ProlepticMonth' for get() method, use getLong() instead"); case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year); case YEAR: return year; case ERA: return (year >= 1 ? 1:0); * * /
        // Unsupported field: HourOfDay
// System.out.println("ChronoField.HOUR_OF_DAY => " + parse1.get(ChronoField.HOUR_OF_DAY));
        // Unsupported field: MinuteOfHour
// System.out.println("ChronoField.MINUTE_OF_HOUR => " + parse1.get(ChronoField.MINUTE_OF_HOUR));
        // Unsupported field: MinuteOfHour
// System.out.println("ChronoField.SECOND_OF_MINUTE => " + parse1.get(ChronoField.SECOND_OF_MINUTE));
        System.out.println("ChronoField.YEAR => " + parse1.get(ChronoField.YEAR));
        // Unsupported field: MinuteOfHour
// System.out.println("ChronoField.INSTANT_SECONDS => " + parse1.get(ChronoField.INSTANT_SECONDS));

    }/* Result:  now() => 2021-08-08 dayOfMonth => 11 getDayOfYear => 131 getDayOfWeek => TUESDAY getMonthValue => 5 getYear => 2021 getChronology => ISO getEra => CE ChronoField.YEAR => 2021 */
Copy the code

TemporalField is an interface that defines how to access the value of TemporalField. ChronnoField implements this interface

LocalTime

LocalTime: is similar to LocalDate, except that it contains the specific time and has more specific time. The following are the corresponding methods and tests:

 @Test
    public void localTimeTest(a) throws Exception {
        LocalTime now = LocalTime.now();
        System.out.println("LocalTime.now() => "+  now);
        System.out.println("getHour => "+ now.getHour());
        System.out.println("getMinute => "+ now.getMinute());
        System.out.println("getNano => "+ now.getNano());
        System.out.println("getSecond => "+ now.getSecond());

        LocalTime systemDefault = LocalTime.now(Clock.systemDefaultZone());
        / / ZoneName = > Java. Time. The format. The ZoneName. ZidMap from this map on the inside to get it
        LocalTime japan = LocalTime.now(Clock.system(ZoneId.of("Japan")));
        // Change the time zone
        LocalTime japan2 = LocalTime.now(ZoneId.of("Japan"));
        // Format the time
        LocalTime localTime = LocalTime.of(15.22);
        // From transforms from another time, as long as their interfaces are compatible
        LocalTime from = LocalTime.from(LocalDateTime.now());
        // the value of nanosecond
        LocalTime localTime1 = LocalTime.ofNanoOfDay(1);
        LocalTime localTime2 = LocalTime.ofSecondOfDay(1);
        Invalid value for MinuteOfHour (valid values 0-59): 77
// LocalTime.of(15, 77);
        // Get the local default time
        System.out.println("LocalTime.now(Clock.systemDefaultZone()) => "+ systemDefault);
        // Get the time of Japan time zone
        System.out.println("LocalTime.now(Clock.system(ZoneId.of(\"Japan\"))) => "+ japan);
        System.out.println("LocalTime.now(ZoneId.of(\"Japan\")) => "+ japan2);
        System.out.println("LocalTime.of(15, 22) => "+ localTime);
        System.out.println("LocalTime.from(LocalDateTime.now()) => "+ from);
        System.out.println("LocalTime.ofNanoOfDay(1) => "+ localTime1);
        System.out.println("LocalTime.ofSecondOfDay(1) => "+ localTime2);
    }/* Result: Localtime.now () => 12:58:13.553 getHour => 12 getMinute => 58 getNano => 553000000 getSecond => 13 Localtime.now (clock. systemDefaultZone()) => 12:58:13.553 localtime.now (clock. system(zoneid.of ("Japan"))) => 13:58:13.553 LocalTime. Now (ZoneId) of (" Japan ")) = > 13:58:13. 553 LocalTime. Of (15, From (localDatetime.now ()) => 12:58:13.553 localTime.ofnanoofDay (1) => 00:00:00.000000001 LocalTime.ofSecondOfDay(1) => 00:00:01 */
Copy the code

LocalDateTime

LocalDateTime: The LocalDateTime class is a combination of LocalDate and LocalTime and can be created directly with the of() method, It is also possible to combine a LocalDate or LocalTime into a LocalDateTime by calling the atTime() method of LocalDate or the atDate() method of LocalTime. Here are some simple method tests. You’ll later write code for a utility class that combines this.

	@Test
    public void localDateTimeTest(a) throws Exception {
        //Text '2021-11-11 15:30:11' could not be parsed at index 10
// LocalDateTime parse = LocalDateTime.parse("2021-11-11 15:30:11");
        // The ISO time format is used by default
        LocalDateTime parse1 = LocalDateTime.parse("2011-12-03T10:15:30");
        // If you want your own format, you need to format it manually
        LocalDateTime parse = LocalDateTime.parse("The 2021-11-11 15:30:11", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println("LocalDateTime.parse(....) => "+ parse1);
        System.out.println("LocalDateTime.parse(....) => "+ parse);

        LocalDateTime of = LocalDateTime.of(LocalDate.now(), LocalTime.now());
        LocalDateTime japan = LocalDateTime.now(ZoneId.of("Japan"));
        System.out.println("LocalDateTime.of(LocalDate.now(), LocalTime.now()) => "+ of);
        System.out.println("LocalDateTime.now(ZoneId.of(\"Japan\")) => "+ japan);
    }/* Localdatetime.parse (....) => 2011-12-03T10:15:30 LocalDateTime.parse(....) => 2021-11-11T15:30:11 LocalDateTime.of(LocalDate.now(), Localtime.now ()) => 21-08-08T13:22:59.697 localtime.now (zoneid.of ("Japan")) => 21-08-08T14:22:59.697 */
Copy the code

Fine grained machine time operation

JDK8 also classifies machine time, as shown below

Instant

Instant is used to represent a timestamp, similar to the common system.currentTimemillis (), but accurate to nano-second.

Note: Two constants are used internally, seconds for the number of seconds since 1970-01-01 00:00:00 and nanos for the nanosecond part (nanos does not exceed 999,999,999).

Here are some specific test cases:

@Test
    public void instantTest(a) throws Exception {
        Instant now = Instant.now();
        // Unable to obtain Instant from TemporalAccessor: 2021-08-08T13:37:34.403 of type java.time.LocalDateTime
// Instant from = Instant.from(LocalDateTime.now());
        Instant instant = Instant.ofEpochSecond(3.0);
        Instant instant1 = Instant.ofEpochSecond(5.1 _000_000_000);
        System.out.println("Instant.now() => "+ now);
// System.out.println("Instant.from(LocalDateTime.now()) => "+ from);
        System.out.println("Instant.ofEpochSecond => "+ instant);
        System.out.println("Instant.ofEpochSecond => "+ instant1);
        System.out.println("Instant.get(ChronoField.NANO_OF_SECOND) => "+ now.get(ChronoField.NANO_OF_SECOND));
    }/* Result: Instant. Now () => 2021-08-08T05:42:42.465z Instant. OfEpochSecond => 1970-01-01 t00:03z Instant. 1970-01-01T00:00:06Z Instant.get(ChronoField.NANO_OF_SECOND) => 465000000 */
Copy the code

Duration

The internal implementation of Duration is similar to Instant in that it has two parts: seconds for seconds and nanos for nanoseconds. The difference between the two is that Instant is used to represent a timestamp (or point in time), while Duration is used to represent a time period, such as when you want to get the difference between two times:

	@Test
    public void durationTest(a) throws Exception {
        // Text '201-08-08T10:15:30' could not be parsed at index 0
        Duration between = Duration.between(LocalDateTime.parse("2011-12-03T10:15:30"), LocalDateTime.parse("2021-08-08T10:15:30"));
        System.out.println("Duration.between(LocalDateTime.parse(\"2011-12-03T10:15:30\"), LocalDateTime.parse(\"2021-08-08T10:15:30\")) => "+ between);

        Duration duration = Duration.ofDays(7);
        System.out.println("Duration.ofDays(7) => "+ duration);
    }
Copy the code

Period

Period is conceptually similar to Duration, except that Period is measured by year, month and day (e.g. 2 years, 3 months and 6 days). Here is the corresponding unit test and related code:

@Test
    public void periodTest(a) throws Exception {
        Period between = Period.between(LocalDate.parse("2011-12-03"), LocalDate.parse("2021-08-08"));
        Period period = Period.ofWeeks(53);
        Period period1 = Period.ofWeeks(22);
        System.out.println("Period.between(LocalDate.parse(\"2011-12-03\"), LocalDate.parse(\"2021-08-08\")) => "+ between);
        System.out.println("Period.ofWeeks(53) => "+ period);
        System.out.println("Period.ofWeeks(53) getDays => "+ period.getDays());
        // Note that 0 is present if there is no corresponding value
        System.out.println("Period.ofWeeks(53) getMonths => "+ period.getMonths());
        System.out.println("Period.ofWeeks(22) getMonths => "+ period1.getMonths());
        System.out.println("Period.ofWeeks(22) getYears => "+ period1.getYears());
    }/* Result:  Period.between(LocalDate.parse("2011-12-03"), LocalDate.parse("2021-08-08")) => P9Y8M5D Period.ofWeeks(53) => P371D Period.ofWeeks(53) getDays => 371 Period.ofWeeks(53) getMonths => 0 Period.ofWeeks(22) getMonths => 0 Period.ofWeeks(22) getYears => 0 */
Copy the code

TemporalAdjusters complex date operation

This class can do all sorts of more complex operations on time, such as the next business day, the last day of the month, with the with method:

@Test
public void testTemporalAdjusters(a){
    LocalDate of = LocalDate.of(2021.8.1);
    // Get the first day of the current year
    LocalDate with = of.with(TemporalAdjusters.firstDayOfYear());
    System.out.println(" TemporalAdjusters.firstDayOfYear => "+ with);
    // Get the next Saturday of the specified date
    LocalDate with1 = of.with(TemporalAdjusters.next(DayOfWeek.SATURDAY));
    System.out.println(" TemporalAdjusters.next(DayOfWeek.SATURDAY) => "+ with1);
    // Get the last day of the month
    LocalDate with2 = of.with(TemporalAdjusters.lastDayOfMonth());
    System.out.println("TemporalAdjusters.lastDayOfMonth() => "+ with2);

}
Copy the code

Here’s a list of all the methods from the network

The method name describe
dayOfWeekInMonth Returns the day of the week in the same month
firstDayOfMonth Returns the first day of the month
firstDayOfNextMonth Return to the first day of the next month
firstDayOfNextYear Return to the first day of the next year
firstDayOfYear Return to the first day of the year
firstInMonth Returns the first day of the month
lastDayOfMonth Returns the last day of the month
lastDayOfNextMonth Return to the last day of the next month
lastDayOfNextYear Return to the last day of the next year
lastDayOfYear Return to the last day of the year
lastInMonth Returns the last day of the month
next / previous Returns the day of the following/preceding given week
nextOrSame / previousOrSame Returns the next/previous given day of the week, or if the value meets the criteria

DateTimeFormatter Formatter

This class can be thought of as an alternative to SimpleDateFormat in that it has more powerful customization and is thread-safe so you don’t have to worry about multithreaded access.

Build a local formatter based on the DateTimeFormatter, and the code is very simple to understand:

private static DateTimeFormatter generateDefualtPattern(String timeFormat) {
    return new DateTimeFormatterBuilder().appendPattern(timeFormat)
        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
        .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
        .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
        .toFormatter(Locale.CHINA);
}
Copy the code

Time zone information

Time zone information is rarely used, which may be used in operations related to internationalization. For example, I recently bought something from Apple. Although I placed an order on 6th, the phone said I placed the order on 5th, so I think the exact time apple placed the order is calculated according to the American time.

Strong JDK8 date class about time zones related classes (note the case.brass appeared JDK8 class, don’t be mistaken for compatible) of class before, in the previous unit testing is already used in the relevant time zone, the method of using the ZoneId in JDK8 this class, but sometimes we don’t know how to get in, you can refer to the following contents:

/ / ZoneName = > Java. Time. The format. The ZoneName. ZidMap from this map on the inside to get it
LocalTime japan = LocalTime.now(Clock.system(ZoneId.of("Japan")));
Copy the code

Field – Encapsulate the date utility class

Of course, the best way is to give yourself a few more requirements, forced to use JDK8 method to achieve, you will find that you master these API will be particularly fast.

Matters needing attention:

All utility code uses the same local formatter build method: generateDefualtPattern() :

/** * generates the default formatter **@paramTimeFormat Specifies the format *@returnThe default time formatter */
    private static DateTimeFormatter generateDefualtPattern(String timeFormat) {
        return new DateTimeFormatterBuilder().appendPattern(timeFormat)
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                .toFormatter(Locale.CHINA);
    }

Copy the code

Gets the last and next business days for the specified time

Note that this version does not judge holidays, but of course this is the manual version.

/** * Gets the last working day of the specified time **@paramTime Specifies the time *@paramFormattPattern Format parameter *@return* /
    public static String getPreWorkDay(String time, String formattPattern) {
        DateTimeFormatter dateTimeFormatter = generateDefualtPattern(formattPattern);
        LocalDateTime compareTime1 = LocalDateTime.parse(time, dateTimeFormatter);
        compareTime1 = compareTime1.with(temporal -> {
            // The current date
            DayOfWeek dayOfWeek = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
            // Normally, subtract one day at a time
            int dayToMinu = 1;
            // If it is Sunday, subtract 2 days
            if (dayOfWeek == DayOfWeek.SUNDAY) {
                dayToMinu = 2;
            }
            // If it is Saturday, subtract one day
            if (dayOfWeek == DayOfWeek.SATURDAY) {
                dayToMinu = 1;
            }
            return temporal.minus(dayToMinu, ChronoUnit.DAYS);
        });
        return compareTime1.format(dateTimeFormatter);
    }


    /** * Gets the next working day of the specified time **@paramTime Specifies the time *@paramFormattPattern Format parameter *@return* /
    public static String getNextWorkDay(String time, String formattPattern) {
        DateTimeFormatter dateTimeFormatter = generateDefualtPattern(formattPattern);
        LocalDateTime compareTime1 = LocalDateTime.parse(time, dateTimeFormatter);
        compareTime1 = compareTime1.with(temporal -> {
            // The current date
            DayOfWeek dayOfWeek = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
            // Normally, add one day at a time
            int dayToAdd = 1;
            // If it is Friday, add 3 days
            if (dayOfWeek == DayOfWeek.FRIDAY) {
                dayToAdd = 3;
            }
            // If it is Saturday, add two days
            if (dayOfWeek == DayOfWeek.SATURDAY) {
                dayToAdd = 2;
            }
            return temporal.plus(dayToAdd, ChronoUnit.DAYS);
        });
        return compareTime1.format(dateTimeFormatter);
    }
Copy the code

Check whether the current time is less than the target time

To determine whether the current time is less than the target time, this is a combination of some of the methods we learned earlier. Note that the time zone used here is the current system time zone. If you switch to another time zone, you will see a different effect. And I’m using LocalDateTime so don’t get confused.

/** * Use JDK 1.8 date classes to compare times ** determine whether the current time is less than the target time **@paramTime Time character string *@paramFormat Specifies the format *@returnCheck whether the current time is less than the target time */
    public static boolean isBefore(String time, String format) {
        DateTimeFormatter dateTimeFormatter = generateDefualtPattern(format);
        LocalDateTime compareTime = LocalDateTime.parse(time, dateTimeFormatter);
        GetNowByNew encapsulates the now() method
        LocalDateTime current = LocalDateTime.parse(getNowByNew(format), dateTimeFormatter);
        long compare = Instant.from(compareTime.atZone(ZoneId.systemDefault())).toEpochMilli();
        long currentTimeMillis = Instant.from(current.atZone(ZoneId.systemDefault())).toEpochMilli();
        return currentTimeMillis < compare;
    }
Copy the code

Gets the day of the week for the specified time

It is a secondary encapsulation of JDK8’s own methods.

/** * returns the enumeration object **@paramThe date date *@paramFormattPattern format *@return* /
public static DayOfWeek getDayOfWeek(String date, String formattPattern) {
    DateTimeFormatter dateTimeFormatter = generateDefualtPattern(formattPattern);
    return LocalDate.parse(date, dateTimeFormatter).getDayOfWeek();
}
Copy the code

Gets the date between the start date and end date

Here need to pay attention to is not very rigorous, it is best to execute before the date of judgment

public static final String yyyyMMdd = "yyyy-MM-dd";

/** * Gets the date between the start date and the end date (returns List<String>) **@paramStartTime Start date *@paramEndTime End date *@returnAll dates between start and end, including start and end */
public static List<String> getMiddleDateToString(String startTime, String endTime) {
    LocalDate begin = LocalDate.parse(startTime, DateTimeFormatter.ofPattern(yyyyMMdd));
    LocalDate end = LocalDate.parse(endTime, DateTimeFormatter.ofPattern(yyyyMMdd));
    List<LocalDate> localDateList = new ArrayList<>();
    long length = end.toEpochDay() - begin.toEpochDay();
    // The number of days to collect the difference
    for (long i = length; i >= 0; i--) {
        localDateList.add(end.minusDays(i));
    }
    List<String> resultList = new ArrayList<>();
    for (LocalDate temp : localDateList) {
        resultList.add(temp.toString());
    }
    return resultList;
}
Copy the code

Common pits in the date API:

LocalDateTimeThe format ofyyyy-MM-ddError:

The most problematic diamante for first use is shown in the following form, as we do

LocalDateTime parse2 = LocalDateTime.parse("2021-11-11", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
Copy the code

When run, the following exception is thrown:

java.time.format.DateTimeParseException: Text '2021-11-11' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {},ISO resolved to 2021-11-11 of type java.time.format.Parsed
Copy the code

Here’s the solution:

The first solution is more painful, but it is a very safe solution.

try {
    LocalDate localDate = LocalDate.parse("2019-05-27", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    LocalDateTime localDateTime = localDate.atStartOfDay();
    System.out.println(localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
} catch (Exception ex) {
    ex.printStackTrace();
}
Copy the code

Another way is to build a “Chinese” date formatter using the following method:

/** * generates the default formatter **@paramTimeFormat Specifies the format *@returnThe default time formatter */
private static DateTimeFormatter generateDefualtPattern(String timeFormat) {
    return new DateTimeFormatterBuilder().appendPattern(timeFormat)
        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
        .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
        .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
        .toFormatter(Locale.CHINA);
}
Copy the code

Call format appearsxx not be parsed, unparsed text found at index 10

Error: Use incorrect format to format string, such as YYYY-MM-DD format 2020-05-12 12:15:33

The fundamental solution to the above problems is as follows: Because localdateTime does not find the corresponding format in the case of formatting, there will be similar to the unsupport method

/** * generates the default formatter **@paramTimeFormat Specifies the format *@return* /
    private static DateTimeFormatter generateDefualtPattern(String timeFormat) {
        return new DateTimeFormatterBuilder().appendPattern(timeFormat)
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 1)
                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 1)
                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                .toFormatter(Locale.CHINA);
    }
Copy the code

Here are some answers to other questions:

DateTimeParseException: Text could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor

Text: Cannot get LocalDateTime from TemporalAccessor

Cannot obtain LocalDateTime from TemporalAccessor when parsing LocalDateTime (Java 8)

DateTimeParseException a few craters

Referring to the exception log below, the root cause is that DateTimeFormatter formatting does not have the HH option, which is where the pit is

java.time.format.DateTimeParseException: Text 'the 2017-02-02 08:59:12' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {MinuteOfHour=59, NanoOfSecond=0, SecondOfMinute=12, MicroOfSecond=0, MilliOfSecond=0, HourOfAmPm=8},ISO resolved to 2017-02-02 of type java.time.format.Parsed
Copy the code

Conclusion:

In the process of writing my own utility classes, I found them to work much better than the previous Date and Calendar classes, and the Date classes in JDK8 are thread-safe. Of course JDK8 is not very friendly for domestic use, there is no way after all is a foreign thing, but there are a lot of solutions, used to solve the routine can also accept. Finally, conditional had better use the search engine of Google, can help you cross pit not only in the past, a lot of big god still can give you talk about principle, be very useful.

Write in the last

Writing is not easy, beg for praise, beg for collection.

Finally, I would like to recommend my personal wechat public account: “Laishi Xiaowu”. If you have any questions, please communicate with me through the public account. Of course, the comments will be answered as soon as you see them.

Other problems

  1. A pit about LocalDate

About LocalDate some source code analysis

Directly to the source code, LocalDate represents only a date, not a DateTime. Therefore, “HH: mm: ss” is meaningless during formatting. If our formatting parameters do not conform to the following rules, this method will throw an exception and indicate that the corresponding formatting operation is not supported.

private int get0(TemporalField field) {
        switch ((ChronoField) field) {
            case DAY_OF_WEEK: return getDayOfWeek().getValue();
            case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1;
            case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1;
            case DAY_OF_MONTH: return day;
            case DAY_OF_YEAR: return getDayOfYear();
            case EPOCH_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'EpochDay' for get() method, use getLong() instead");
            case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1;
            case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1) / 7) + 1;
            case MONTH_OF_YEAR: return month;
            case PROLEPTIC_MONTH: throw new UnsupportedTemporalTypeException("Invalid field 'ProlepticMonth' for get() method, use getLong() instead");
            case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year);
            case YEAR: return year;
            case ERA: return (year >= 1 ? 1 : 0);
        }
        throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
    }
Copy the code
  1. Formatting problems:

    Calling DateFomatter can cause errors, mostly due to using the wrong format or using the wrong time class

    Error java.time.format.DateTimeParseException: could not be parsed, unparsed text found at index 10

The resources

Spiderman said java8 – LocalDateTime