This is the 9th 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

4hutool :DateUtil- Format time


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. FormatLocalDateTime (Java. Time. LocalDateTime)

Methods described

Format date time <br> Format YYYY-MM-DD HH: MM: SS

Source code Analysis 1

	/** * Format date time <br> * Format YYYY-MM-DD HH: MM :ss **@paramLocalDateTime Formatted date *@returnThe formatted character string */
	public static String formatLocalDateTime(LocalDateTime localDateTime) {
		return LocalDateTimeUtil.formatNormal(localDateTime);
	}
Copy the code

First, the formatLocalDateTime method takes an input parameter of LocalDateTime.

Then call LocalDateTimeUtil. FormatNormal (localDateTime)

//LocalDateTimeUtil
	/** * Format the date and time in yyyY-MM-DD HH: MM :ss format **@param time      {@link LocalDateTime}
	 * @returnFormatted string *@since5.3.11 * /
	public static String formatNormal(LocalDateTime time) {
		return format(time, DatePattern.NORM_DATETIME_FORMATTER);
	}
	/** * Format the date and time in the specified format **@param time      {@link LocalDateTime}
	 * @paramDate formatter, predefined format see: {@link DateTimeFormatter}
	 * @returnThe formatted character string */
	public static String format(LocalDateTime time, DateTimeFormatter formatter) {
		return TemporalAccessorUtil.format(time, formatter);
	}
Copy the code

NORM_DATETIME_FORMATTER datepattern. NORM_DATETIME_FORMATTER date-time format:

/** * Standard date and time format, accurate to seconds: YYYY-MM-DD HH: MM :ss */
public static final String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
Copy the code

And then it callsformat(LocalDateTime time, DateTimeFormatter formatter)The DateTimeFormatter class is supported by Java8, which is thread-safe.

Hutool makes a good example here of replacing SimpleDateFormat (thread-unsafe) with DateTimeFormatter.

Why SimpleDateFormat is not thread-safe

Then we continue to dig down TemporalAccessorUtil. The format (time, formatter)

/** * Format the date and time in the specified format **@param time      {@link TemporalAccessor}
 * @paramDate formatter, predefined format see: {@link DateTimeFormatter}
 * @returnFormatted string *@since5.3.10 * /
public static String format(TemporalAccessor time, DateTimeFormatter formatter) {
   if (null == time) {
      return null;
   }

   if(null == formatter){
      formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
   }


   try {
      return formatter.format(time);
   } catch (UnsupportedTemporalTypeException e){
      if(time instanceof LocalDate && e.getMessage().contains("HourOfDay")) {// The user passes in LocalDate, but requires formatting with a time part. Convert to LocalDateTime and retry
         return formatter.format(((LocalDate) time).atStartOfDay());
      }else if(time instanceof LocalTime && e.getMessage().contains("YearOfEra")) {// The user passes in LocalTime, but asks for formatting with the date part, converts to LocalDateTime and tries again
         return formatter.format(((LocalTime) time).atDate(LocalDate.now()));
      }
      throwe; }}Copy the code

If time is null, null is returned. If formatter is null, give the format default value, eg:2011-12-03T10:15:30

Format (time) is equivalent to datetimeFormatter. format(LocalDateTime). This formatting succeeds.

Worthy of mention is * * TemporalAccessorUtil. The format (TemporalAccessor time, DateTimeFormatter formatter) * * add exception handling mechanism inside

 try {
      return formatter.format(time);
   } catch (UnsupportedTemporalTypeException e){
      if(time instanceof LocalDate && e.getMessage().contains("HourOfDay")) {// The user passes in LocalDate, but requires formatting with a time part. Convert to LocalDateTime and retry
         return formatter.format(((LocalDate) time).atStartOfDay());
      }else if(time instanceof LocalTime && e.getMessage().contains("YearOfEra")) {// The user passes in LocalTime, but asks for formatting with the date part, converts to LocalDateTime and tries again
         return formatter.format(((LocalTime) time).atDate(LocalDate.now()));
      }
      throw e;
   }
Copy the code

Because the implementation classes of TemporalAccessor Time are commonly used as follows (provided by Java8) :

  • LocalDateTime
  • LocalDate
  • LocalTime

When performing date-time conversion, the date-time must correspond to the formatted string to be converted, otherwise an exception will be thrown, so the above remedy is made.

Format (java.time.localdatetime, java.lang.string)

Methods described

Format the date according to a specific format

Source code Analysis 1

/** * Formats the date according to a specific format **@paramLocalDateTime Formatted date *@paramFormat Date format. The common format is: {@link DatePattern}
 * @returnThe formatted character string */
