问题
String is an input and i have to check whether it is in any of these formats. If it is in sdf1 format then pass, if it is in sdf2,3.... then i add the missing the format and parse it with sdf1 format
SimpleDateFormat sdf1 = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a");
SimpleDateFormat sdf2 = new SimpleDateFormat("MM/dd/yyyy hh:mm:ssa");
SimpleDateFormat sdf3 = new SimpleDateFormat("MM/dd/yyyy hh:mm a");
SimpleDateFormat sdf3 = new SimpleDateFormat("MM/dd/yyyy hh:mma");
SimpleDateFormat sdf3 = new SimpleDateFormat("MM/dd/yyyy hh:mm");
SimpleDateFormat sdf3 = new SimpleDateFormat("MM/dd/yyyy");
Here is what i have
try{
// Parse if it is MM/dd/yyyy hh:mm:ss a
cal = Calendar.getInstance();
cal.setTime(sdf1.parse(inStr));
}catch(Exception exp){
try{
cal = Calendar.getInstance();
//Parse if it is MM/dd/yyyy hh:mm:ssa
sdf2.parse(inStr);
inStr = new StringBuilder(inStr).insert(str.length()-2, " ").toString();
cal.setTime(sdf1.parse(inStr));
}catch(Exception dte2){
try{
cal = Calendar.getInstance();
//Parse if it is MM/dd/yyyy hh:mma
sdf3.parse(inStr);
//if pass then set 00:00:00 AM
inStr = inStr+" AM";
inStr = new StringBuilder(inStr).insert(str.length()-2, ":00").toString();
cal.setTime(sdf1.parse(inStr));
it keeps going like try parsing and if failed in exception block check for the next one. Is there any easy way to do this, may be in JAVA 8? i could use the link from marked as duplicate it talks about how to parse, but i have additional requirement as auto complete with missing format.
回答1:
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
来源:https://stackoverflow.com/questions/49678922/java-date-time-format-check-and-reset