This is the 10th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

❤️ About the author: Hello everyone, I am Xiao Xu Zhu. Java field quality creator 🏆, CSDN blog expert certification 🏆, Huawei Cloud enjoy expert certification 🏆

❤️ technology live, the appreciation

❤️ like 👍 collect ⭐ look again, form a habit

Before reading this article, it is recommended to have some knowledge of the date and time of Java source code. If not, you can read this article first:

Swastika blog teaches you to understand Java source code date and time related usage

Related articles:

Hutool actual combat (take you to master the various tools) directory

5hutool Combat :DateUtil- Parse the time that was formatted


Source code analysis purposes

Know what it is and why

Project reference

The basis of this blog: Hutool -5.6.5 version of the source code

        <dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-core</artifactId>
			<version>5.6.5</version>
		</dependency>
Copy the code

The method name: DateUtil. ParseLocalDateTime (Java. Lang. CharSequence)

Methods described

Construct LocalDateTime object format: YYYY-MM-DD HH: MM: SS

Source code Analysis 1

	/** * Build the LocalDateTime object **@paramDateStr Time string (formatted) *@paramUse the format {@linkDatePattern} defines the format *@returnLocalDateTime object * /
	public static LocalDateTime parseLocalDateTime(CharSequence dateStr, String format) {
		return LocalDateTimeUtil.parse(dateStr, format);
	}
Copy the code

ParseLocalDateTime (CharSequence dateStr, String format) the format of the method must use the format defined by DatePattern to ensure that it can be parsed.

**LocalDateTimeUtil.parse(dateStr, format)** localDateTimeUtil.parse (dateStr, format)** localDateTimeUtil.parse (dateStr, format)

//LocalDateTimeUtil
/** * parses the date and time string as {@link LocalDateTime}
	 *
	 * @paramText Date time character string *@paramFormat The date format, similar to YYYY-MM-DD HH: MM :ss,SSS *@return {@link LocalDateTime}
	 */
	public static LocalDateTime parse(CharSequence text, String format) {
		if (null == text) {
			return null;
		}

		DateTimeFormatter formatter = null;
		if(StrUtil.isNotBlank(format)){
			// Fix a problem where the 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 yyyyMMddHHmmssS and yyyyMMddHHmmssSS dates into the yyyyMMddHHmmssSSS format 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);
	}
Copy the code

Comments in writing to repair the JDK8 a bug bugs.openjdk.java.net/browse/JDK-…

Try:

	@Test
	public void localDateTimeTest5(a) {
		String strDate = "20210805220359100";
		DateTimeFormatter formatter =DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
		System.out.println(formatter.parse(strDate));
	}
Copy the code

It really does get an error.

There was an official solution, but it was fixed in java9. Put it in the 8U version.

Fix yyyyMMddHHmmssSSS format not parsing

//LocalDateTimeUtil
/** * parses the date and time string as {@link LocalDateTime}
	 *
	 * @paramText Date time character string *@paramFormat The date format, similar to YYYY-MM-DD HH: MM :ss,SSS *@return {@link LocalDateTime}
	 */
	public static LocalDateTime parse(CharSequence text, String format) {... formatter =new DateTimeFormatterBuilder()
						.appendPattern(DatePattern.PURE_DATETIME_PATTERN)
						.appendValue(ChronoField.MILLI_OF_SECOND, 3) .toFormatter(); .return parse(text, formatter);
	}
Copy the code

Parse (text, formatter) is finally called;

/** * parses the date and time string as {@linkLocalDateTime}, the format can be date time, date, time * *@paramText Date time character string *@paramDate formatter, predefined format see: {@link DateTimeFormatter}
	 * @return {@link LocalDateTime}
	 */
	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));
	}
Copy the code

The first good habit is to check whether the input parameter is null.

LocalDateTime.parse(text)// Return the LocalDateTime object
DateTimeFormatter.parse(text)// Return the TemporalAccessor object
Copy the code

These are new apis for java8:

Swastika blog teaches you to understand Java source code date and time related usage

Finally, use **of(TemporalAccessor)** to convert to a LocalDateTime time object

First, TemporalAccessor:

The TemporalAccessor implementation class contains

  • Instant
  • LocalDateTime
  • ZonedDateTime
  • OffsetDateTime
  • LocalDate
  • LocalTime
  • OffsetTime
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)
		);
	}
Copy the code

First, we know from the above that LocalDate is the implementation class of temporalAccessor. ((LocalDate)temporalAccessor).atstartofDay () this will become localDate.atstartofDay ()

public LocalDateTime atStartOfDay(a) {
        return LocalDateTime.of(this, LocalTime.MIDNIGHT);
    }
Copy the code

LocalTime.MIDNIGHT:

 /** * The time of midnight at the start of the day, '00:00'. */
    public static final LocalTime MIDNIGHT;
Copy the code

LocalDateTime is a combination of LocalDate and LocalTime.

 public static LocalDateTime of(LocalDate date, LocalTime time) {
        Objects.requireNonNull(date, "date");
        Objects.requireNonNull(time, "time");
        return new LocalDateTime(date, time);
    }
Copy the code

TemporalAccessorUtil. Get (temporalAccessor, chronofield.year) this is hutool source, let’s have a look

	/** * Returns 0 ** if the attribute does not exist@paramTemporalAccessor Requires the acquisition of time objects *@paramField Specifies the property to obtain *@returnTime, which defaults to 0 */ if not available
	public static int get(TemporalAccessor temporalAccessor, TemporalField field) {
		if (temporalAccessor.isSupported(field)) {
			return temporalAccessor.get(field);
		}

		return (int)field.range().getMinimum();
	}
Copy the code

Determine whether temporalAccessor supports the specified fields, and if so, directly return the time value corresponding to the specified fields. If no, run the command

(int)field.range().getMinimum(), get the minimum value of the field.

		System.out.println(ChronoField.YEAR.range().getMinimum());
		System.out.println(ChronoField.MONTH_OF_YEAR.range().getMinimum());
		System.out.println(ChronoField.DAY_OF_MONTH.range().getMinimum());
		System.out.println(ChronoField.HOUR_OF_DAY.range().getMinimum());
		System.out.println(ChronoField.MINUTE_OF_HOUR.range().getMinimum());
		System.out.println(ChronoField.SECOND_OF_MINUTE.range().getMinimum());
		System.out.println(ChronoField.NANO_OF_SECOND.range().getMinimum());
Copy the code

Year specifies the minimum and maximum value set during initialization