public static String format(LocalDateTime localDateTime, String format) {
   return LocalDateTimeUtil.format(localDateTime, format);
}
Copy the code

First: Hutool provides common date-time formats

/** * date formatting class, which provides the common date formatting object ** /
public class DatePattern {... }Copy the code

Then: call localDateTimeUtil. format(localDateTime, format)

/** * Format the date and time in the specified format **@param time   {@link LocalDateTime}
 * @paramFormat The date format, similar to YYYY-MM-DD HH: MM :ss,SSS *@returnThe formatted character string */
public static String format(LocalDateTime time, String format) {
   if (null == time) {
      return null;
   }
   return format(time, DateTimeFormatter.ofPattern(format));
}
Copy the code

Source format * * (time, DateTimeFormatter ofPattern (format)) * * can be disassembled into two parts:

  • DateTimeFormatter.ofPattern(format)

  • format(LocalDateTime time, DateTimeFormatter formatter)

The first part: * * DateTimeFormatter ofPattern (format) * * is to put the date/time format string into the date/time formatting objects DateTimeFormatter;

Note DateTimeFormatter ofPattern (format) usage is the pit (post code explanation — > a swastika teach you understand Java source code date and time of the related usage) :

  1. In normal configuration, string dates in standard format can be converted normally. If the value of month, day, hour, minute, or second is less than two digits, the conversion will fail and an exception will be thrown.
  2. Use YYYY and DD with caution

Format (LocalDateTime time, DateTimeFormatter formatter)

Dateutil. format(java.util.Date, java.text.dateformat)

Methods described

Format the date according to a specific format

Source code Analysis 1

/** * Formats the date according to a specific format **@paramDate Formatted date *@paramFormat Date format. The common format is: {@link DatePattern}
 * @returnThe formatted character string */
public static String format(Date date, String format) {
   if (null == date || StrUtil.isBlank(format)) {
      return null;
   }

   TimeZone timeZone = null;
   if (date instanceof DateTime) {
      timeZone = ((DateTime) date).getTimeZone();
   }
   return format(date, newSimpleFormat(format, null, timeZone));
}
Copy the code

From the code, the **format(Date Date, String format)** method provides two input arguments, a formatted Date of type Date and a String to format the Date. This is to be compatible with the methods provided by the older date-time API prior to java8.

Two parameters are nulled in the method.

Then determine if the time is a Hutool DateTime object, and if so, get the TimeZone

Then call format(date, newSimpleFormat(format, NULL, timeZone)), which can be split into two parts:

  • NewSimpleFormat (format, NULL, timeZone), get SimpleDateFormat object (note: this method is not thread-safe)

  • Format (Date Date, DateFormat format) Formats a Date based on a specific format

**newSimpleFormat(format, NULL, timeZone)

/** * create {@linkSimpleDateFormat}, note that this object is not thread-safe! <br> * This object defaults to strictly formatted mode, meaning that parse will report an error if it is incorrectly formatted. * *@paramPattern expression *@param locale   {@linkThe Locale}, {@codeNull} indicates the default *@param timeZone {@linkTimeZone}, {@codeNull} indicates the default *@return {@link SimpleDateFormat}
 * @since5.5.5 * /
public static SimpleDateFormat newSimpleFormat(String pattern, Locale locale, TimeZone timeZone) {
   if (null == locale) {
      locale = Locale.getDefault(Locale.Category.FORMAT);
   }
   final SimpleDateFormat format = new SimpleDateFormat(pattern, locale);
   if (null! = timeZone) { format.setTimeZone(timeZone); } format.setLenient(false);
   return format;
}
Copy the code

If **format(Date Date, String format) specifies the time of the Date object, then format(Date, newSimpleFormat(format, NULL, timeZone))** would look like this: Format(date, newSimpleFormat(format, NULL, null)).

// Get the current locale
locale = Locale.getDefault(Locale.Category.FORMAT);
Copy the code

Then a SimpleDateFormat object is new. And set the time zone and set setLenient, which means whether or not to parse dates strictly. When setLenient is set to false, dates are strictly parsed: the date and time format is strictly adhered to, and Java does not help with calculations, throwing exceptions.

**format(Date Date, DateFormat format) **

/** * Formats the date according to a specific format **@paramDate Formatted date *@param format {@link SimpleDateFormat}
 * @returnThe formatted character string */
