2

考虑以下代码:

public static void main(String[] args) {

    String pattern = "MMM dd, yyyy HH:mm:ss a z";

    // joda-time
    DateTime dt = DateTime.now();
    System.out.println(dt.toString(pattern));

    // java.time
    ZonedDateTime ldt = ZonedDateTime.now();
    System.out.println(ldt.toString(pattern)); // doesn't exist
    System.out.println(ldt.format(DateTimeFormatter.ofPattern(pattern)));
}

joda-time 类(DateTime,LocalDate等)包含一个toString方法,它接受您想要的格式的字符串。这是一个非常方便的方法。然而,java-8 实现省略了这个方法。相反,您需要调用format(DateTimeFormatter formatter).

一个小小的抱怨,当然。但我的问题是:有什么理由从 java.time 中省略了吗?由于这个小疏忽,将我的应用程序从 joda-time 转换为 java.time 将变得更加困难。但是,如果有合乎逻辑的原因,我可以接受。并不是说你来这里是为了缓解我的担忧,但我想我会问一下以防万一。

编辑:对于亲密的选民来说,这不是一个基于意见的问题。任何熟悉 joda-time/java.time 的内部工作原理以及他们以某种方式开发的动机的人都有资格回答这个问题,即使他们从未回答过。

4

3 回答 3

5

一个有趣的问题。Joda-Time 和 java.time (JSR-310) 有不同的设计中心——Joda-Time 是一个开源库,而 java.time 是 JDK 的扩展。一个实际含义是对方法计数的压力更大,这是这里的一个因素。

Joda-Time 中所讨论的方法是以下四种方法之一:

  • toString()
  • toString(DateTimeFormatter dtf)
  • toString(String pattern)
  • toString(String pattern, Locale loc)

第一个是 Java 中的标准方法,因此默认包含在内。基于格式化程序的方法很方便,因为您可以只使用格式化程序本身。这两种基于模式的方法更加方便,因为它们只是创建了一个格式化程序。

但是请注意,基于模式的方法需要两种变体,一种有语言环境,一种没有语言环境,而格式化程序在内部嵌入语言环境(因此不需要方法变体)。在考虑 JSR-310 时,对额外语言环境方法的需求非常重要。

另一个考虑因素是缓存/性能。Joda-Time 对格式化程序有一个模式缓存,以避免重新解析像“yyyy-MM-dd”这样的模式。这样的缓存在 JDK 中不太受欢迎,因此希望找到一种没有缓存的方法。

使用 java.time 格式化程序的推荐方法是将它们分配给静态变量。新格式化程序是线程安全的(与旧格式化程序不同),因此效果很好。此外,为格式化程序定义一个常量意味着模式的解析只发生一次 - 常量存储准备格式化/解析的内部数据结构。

private static final DateTimeFormatter FORMATTER =
                DateTimeFormatter.ofPattern("MMM dd, yyyy HH:mm:ss a z");
public static void main(String[] args) {
  ZonedDateTime ldt = ZonedDateTime.now();
  System.out.println(ldt.format(FORMATTER);
}

最后,JSR-310 中的方法最初被称为toString(DateTimeFormatter). Oracle 内部的审查建议将该方法重命名为format(DateTimeFormatter).

于 2014-04-02T10:46:29.653 回答
1

替代方案的决定性优势format是可以共享单个 DateTimeFormatter(这不是旧的不可共享的非线程安全 DateFormatter)。

API报价:

从模式创建的格式化程序可以根据需要多次使用,它是不可变的并且是线程安全的。

两者都没有,是 API 设计中的清洁问题。

所以这个API借给一个人写:

final DateTimeFormatter DTF =
        DateTimeFormatter.ofPattern("MMM dd, yyyy HH:mm:ss a z"));
...
System.out.println(ldt.format(DTF));
于 2014-04-01T17:28:20.187 回答
1

我所说的一切都是猜测,因为您必须与新的日期时间 API 的作者交谈才能真正找到答案。

我猜他们决定使用格式化程序,因为它在语义上更合适,并且更符合您实际尝试做的事情:为特定语言环境格式化日期。尽管toString采用了一种模式,但签名toString(String)并不完全直观。此外,拥有一个处理日期格式的专用方法可能比重载更好Object#toString。它绝对是一个更清洁的 API。

同样,正如我所说,这是猜测,所以要得到真正的答案,你必须去源头。但如果我做这样的事情,这些就是我的理由。

于 2014-04-01T17:19:42.550 回答