【问题标题】:java.time ::toString(String pattern) method missingjava.time ::toString(String pattern) 方法缺失
【发布时间】:2014-04-01 17:13:32
【问题描述】:

考虑以下代码:

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 类(DateTimeLocalDate 等)包含一个 toString 方法,该方法接受您想要的格式的字符串。这是一个非常方便的方法。然而,java-8 实现省略了这个方法。相反,您需要致电format(DateTimeFormatter formatter)

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

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

【问题讨论】:

  • 请注意,joda-time 仍然是一个地狱般的库,没有真正的理由(除非您需要为 .jar 节省 500KB 的存储空间)来切换。
  • java.time 的主要目的是防止新项目需要 joda-time 吗?
  • @ryvantage java.time的作者是JodaTime的作者。所以我想说java.time是JodaTime的精神继承者。
  • @ryvantage TBH,这是一个基于意见的问题,因为没有真正的答案(除非实际作者插话)。我们只是在猜测。
  • 正是我问这个问题的原因:如果同一作者写了两个,那么他一定有理由省略该方法。我只是想知道为什么。

标签: java java-8 jodatime java-time


【解决方案1】:

一个有趣的问题。 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)

【讨论】:

  • 因此,实用性(更少的方法,无缓存)与便利性相比,实用性胜出 JDK。谢谢!很高兴直接从源头听到。
【解决方案2】:

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));

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2012-06-02
      • 2020-09-03
      • 1970-01-01
      • 2018-07-28
      • 2017-07-09
      • 2013-08-13
      • 1970-01-01
      • 1970-01-01
      • 2013-10-31
      相关资源
      最近更新 更多