public static String format(Date date, DateFormat format) {
   if (null == format || null == date) {
      return null;
   }
   return format.format(date);
}
Copy the code

Two input parameters are nulled. Then call simpledateformat.format (date), which was provided before java8.

Method name: DateUtil. The format (Java. Util. Date, Java. Time. The format. The DateTimeFormatter) (method has a problem, have feedback, authorities have revised)

Methods described

Format the date according to a specific format

Source code Analysis 1

/** * Formats the date according to a specific format **@paramDate Formatted date *@param format {@link DateTimeFormatter}
 * @returnFormatted string *@since5.0.0 * /
public static String format(Date date, DateTimeFormatter format) {
   if (null == format || null == date) {
      return null;
   }
   return format.format(date.toInstant());
}
Copy the code

First, two input parameters are nulled.

Then, format.format(date.toinstant ()) is executed, and the code can be broken into two parts:

  • Date.toinstant (): Returns an Instant object
  • Datetimeformatter. format(Instant) : method of formatting date and time provided by java8

How does the code ** dateTimeFormatter.format (Instant)** handle?

    public String format(TemporalAccessor temporal) {
        StringBuilder buf = new StringBuilder(32);
        formatTo(temporal, buf);
        return buf.toString();
    }


Copy the code

First, we create a StringBuilder object to concatenate strings;

Then call the **formatTo(temporal, buf)** method

public void formatTo(TemporalAccessor temporal, Appendable appendable) {
    Objects.requireNonNull(temporal, "temporal");
    Objects.requireNonNull(appendable, "appendable");
    try {
        DateTimePrintContext context = new DateTimePrintContext(temporal, this);
        if (appendable instanceof StringBuilder) {
            printerParser.format(context, (StringBuilder) appendable);
        } else {
            // buffer output to avoid writing to appendable in case of error
            StringBuilder buf = new StringBuilder(32); printerParser.format(context, buf); appendable.append(buf); }}catch (IOException ex) {
        throw newDateTimeException(ex.getMessage(), ex); }}Copy the code

FormatTo (temporal, buf);

The Instant object is then wrapped in a new DateTimePrintContext object

Troubleshoot demo running problems

		// Format the date according to a specific format
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		String dateStr = DateUtil.format(new Date(),dtf);
		System.out.println(dateStr);
Copy the code

Datetimeformatter.format is the JDK source

From the above knowable, invoked NumberPrinterParser. Format () NumberPrinterParser is in DateTimeFormatterBuilder in the class.

You get an error at this point

Let’s see what happens to context.getValue(field) :

The above code makes sense, temporal is actually an Instant object, and Instant. GetLong only supports four field types.

NANO_OF_SECOND
MICRO_OF_SECOND
MILLI_OF_SECOND
INSTANT_SECONDS
Copy the code

If none of the above field types is present, an exception is thrown

Dateutil. format Converts the Date object to Instant when DateTimeFormatter is encountered.

Suggest other way

/** * Formats the date according to a specific format **@paramDate Formatted date *@param format
 * @returnFormatted string *@since5.0.0 * /
public static String format(Date date, DateTimeFormatter format) {
   if (null == format || null == date) {
      return null;
   }
   Instant instant = date.toInstant();
  
   ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
   LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
   return format.format(localDateTime);
}
Copy the code

Format dateTimeFormatter. format(LocalDateTime)

Test the demo

// Format the date according to a specific format
String str = "The 2021-07-25 20:11:25";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:dd");
Date date = DateUtil.parse(str);
String dateStr = DateUtil.format(date,dtf);
System.out.println(dateStr);
Assert.assertEquals(str, dateStr);
Copy the code

Other official

Updated in version #5.7.5

/** * Formats the date according to a specific format **@paramDate Formatted date *@param format {@link SimpleDateFormat} {@link DatePattern#NORM_DATETIME_FORMATTER}
 * @returnFormatted string *@since5.0.0 * /
public static String format(Date date, DateTimeFormatter format) {
   if (null == format || null == date) {
      return null;
   }
   // java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfEra
   // If the preceding error occurs, the Instant timestamp has no time zone information, and the default time zone is assigned
   return TemporalAccessorUtil.format(date.toInstant(), format);
}
Copy the code

Replaced the new method is called TemporalAccessorUtil. The format (date. ToInstant (), the format), date. ToInstant () returns the Instant, Is turned into TemporalAccessorUtil. The format (Instant, format)

//TemporalAccessorUtil
	/** * Format the date and time in the specified format **@param time      {@link TemporalAccessor}
	 * @paramDate formatter, predefined format see: {@link DateTimeFormatter}
	 * @returnFormatted string *@since5.3.10 * /
	public static String format(TemporalAccessor time, DateTimeFormatter formatter) {
		if (null == time) {
			return null;
		}

		if(null == formatter){
			formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
		}

		try {
			return formatter.format(time);
		} catch (UnsupportedTemporalTypeException e){
			if(time instanceof LocalDate && e.getMessage().contains("HourOfDay")) {// The user passes in LocalDate, but requires formatting with a time part. Convert to LocalDateTime and retry
				return formatter.format(((LocalDate) time).atStartOfDay());
			}else if(time instanceof LocalTime && e.getMessage().contains("YearOfEra")) {// The user passes in LocalTime, but asks for formatting with the date part, converts to LocalDateTime and tries again
				return formatter.format(((LocalTime) time).atDate(LocalDate.now()));
			} else if(time instanceof Instant){
				// The timestamp has no time zone information
				return formatter.format(((Instant) time).atZone(ZoneId.systemDefault()));
			}
			throwe; }}Copy the code

– Added a default time zone when time is Instant

else if(time instanceof Instant){
   // The timestamp has no time zone information
   return formatter.format(((Instant) time).atZone(ZoneId.systemDefault()));
}
Copy the code

Dateutil. formatDateTime(java.util.date)

Methods described

Format date time <br> Format YYYY-MM-DD HH: MM: SS

Source code Analysis 1

/** * Format date time <br> * Format YYYY-MM-DD HH: MM :ss **@paramDate Formatted date *@returnFormatted date */
public static String formatDateTime(Date date) {
   if (null == date) {
      return null;
   }
   return DatePattern.NORM_DATETIME_FORMAT.format(date);
}
Copy the code

