【问题标题】:Parsing a date in Java?用Java解析日期?
【发布时间】:2019-09-17 17:50:50
【问题描述】:

我有 dd-mmm-yy 或 d-mmm-y 形式的文本格式的日期,其中月份是字母的缩写(例如,2009 年 11 月 4 日或 05 年 12 月 12 日等... ) 我想解析它以产生一个 java.util.Date 对象。

这可以通过利用 java.text.DateFormat 类来实现吗?或者有其他简单的方法吗?

【问题讨论】:

    标签: java parsing date


    【解决方案1】:

    您可能需要使用 SimpleDateFormat 来解析自定义格式。这个article 解释了格式化的细节。

    "d-MMM-yyyy" corresponds to 4-Nov-2009
    

    【讨论】:

    • 这需要一个日期并将其格式化为一个字符串,我需要相反的,还有其他例子吗?
    • 你要解析一个字符串到日期,所以使用parse方法。
    • 它是双向的。使用 parse() 从 String 转到 Date
    • 注意:SimpleDateFormat 不同步。我在支持一个 Tomcat 应用程序时发现了这一点,该应用程序由于两个线程同时使用相同的内存区域而崩溃。如果您在 Web 应用程序中使用 SimpleDateFormat,请确保为每个 Web 请求实例化一个新对象。
    【解决方案2】:

    SimpleDateFormat 是通常用于此的类。请注意,这个类不是线程安全的(有点违反直觉),如果您在线程上下文中使用它,那么研究Joda 及其DateTimeFormatter 是值得的。

    【讨论】:

      【解决方案3】:

      您可以使用java.text.SimpleDateFormat 完成此操作。点击链接,你会看到所有的模式。

      对于 1-2 位数的日子,您可以使用 d 模式。对于 3 个字符的月份缩写,您可以使用 MMM 模式。对于 2 位数年份,您可以使用 yy 模式。

      所以以下应该做:

      String dateString = "4-Nov-09";
      SimpleDateFormat sdf = new SimpleDateFormat("d-MMM-yy");
      Date date = sdf.parse(dateString);
      

      【讨论】:

        【解决方案4】:

        无论您做什么,请使用区域设置。这样,当输入带有法语月份名称时,您仍然可以获得合理的结果。

        【讨论】:

          【解决方案5】:

          java.time

          这是现代答案。问题中提到的DateFormat 类及其在大多数旧答案中使用的SimpleDateFormat 子类是出了名的麻烦且早已过时。不要使用其中任何一个。也不要使用Date,它的设计很糟糕,而且也已经过时了。

          由于您有两位数的年份(在您的示例中为 09 和 05),因此您需要确定一个世纪。在第一轮中,我假设年份在 2000 年到 2099 年之间。

          首先我们需要一个格式化程序:

          static DateTimeFormatter dateFormatter
                  = DateTimeFormatter.ofPattern("d-MMM-uu", Locale.ENGLISH);
          

          DateTimeFormatter 是线程安全的,所以我们很高兴有一个实例供所有人使用。 @shoover 是正确的,我们应该提供一个语言环境。像这样使用格式化程序:

              String text = "4-Nov-09";
              LocalDate date = LocalDate.parse(text, dateFormatter);
              System.out.println("Date: " + date);
          

          输出是:

          日期:2009-11-04

          验证

          为了验证,特别是对两位数年份的正确解释,我建议您添加范围检查。例如,要验证解析的日期不超过过去或未来 10 年:

              LocalDate today = LocalDate.now(ZoneId.systemDefault());
              if (date.isBefore(today.minusYears(10))
                      || date.isAfter(today.plusYears(10))) {
                  System.err.println("This date can’t be right");
              }
          

          出于许多目的,您将提前知道日期是过去还是将来,并且可以比我的示例进一步缩小有效间隔。

          其他世纪

          如果年份可以超出 20xx 范围,我们通过DateTimeFormatterBuilder 及其appendValueReduced 方法控制年份的解释。请参阅以下链接列表中的相关答案之一。

          链接

          【讨论】:

            【解决方案6】:

            【讨论】:

              【解决方案7】:

              你可以试试这个库dateparser

              它可以自动识别任何String,并将其解析为DateCalendarLocalDateTime >OffsetDateTime正确。

              有了它,你不必准备任何合适的模式:

              Date date = DateParserUtils.parseDate("12-Dec-05");
              

              date 将是 Mon Dec 12 00:00:00 CST 2005

              很酷吗?

              【讨论】:

              • 我们真正希望从12-Dec-05 获得的是LocalDate(这是一个没有时间的日期)。这是不受支持的吗?有些人可能还期望从您的字符串中获得 2012 年 12 月 5 日,我对不指定我们想要的内容感到不舒服。
              • 在我看来12-Dec-05Dec, 12, 05差不多,不知道哪个用得更广。但是dateparser可以自定义,你可以很容易地改变它。关于LocalDate,可以使用LocalDateTime#toLocalDate获取。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-02-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多