有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java验证从csv获取的正确日期时间格式

我需要读取一个csv文件,它在一个时间戳列中具有不同的时间格式。它可以是下面提到的5种格式中的任何一种。我需要匹配获取的日期,并对每一行进行相应的解析。 请建议如何验证广告解析它。提前谢谢

public static final String DEFAULT_DATE_FORMAT_PATTERN = "yyyy-MM-dd";
public static final String DEFAULT_DATE_TIME_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";
public static final String DATE_TIME_MINUTES_ONLY_FORMAT_PATTERN = "yyyy-MM-dd HH:mm";
public static final String DATE_TIME_WITHOUT_MILLIS_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss";
Epoch in milli

共 (2) 个答案

  1. # 1 楼答案

    暴力方法:

    • 只需尝试4种格式,一种接一种地解析传入字符串
    • 如果解析引发异常,请尝试下一个异常
    • 如果解析通过,那么格式正好匹配

    当然,如果我们谈论的是更大的桌子,这是相当低效的。可能的优化:

    • 显然,不同的模式有细微的差异,因此可以首先使用indexOf()检查。Like:如果要分析的值不包含':'字符,那么它只能是第一个模式
    • 您可以手动查看数据,以了解所使用模式的实际分布情况。然后调整模式的顺序,以尝试在数据中使用该模式的可能性

    或者:您可以定义自己的正则表达式。唯一让它有点难看的是,您的输入使用的是月份名称,而不是月份编号。但我认为编写一个涵盖所有案例的正则表达式应该不会太难

  2. # 2 楼答案

    您需要的是一个具有可选部分的格式化程序。模式可以包含方括号来表示可选部分,例如HH:mm[:ss]。然后,格式化程序需要解析HH:mm,并尝试将以下文本解析为:ss,如果解析失败,则跳过它yyyy-MM-dd[ HH:mm[:ss[.SSS]]]将成为模式

    这里只有一个问题–当您尝试使用LocalDateTime::parse解析带有模式yyyy-MM-dd(因此没有时间部分)的字符串时,它将抛出一个DateTimeFormatException,消息是无法从TemporalAccessor获取LocalDateTime。显然,至少要有一个时间段才能成功

    幸运的是,我们可以使用DateTimeFormatterBuilder来构建模式,指示格式化程序在解析文本中缺少信息时使用一些默认值。这是:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .appendPattern("yyyy-MM-dd[ HH:mm[:ss[.SSS]]]")
        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
        .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
        .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
        .toFormatter();
    LocalDateTime dateTime = LocalDateTime.parse(input, formatter);
    

    测试:

    String[] inputs = {
        "2020-10-22", // OK
        "2020-10-22 14:55", // OK
        "2020-10-22T14:55", // Fails: incorrect format
        "2020-10-22 14:55:23",
        "2020-10-22 14:55:23.9", // Fails: incorrect fraction of second
        "2020-10-22 14:55:23.91", // Fails: incorrect fraction of second
        "2020-10-22 14:55:23.917", // OK
        "2020-10-22 14:55:23.9174", // Fails: incorrect fraction of second
        "2020-10-22 14:55:23.917428511" // Fails: incorrect fraction of second 
    };
    

    那以毫为单位的纪元呢

    嗯,这不能由DateTimeFormatter直接解析。但更重要的是:以毫为单位的纪元有一个隐含的时区:UTC。其他模式缺少时区。因此,一个时代是一条根本不同的信息。您可以做的一件事是假设输入缺少一个时区

    但是,如果您仍然希望解析该瞬间,可以尝试使用Long::parseLong将其解析为long,如果解析失败,则尝试使用格式化程序进行解析。或者,您可以使用正则表达式(如-?\d+或其他东西)尝试匹配瞬间,如果匹配,则作为瞬间进行解析,如果失败,则尝试使用上述格式化程序进行解析