First of all, it is a good habit to judge the null processing of the input parameter

Datepattern.norm_datetime_format.format (date) is then called to return the FastDateFormat object

For java8 only before the program, you can use FastDateFormat thread safety replace SimpleDateFormat thread is not safe — “source analysis

FastDateFormat is a thread-safe implementation source from Apache Commons Lang 3.5Copy the code
DatePattern.NORM_DATETIME_FORMAT-->	
/** * Standard date-time format, accurate to seconds {@linkFastDateFormat} : YYYY-MM-DD HH: MM :ss */
	public static final FastDateFormat NORM_DATETIME_FORMAT = FastDateFormat.getInstance(NORM_DATETIME_PATTERN);
Copy the code

Is converted toFastDateFormat.format(date)

//FastDateFormat
@Override
public String format(final Date date) {
   return printer.format(date);
}

//FastDatePrinter	
@Override
public String format(final Date date) {
    final Calendar c = Calendar.getInstance(timeZone, locale);
    c.setTime(date);
    return applyRulesToString(c);
}
Copy the code

First, convert date to Calendar so that you can easily obtain the date and time

private String applyRulesToString(final Calendar c) {
   return applyRules(c, new StringBuilder(mMaxLengthEstimate)).toString();
}

	private <B extends Appendable> B applyRules(final Calendar calendar, final B buf) {
		try {
			for (final Rule rule : this.rules) { rule.appendTo(buf, calendar); }}catch (final IOException e) {
			throw new DateException(e);
		}
		return buf;
	}
