2

我应该以我使用 Apache Spark 作为开头,它使用java.sql.Date,以防有人建议我应该使用java.time. 下面的例子是在 Scala 中。

我使用(已弃用)获取日期月份的 API 如下:

val date: java.sql.Date = ???
val month = date.getMonth()

但是,如果我看看我应该如何根据弃用来执行此操作,则上面的代码将被重写如下:

val date: java.sql.Date = ???
val cal = Calendar.getInstance()
cal.setTime(date)
cal.get(Calendar.MONTH)

代码的简单性和可读性明显不同,从函数式编程的角度来看,日期作为日历的副作用并不是非常好。有人可以解释为什么他们认为做出了这种改变吗?

4

2 回答 2

5

在 JDK 1.1 之前,Date 类有两个附加功能。它允许将日期解释为年、月、日、小时、分钟和秒值。它还允许格式化和解析日期字符串。不幸的是,这些函数的 API不适合国际化。从 JDK 1.1 开始,应使用 Calendar 类在日期和时间字段之间进行转换,并且应使用 DateFormat 类来格式化和解析日期字符串。Date 中的相应方法已弃用。

JavaDoc解释了。国际化。


万一有人建议我应该使用来自java.time”的日期

没有什么可以阻止您java.time尽快转换为类,执行您需要的任何计算/修改,如果您需要重新插入,请java.sql.Date再次转换回。

于 2020-07-09T09:57:56.883 回答
2
    val date: java.sql.Date = ???
    val month = date.toLocalDate().getMonthValue()

您自己说过,我仍然认为:您应该使用 java.time,现代 Java 日期和时间 API。当您java.sql.Date从尚未升级到 java.time 的遗留 API 中获得老式 API 时,将其转换为现代 API,LocalDate并享受使用 java.time 编写的自然代码。

为什么不推荐使用 getMonth() 和其他 getXxx 方法?

虽然迈克尔已经回答了这个问题java.util.Date但我有一些要补充的java.sql.Date。对于这堂课,情况比迈克尔报告的要糟糕得多。

java.util.Date在弃用之后没有弃用(被认可?)的是 aDate是一个时间点。java.sql.Date另一方面,从来都不是一个时间点。说明这一事实的一种方法是它的toInstant方法——应该将它转换为一个Instant时间点——无条件地抛出一个UnsupportedOperationException。Ajava.sql.Date本来是要与 SQL 数据库及其date数据类型一起使用的日历日期,在大多数情况下,它也是一个日期,由年、月和月中的某天定义。由于 aDate不再是年、月和日,他们实际上已经弃用了 ajava.sql.Date应该是的所有内容。LocalDate直到使用 JDBC 4.2 我们可以与 SQL 数据库交换对象,他们才给我们一个替代品。

导致弃用的观察结果产生了非常实际的后果。让我们试试这个(在 Java 中,因为这是我能写的):

void foo(java.sql.Date sqlDate) {
    System.out.println(sqlDate);
    TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Pacific/Samoa")));
    System.out.println(sqlDate.getMonth());
}

在一次调用中打印的方法:

2020-11-02
9

所以我们有第 11 个月的第二天,月份打印为 9?有两件事发生:

  1. 令人困惑的是,返回的月份数getMonth()是从 0 开始的,所以 9 表示 10 月。
  2. 在 JVM的Date默认时区中,它在内部表示为从纪元到一天开始的毫秒数。2020-11-02 00:00:00 在我的原始时区(在此演示中设置为 Pacific/Kiritimati)与萨摩亚的 2020-10-31 23:00:00 是同一时间点。因此我们得到十月。

您不必自己更改时区即可。可能发生的情况包括:

  • JVM 的默认时区可以从程序的任何部分以及在同一 JVM 中运行的任何其他程序进行更改。
  • 日期可以在一个 JVM 中运行的程序中序列化,并在具有不同时区设置的不同 JVM 中反序列化。

顺便说一句,我在顶部展示的第一个片段通常无助于在这些情况下出现意外结果。如果在您从 转换为 之前事情偏离了轨道,那么java.sql.Date转换LocalDate也会给您错误的日期。如果可以,请在任何人弄乱 JVM 时区设置LocalDate 之前转换为安全起见。

于 2020-07-09T13:57:56.887 回答