Java 8日期验证 - 构建格式化程序

时间:2016-08-25 00:17:54

标签: validation date java-8

我正在尝试基于https://stackoverflow.com/a/32964692/829542 ...构建DateTimeFormatter以验证我的输入日期。我的逻辑要求以下格式有效

  1. YYYY-MM-dd'T'HH:MM:SS.SSSSSS
  2. yyyy-MM-dd HH:mm:ss.SSSSSS
  3. ...上述格式的微秒(SSSSSS)部分是可选的(或)如果微秒提供的数字比预期的6位数精度少 - 比如333而不是000333,我需要是能够填充,验证和处理日期。

    我正在使用DateTimeFormatter来构建一个自定义格式化程序并到达下面 -

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendPattern("yyyy")
                .appendLiteral('-')
                .appendValue(MONTH_OF_YEAR)
                .appendLiteral('-')
                .appendValue(DAY_OF_MONTH)
                .appendLiteral('T')
                .appendPattern(" HH:mm:ss")
                .appendPattern("[.SSSSSS]")
                .parseDefaulting(MICRO_OF_SECOND, MICRO_OF_SECOND.range().getMinimum())
                .toFormatter();
    

    但是,这不解析 - 例如“2016-08-04T20:43:30”作为有效日期,我也不知道如何填充数字。我看到DateTimeFormatter中有一个pad方法,但我不知道如何使用它们来获得所需的结果。我是唯一一个觉得有很多东西可以用Java Docs消费并跟随!!

    任何专家建议表示赞赏!

    更新1:

    基于@mtj的答案,能够扩展解决方案以涵盖大部分问题。现在唯一的待处理项目是制作否。日期中指定的微秒数,灵活宽度为0-6。现在,只有0和6位宽度有效。

    public class Test {
    
        public static void main(String[] args)
        {
            System.out.println("Date 1 - 2016-08-04T20:43:30 = " + Test.isValid("2016-08-04T20:43:30")); // true
            System.out.println("Date 2 - 2016-08-04 20:43:30 = " + Test.isValid("2016-08-04 23:43:30")); // true
    
            System.out.println("Date 3 - 2016-08-04T20:43:30.123121 = " + Test.isValid("2016-08-04T20:43:30.123121")); // true
            System.out.println("Date 4 - 2016-08-04 20:43:30.123131 = " + Test.isValid("2016-08-04 20:43:30.123131")); // true
    
            System.out.println("Date 5 - 2016-08-04'T'20:43:30.123121 = " + Test.isValid("2016-08-04'T'20:43:30.123121")); // true
    
            System.out.println("Date 6 - 2016-08-04'T' 20:43:30.123121 = " + Test.isValid("2016-08-04'T' 20:43:30.123121")); // false (as expected)
    
            System.out.println("Date 7 - 2016-08-04T20:43:30.123 = " + Test.isValid("2016-08-04T20:43:30.123")); // false
            System.out.println("Date 8 - 2016-08-04T20:43:30.123 = " + Test.isValid("2016-08-04 20:43:30.123")); // false
        }
    
        public static boolean isValid(String inputDate)
        {
            DateTimeFormatter charLiteralTFormat = getDateFormat()
                    .appendOptional(new DateTimeFormatterBuilder().appendLiteral("'").toFormatter())
                    .appendOptional(new DateTimeFormatterBuilder().appendLiteral('T').toFormatter())
                    .appendOptional(new DateTimeFormatterBuilder().appendLiteral("'").toFormatter())
                    .append(getTimeFormat().toFormatter())
                    .toFormatter();
    
            DateTimeFormatter spaceBtwnDttmFormat = getDateFormat()
                    .appendOptional(new DateTimeFormatterBuilder().appendLiteral(' ').toFormatter())
                    .append(getTimeFormat().toFormatter())
                    .toFormatter();
    
            DateTimeFormatter[] formatters = {
                    charLiteralTFormat, spaceBtwnDttmFormat};
    
            for(DateTimeFormatter formatter : formatters) {
                try {
                    LocalDate.parse(inputDate, formatter);
                    return true;
                } catch (DateTimeParseException e) {
                    //System.out.println(" Invalid Date ... ");
                }
            }
    
            return false;
        }
    
        public static DateTimeFormatterBuilder getDateFormat(){
            DateTimeFormatterBuilder baseFormat = new DateTimeFormatterBuilder()
                    .appendPattern("yyyy")
                    .appendLiteral('-')
                    .appendValue(MONTH_OF_YEAR)
                    .appendLiteral('-')
                    .appendValue(DAY_OF_MONTH);
    
            return baseFormat;
        }
    
        public static DateTimeFormatterBuilder getTimeFormat() {
            DateTimeFormatterBuilder timeFormat = new DateTimeFormatterBuilder()
                    .appendPattern("HH:mm:ss")
                    .appendOptional(new DateTimeFormatterBuilder().appendLiteral('.').toFormatter())
                    .appendOptional(new DateTimeFormatterBuilder().appendValue(ChronoField.MICRO_OF_SECOND,6).toFormatter());
    
            return timeFormat;
        }
    }
    

    输出

    // Output - 
    // Validation going as expected
    Date 1 - 2016-08-04T20:43:30 = true
    Date 2 - 2016-08-04 20:43:30 = true
    Date 3 - 2016-08-04T20:43:30.123121 = true
    Date 4 - 2016-08-04 20:43:30.123131 = true
    Date 5 - 2016-08-04'T'20:43:30.123121 = true
    Date 6 - 2016-08-04'T' 20:43:30.123121 = false
    
    // Output - 
    // Validation NOT going as expected
    Date 7 - 2016-08-04T20:43:30.123 = false
    Date 8 - 2016-08-04T20:43:30.123 = false
    

1 个答案:

答案 0 :(得分:0)

您发布的示例和输入的问题是小时之前的空白。删除它,它可以工作。

但请注意,这将解析您需要的两种模式。

我猜,以下内容将更接近您的要求,即使它会接受“T' T'并且应该是非法的空白:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .appendPattern("yyyy")
        .appendLiteral('-')
        .appendValue(ChronoField.MONTH_OF_YEAR)
        .appendLiteral('-')
        .appendValue(ChronoField.DAY_OF_MONTH)
        .appendOptional(new DateTimeFormatterBuilder().appendLiteral('T').toFormatter())
        .appendOptional(new DateTimeFormatterBuilder().appendLiteral(' ').toFormatter())
        .appendPattern("HH:mm:ss")
        .appendOptional(new DateTimeFormatterBuilder().appendPattern(".SSSSSS").toFormatter())
        .toFormatter();