Copy the code

The core code is this

for (final Rule rule : this.rules) {
				rule.appendTo(buf, calendar);
			}
Copy the code

Test the demo

String dateStr = "2017-03-01";
Date date = DateUtil.parse(dateStr);
String formatDateTime = DateUtil.formatDateTime(date);
Assert.assertEquals("The 2017-03-01 00:00:00", formatDateTime);
Copy the code

Breakpoint tracking code:

Follow the code

//FastDatePrinter
private static class PaddedNumberField implements NumberRule {...@Override
		public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
			appendTo(buffer, calendar.get(mField));
		}

		/ * * * {@inheritDoc} * /
		@Override
		public final void appendTo(final Appendable buffer, final int value) throws IOException {
			appendFullDigits(buffer, value, mSize);
		} 
        
    ...}
Copy the code

The year is already set: 2017

Follow the code below:

//FastDatePrinter
	private static class CharacterLiteral implements Rule {...@Override
		public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { buffer.append(mValue); }... }Copy the code

Just concatenate the ‘-‘ string.

Next fetch month:

//FastDatePrinter
private static class TwoDigitMonthField implements NumberRule {.../ * * * {@inheritDoc} * /
		@Override
		public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
			appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
		}

		/ * * * {@inheritDoc} * /
		@Override
		public final void appendTo(final Appendable buffer, final int value) throws IOException { appendDigits(buffer, value); }... }Copy the code

Get month: 3

Next: concatenate the ‘-‘ string directly.

Keep following

//FastDatePrinter
private static class TwoDigitNumberField implements NumberRule {...@Override
		public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
			appendTo(buffer, calendar.get(mField));
		}

		/ * * * {@inheritDoc} * /
		@Override
		public final void appendTo(final Appendable buffer, final int value) throws IOException {
			if (value < 100) {
				appendDigits(buffer, value);
			} else {
				appendFullDigits(buffer, value, 2); }}... }Copy the code

Date obtained: 2017-03-01

Then we add a space string

Time and second calls, all call the same FastDatePrinter#TwoDigitNumberField.

//FastDatePrinter
private static class TwoDigitNumberField implements NumberRule {...@Override
		public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
			appendTo(buffer, calendar.get(mField));
		}

		/ * * * {@inheritDoc} * /
		@Override
		public final void appendTo(final Appendable buffer, final int value) throws IOException {
			if (value < 100) {
				appendDigits(buffer, value);
			} else {
				appendFullDigits(buffer, value, 2); }}... }Copy the code

So you get “2017-03-01 00:00:00”

Dateutil. formatDate(java.util.date)

Methods described

Format the date part (excluding time) <br> format YYYY-MM-DD

Source code Analysis 1

/** * Format the date part (excluding the time) <br> * Format YYYY-MM-DD **@paramDate Formatted date *@returnThe formatted character string */
public static String formatDate(Date date) {
   if (null == date) {
      return null;
   }
   return DatePattern.NORM_DATE_FORMAT.format(date);
}
Copy the code

First of all, it is a good habit to judge the null processing of the input parameter

Datepattern.norm_date_format.format (date) is then called to return the FastDateFormat object

For java8 only before the program, you can use FastDateFormat thread safety replace SimpleDateFormat thread is not safe — “source analysis

