Java date time format check and reset

…衆ロ難τιáo~ 提交于 2019-12-04 20:33:09

In Java 8, you can use a java.time.format.DateTimeFormatter with lots of optional sections - delimited by []:

DateTimeFormatter fmt = DateTimeFormatter
    .ofPattern("MM/dd/yyyy[ hh:mm[[:ss][ ]a]][HH:mm]", Locale.US);

If you want just to validate the inputs - and don't assign the result to a date/time variable - just calling parse is enough. This works for all the cases below:

fmt.parse("10/20/2018");
fmt.parse("10/20/2018 10:20");
fmt.parse("10/20/2018 10:20AM");
fmt.parse("10/20/2018 10:20 AM");
fmt.parse("10/20/2018 10:20:30AM");
fmt.parse("10/20/2018 10:20:30 AM");

If the input is invalid, it'll throw a DateTimeParseException.

Note that there's a difference between HH and hh. H is for hour-of-day (values between 0 and 23), while h is for clock-hour-of-am-pm (values between 1 and 12). H can't be with AM/PM designator, while h must have AM/PM to disambiguate it. That's why there are 2 different optional sections, one with each field.

I also use Locale.US because AM/PM strings are localized. Although for most locales, the result is "AM" or "PM", for some others it can be lowercase ("am"), or some other values (午後 in Japanese, for example).

If you don't set the locale, it uses the JVM default. But I prefer to set it a specific one that I know it'll work with the inputs I have.


To print those values again, with all the fields, it's a little bit tricky. The inputs can have only a date (day, month, year), or a date and time (day, month, year, hour, minute), so one alternative is to use a LocalDateTime (and set the missing fields when not present).

You can use parseBest and then check the type that was parsed:

// parse, try to create a LocalDateTime - if it's not possible, try a LocalDate
TemporalAccessor parsed = fmt.parseBest("10/20/2018", LocalDateTime::from, LocalDate::from);
LocalDateTime dt = null;
if (parsed instanceof LocalDateTime) {
    // LocalDateTime parsed (all fields set)
    dt = (LocalDateTime) parsed;
} else if (parsed instanceof LocalDate) {
    // LocalDate parsed (set time fields)
    dt = ((LocalDate) parsed)
        // set time (use whatever value you want - I'm using 10 AM as example)
        .atTime(LocalTime.of(10, 0));
}

Then you use another formatter for output - that's because the first formatter will print all the optional sections when formatting, so it'll print the hours twice. Just create another one and that's it:

DateTimeFormatter outputFmt = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a", Locale.US);
System.out.println(dt.format(outputFmt)); // 10/20/2018 10:00:00 AM
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!