有 Java 编程相关的问题?

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

java的DateTimeFormatter比SimpleDateFormat更严格吗?以毫秒为单位分析日期

我有一个简单的测试用例:

public static void main(String[] args) {
  String pattern = "yyyy-MM-dd HH:mm:ss.SSS";
  String date = "2017-01-15 15:15:15.5";

  SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
  DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
  FastDateFormat fastDateFormat = FastDateFormat.getInstance(pattern);
  try {
    System.out.println("SFD: " + simpleDateFormat.parse(date));
  }catch (Exception e) {
    System.err.println("SDF failed");
  }
  try {
    System.out.println("DTF: " + dateTimeFormatter.parse(date));
  }catch (Exception e) {
    System.err.println("DTF failed");
  }
  try {
    System.out.println("FDF: " + fastDateFormat.parse(date));
  }catch (Exception e) {
    System.err.println("FDF failed");
  }
}

输出如下:

SFD: Thu Jan 15 15:15:15 CET 1970
DTF failed
FDF: Thu Jan 15 15:15:15 CET 1970

根据结果,Java的8 DateTimeFormatter比SimpleDateFormat更严格。我的问题是,为什么在这种情况下,最好的方法是用.S作为毫秒或.SSS接受两个日期,比如用try/catch多次解析


共 (2) 个答案

  1. # 1 楼答案

    您基本上是在问为什么SimpleDateFormat在模式显示为“.SSS”时接受一位毫秒值

    原因在javadoc中SimpleDateFormat

    Pattern letters are usually repeated, as their number determines the exact presentation:

    ...

    Number: For formatting, the number of pattern letters is the minimum number of digits, and shorter numbers are zero-padded to this amount. For parsing, the number of pattern letters is ignored unless it's needed to separate two adjacent fields.

    显然,您可以通过调用setLenient(false)来改变这一点。然而,javadocs并没有具体说明宽大的实际效果

    相比之下,javadoc for DateTimeFormatter只是简单地说“模式字母的计数决定了格式”,而不区分格式和解析


    为什么它们不同?您需要询问DateTimeFormatterAPI的设计人员,但我认为设计者认为SimpleDateFormat(默认)宽松解析模式的^{特别的和未指定的性质是有害的


    如何简单地让DateTimeFormatter接受具有一位或三位毫秒值的日期

    一种方法是使用DateTimeFormatterBuilder创建格式化程序。这允许您为格式中的任何字段指定最小和最大宽度

  2. # 2 楼答案

    SimpleDateFormat不是每个默认值都严格,因为属性lenient是每个默认值true。但是您可以将属性lenient设置为false以使其严格

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
    simpleDateFormat.setLenient(false);
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
    try {
        System.out.println("SFD: " + simpleDateFormat.parse(date));
    } catch (Exception e) {
        System.err.println("SDF failed");
    }
    try {
        System.out.println("DTF: " + dateTimeFormatter.parse(date));
    } catch (Exception e) {
        System.err.println("DTF failed");
    }
    

    结果将是

    SDF failed
    DTF failed
    

    DateFormat.parse(String, ParsePosition)

    By default, parsing is lenient: If the input is not in the form used by this object's format method but can still be parsed as a date, then the parse succeeds. Clients may insist on strict adherence to the format by calling setLenient(false).