FastDateFormat is a thread-safe implementation source from Apache Commons Lang 3.5Copy the code
	/** * Standard date format {@linkFastDateFormat} : yyyy - MM - dd * /
	public static final FastDateFormat NORM_DATE_FORMAT = FastDateFormat.getInstance(NORM_DATE_PATTERN);
Copy the code

Convert to fastDateformat.format (date), source analysis see above

Dateutil. formatTime(java.util.date)

Methods described

Format time <br> Format HH:mm: SS

Source code Analysis 1

/** * Format time <br> * Format HH:mm:ss **@paramDate Formatted date *@returnFormatted string *@since3.0.1 * /
public static String formatTime(Date date) {
   if (null == date) {
      return null;
   }
   return DatePattern.NORM_TIME_FORMAT.format(date);
}
Copy the code

First of all, it is a good habit to judge the null processing of the input parameter

Datepattern.norm_time_format.format (date) is then called to return the FastDateFormat object

For java8 only before the program, you can use FastDateFormat thread safety replace SimpleDateFormat thread is not safe — “source analysis

FastDateFormat is a thread-safe implementation source from Apache Commons Lang 3.5Copy the code
	/** * Standard time format {@linkFastDateFormat} : HH: mm: ss * /
	public static final FastDateFormat NORM_TIME_FORMAT = FastDateFormat.getInstance(NORM_TIME_PATTERN);
Copy the code

Convert to fastDateformat.format (date), source analysis see above

Dateutil.formathttpdate (java.util.date)

Methods described

The standard date format follows the RFC 1123 specification in a format similar to: Fri, 31 Dec 1999 23:59:59 GMT

Source code Analysis 1

* The standard date format follows the RFC 1123 specification in a format similar to: Fri, 31 Dec 1999 23:59:59 GMT **@paramDate Formatted date *@returnHTTP Standard date string */
public static String formatHttpDate(Date date) {
   if (null == date) {
      return null;
   }
   return DatePattern.HTTP_DATETIME_FORMAT.format(date);
}
Copy the code

First of all, it is a good habit to judge the null processing of the input parameter

Then call datepattern.http_datetime_format.format (date) to return the FastDateFormat object

For java8 only before the program, you can use FastDateFormat thread safety replace SimpleDateFormat thread is not safe — “source analysis

FastDateFormat is a thread-safe implementation source from Apache Commons Lang 3.5Copy the code
	/** * HTTP header date-time format {@linkFastDateFormat} : EEE, dd MMM YYYY HH:mm:ss z */
	public static final FastDateFormat HTTP_DATETIME_FORMAT = FastDateFormat.getInstance(HTTP_DATETIME_PATTERN, TimeZone.getTimeZone("GMT"), Locale.US);
Copy the code

Convert to fastDateformat.format (date), source analysis see above

Method name: DateUtil formatChineseDate (Java. Util. Date, Boolean, Boolean)

Methods described

Format to Chinese date format, if isUppercase is false, return similar to October 24, 2018, otherwise Return October 24, 2018

Source code Analysis 1

If isUppercase is false, return something like October 24, 2018, otherwise Return October 24, 2018@paramDate Formatted date *@paramIsUppercase Specifies whether to use uppercase *@paramWithTime contains the time part *@returnChinese date string *@since5.3.9 * /
public static String formatChineseDate(Date date, boolean isUppercase, boolean withTime) {
   if (null == date) {
      return null;
   }

   if (false == isUppercase) {
      return (withTime ? DatePattern.CHINESE_DATE_TIME_FORMAT : DatePattern.CHINESE_DATE_FORMAT).format(date);
   }

   return CalendarUtil.formatChineseDate(CalendarUtil.calendar(date), withTime);
}
Copy the code

First of all, it is a good habit to judge the null processing of the input parameter

When not capitalized

Perform * * (withTime? DatePattern.CHINESE_DATE_TIME_FORMAT : DatePattern.CHINESE_DATE_FORMAT).format(date)**

Datepattern.chinese_date_time_format. format(date) if the time part is included. If the time part is not included, Call the DatePattern. CHINESE_DATE_FORMAT. The format (date)

/** * Standard date format {@linkFastDateFormat: YYYY Year MM month DD day HH MM minute ss second */
public static final FastDateFormat CHINESE_DATE_TIME_FORMAT = FastDateFormat.getInstance(CHINESE_DATE_TIME_PATTERN);

	/** * Standard date format {@linkFastDateFormat: YYYY Year MM month DD */
	public static final FastDateFormat CHINESE_DATE_FORMAT = FastDateFormat.getInstance(CHINESE_DATE_PATTERN);
Copy the code

As you can see from the source code above, both return FastDateFormat objects.

