Java日期时间格式检查和重置

Pat*_*Pat 1 java datetime datetime-parsing java-8

字符串是一个输入,我必须检查它是否是这些格式中的任何一种.如果它是sdf1格式然后传递,如果它在sdf2,3 ....然后我添加缺少格式并用sdf1格式解析它

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"); 
Run Code Online (Sandbox Code Playgroud)

这就是我所拥有的

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));
Run Code Online (Sandbox Code Playgroud)

它继续像尝试解析一样,如果在异常块检查中失败则检查下一个.有没有简单的方法可以做到这一点,可能在JAVA 8?我可以使用标记为重复的链接,它谈论如何解析,但我有额外的要求作为自动完成与缺少格式.

q11*_*112 5

在Java 8中,您可以使用java.time.format.DateTimeFormatter包含许多可选部分的部分 - 由[]以下分隔:

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

如果您只想验证输入 - 并且不将结果分配给日期/时间变量 - 只需调用即可parse.这适用于以下所有情况:

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");
Run Code Online (Sandbox Code Playgroud)

如果输入无效,它将抛出一个DateTimeParseException.

请注意,之间存在差异HHhh.H表示每小时(0到23之间的值),h而是上午时钟小时(1到12之间的值).H不能与AM/PM指示符一起使用,同时h必须有AM/PM来消除它的歧义.这就是为什么有2个不同的可选部分,每个部分都有一个.

我也使用,Locale.US因为AM/PM字符串是本地化的.虽然对于大多数语言环境,结果是"AM"或"PM",但对于其他语言环境,它可以是小写("am")或其他一些值(??例如日语).

如果未设置区域设置,则使用JVM默认值.但我更喜欢将它设置为一个特定的,我知道它将与我的输入一起工作.


要使用所有字段再次打印这些值,这有点棘手.输入可以只有一个日期(日,月,年),或日期和时间(日,月,年,小时,分钟),因此一种方法是使用a LocalDateTime(并在不存在时设置缺少的字段).

您可以使用parseBest然后检查已解析的类型:

// 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));
}
Run Code Online (Sandbox Code Playgroud)

然后你使用另一个格式化程序输出 - 这是因为第一个格式化程序将在格式化时打印所有可选部分,因此它会打印两个小时.只需创建另一个,就是这样:

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
Run Code Online (Sandbox Code Playgroud)