在没有* toInstant()的情况下将java.util.Date截断为LocalDate *,因为java.sql.Date给出了UnsupportedOperationException

如果我在一个恰好是java.sql.Date的变量上使用java.util.Date的toInstant(),我会得到一个UnsupportedOperationException.try {java.util.Date input = new java.sql.Date(System.currentTimeMillis());LocalDate dat...

如果我在一个恰好是java.sql.Date的变量上使用java.util.Date的toInstant(),我会得到一个UnsupportedOperationException.

try {
    java.util.Date input = new java.sql.Date(System.currentTimeMillis());
    LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
} catch (UnsupportedOperationException e) {
    // grrr!
}

我关心的java.util.Date来自mysql DB中的DATE字段,通过遗留API,实际上是java.sql.Date.

现在以下相关问题都非常有趣:

UnsupportedOperationException – Why can’t you call toInstant() on a java.sql.Date?

Convert java.util.Date to java.time.LocalDate

LocalDate to java.util.Date and vice versa simplest conversion?

但它们没有提供任何截断java.util.Date的优雅方法来摆脱时间组件并获得Java 8 LocalDate.

我承认存在一个问题,即一个时区中的同一时刻可能与另一个时区的同一时刻不同.

我怀疑解决方案将涉及java.util.Calendar,而不是制定我自己的解决方案,我宁愿建立别人先做的事情.

我宁愿找到比这更短的东西:

from 07003 :

06001

解决方法:

如果已知输入变量是java.sql.Date,那么您可以简单地转换它并调用toLocalDate()方法:

LocalDate date = ((java.sql.Date) input).toLocalDate();

不幸的是,你不能在java.sql.Date上调用toInstant(),因为according to javadoc,它总是抛出UnsupportedOperationException.

如果您不知道类型(可以是java.util.Date或java.sql.Date),您可以使用getTime()方法返回的值来构建Instant,然后将其转换为时区(下面我使用的是JVM的默认值),最后从中获取本地日期:

LocalDate date = Instant
    // get the millis value to build the Instant
    .ofEpochMilli(input.getTime())
    // convert to JVM default timezone
    .atZone(ZoneId.systemDefault())
    // convert to LocalDate
    .toLocalDate();

toLocalDate()方法获取日期部分(日/月/年),忽略其余部分,因此无需截断它:如果时间是午夜,上午10点或当天的任何其他时间都无关紧要,toLocalDate()将忽略它并获得日期部分.

但是,如果您真的想将时间设置为午夜,则可以使用with method并将LocalTime传递给它:

LocalDate date = Instant
    // get the millis value to build the Instant
    .ofEpochMilli(input.getTime())
    // convert to JVM default timezone
    .atZone(ZoneId.systemDefault())
    // set time to midnight
    .with(LocalTime.MIDNIGHT)
    // convert to LocalDate
    .toLocalDate();

但正如我所说,toLocalDate()方法将忽略时间部分,因此在这种情况下不需要设置时间(LocalDate将是相同的).

您还可以检查日期的类型并相应地选择相应的操作,如下所示:

if (input instanceof java.sql.Date) {
    date = ((java.sql.Date) input).toLocalDate();
} else {
    date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}

您可以根据需要使用任何其他时区,而不是使用JVM默认时区(ZoneId.systemDefault()),通过调用ZoneId.of(“zoneName”),其中区域名称是任何有效的IANA timezones names(始终格式为Region / City,如America / New_York或Europe / London).
避免使用3个字母的缩写(如CET或PST),因为它们是ambiguous and not standard.

您可以通过调用ZoneId.getAvailableZoneIds()获取可用时区列表(并选择最适合您系统的时区).如果需要,您还可以继续使用JVM默认时区,但要提醒它为can be changed without notice, even at runtime,因此最好始终明确指出您正在使用的时区.

本文标题为:在没有* toInstant()的情况下将java.util.Date截断为LocalDate *,因为java.sql.Date给出了UnsupportedOperationException

基础教程推荐