For java8 only before the program, you can use FastDateFormat thread safety replace SimpleDateFormat thread is not safe — “source analysis

FastDateFormat is a thread-safe implementation source from Apache Commons Lang 3.5Copy the code
	/** * HTTP header date-time format {@linkFastDateFormat} : EEE, dd MMM YYYY HH:mm:ss z */
	public static final FastDateFormat HTTP_DATETIME_FORMAT = FastDateFormat.getInstance(HTTP_DATETIME_PATTERN, TimeZone.getTimeZone("GMT"), Locale.US);
Copy the code

Convert to fastDateformat.format (date), source analysis see above

When you use uppercase

Perform CalendarUtil. FormatChineseDate (CalendarUtil. The calendar (date), withTime);

Can be broken down into two parts:

  • CalendarUtil. Calendar (Date): Converts date objects to calendar objects

  • CalendarUtil. FormatChineseDate (Calendar Calendar, Boolean withTime) : specifies the Calendar time formatted into pure Chinese form, for example

    2018-02-24 12:13:14 convert to February 24, 2018 (withTime is false) 2018-02-24 12:13:14 convert to February 24, 2018 12:13 minutes 14 seconds (withTime is true)Copy the code

Calendarutil. calendar(Date)

/** * converts to Calendar object **@paramDate Date object *@returnThe Calendar object * /
public static Calendar calendar(Date date) {
   if (date instanceof DateTime) {
      return ((DateTime) date).toCalendar();
   } else {
      returncalendar(date.getTime()); }}Copy the code

If the DateTime type is provided by Hutool, it can be directly converted to obtain.

If it is of the date type, it is converted to a Calendar object by * cal.setTimeInmillis.

/** * converts to Calendar object **@paramMillis timestamp *@returnThe Calendar object * /
public static Calendar calendar(long millis) {
   final Calendar cal = Calendar.getInstance();
   cal.setTimeInMillis(millis);
   return cal;
}
Copy the code

Some of you will find that this is not the same as the calendar. setTime(Date Date) that we usually use. Look at the source code

//Calendar
public final void setTime(Date date) {
    setTimeInMillis(date.getTime());
}
Copy the code

It’s essentially the same thing. SetTimeInMillis is also called in the setTime method.

CalendarUtil. FormatChineseDate (Calendar Calendar, Boolean withTime) source code analysis:

/** * Format the specified Calendar time in pure Chinese, for example: * * <pre> * 2018-02-24 12:13:14 convert to 2018-02-24 12:13:14 (withTime is false) * 2018-02-24 12:13:14 convert to 2018-02-24 12:13:14 February 24/12/13/14sec (withTime is true) * </pre> * *@param calendar {@link Calendar}
 * @paramWithTime contains the time part *@returnFormatted string *@since5.3.9 * /
public static String formatChineseDate(Calendar calendar, boolean withTime) {
   final StringBuilder result = StrUtil.builder();

   / / year
   String year = String.valueOf(calendar.get(Calendar.YEAR));
   final int length = year.length();
   for (int i = 0; i < length; i++) {
      result.append(NumberChineseFormatter.numberCharToChinese(year.charAt(i), false));
   }
   result.append('years');

   / / month
   int month = calendar.get(Calendar.MONTH) + 1;
   result.append(NumberChineseFormatter.format(month, false));
   result.append('month');

   / /,
   int day = calendar.get(Calendar.DAY_OF_MONTH);
   result.append(NumberChineseFormatter.format(day, false));
   result.append('day');

   if (withTime) {
      / /
      int hour = calendar.get(Calendar.HOUR_OF_DAY);
      result.append(NumberChineseFormatter.format(hour, false));
      result.append('when');
      / / points
      int minute = calendar.get(Calendar.MINUTE);
      result.append(NumberChineseFormatter.format(minute, false));
      result.append('points');
      / / SEC.
      int second = calendar.get(Calendar.SECOND);
      result.append(NumberChineseFormatter.format(second, false));
      result.append('秒');
   }

   return result.toString().replace('zero'.'〇');
}
Copy the code

According to the source code, it is converted by year, month, day, minute, second, each field.