当前位置: 首页 > 知识库问答 >
问题:

将 java.util.Date 截断为本地日期 *不带* 到实例(),因为 java.sql.Date 给出了不受支持的操作异常

吕晟睿
2023-03-14

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

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

我关注的< code>java.util.Date来自mysql DB中的一个日期字段,通过一个遗留API,实际上是一个< code>java.sql.Date。

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

不支持的操作例外 - 为什么不能在 java.sql.Date 上调用

将java.util.Date转换为java.time.LocalDate

将LocalDate设置为java.util。日期,反之亦然,最简单的转换?

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

我承认有一个问题,一个时区的同一时刻可能与另一时区的相同时刻的日期不同。

我怀疑这个解决方案会涉及到java.util.Calendar,但是与其精心设计我自己的解决方案,我宁愿先确定别人已经做了什么。

我更喜欢找比这个短的:

在Java中重置时间戳的时间部分:

Date date = new Date();                      // timestamp now
Calendar cal = Calendar.getInstance();       // get calendar instance
cal.setTime(date);                           // set cal to date
cal.set(Calendar.HOUR_OF_DAY, 0);            // set hour to midnight
cal.set(Calendar.MINUTE, 0);                 // set minute in hour
cal.set(Calendar.SECOND, 0);                 // set second in minute
cal.set(Calendar.MILLISECOND, 0);            // set millis in second
Date zeroedDate = cal.getTime();             // actually computes the new Date

共有3个答案

翟曦
2023-03-14
myResultSet.getObject( … , LocalDate.class ) 

您的麻烦始于使用遗留的日期时间类,如java.sql.Datejava.util.DateCalendar。完全避免这些类。它们现在是遗留的,被java.time类取代。

您说该值以DATE类型的MySQL列中的存储值开始。该类型是仅日期的,没有一天中的时间。因此,您通过使用错误的类不必要地引入了一天中的时间值。

使用符合JDBC 4.2或更高版本的JDBC驱动程序,使用java.time类与数据库交换值。

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;

并传递给PreparedStatement

myPstmt.setObject( … , myLocalDate ) ;
申自明
2023-03-14

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

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

不幸的是,您不能在java.sql上调用toInstant()。日期,因为根据javadoc,它总是抛出UnsupportedOperationException

如果您不知道类型(它可以是java.util.Datejava.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()都会忽略它并只获取日期部分。

但是,如果您真的想将时间设置为午夜,您可以使用< code>with方法并向其传递一个< code>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()方法只会忽略时间部分,因此在这种情况下不需要设置时间(LocalDatewill be same)。

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

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

除了使用JVM默认时区(< code > zoneid . system default()),您还可以根据需要使用任何其他时区,方法是调用< code > zoneid . of(" zone name "),其中时区名称是任何有效的IANA时区名称(格式始终为< code>Region/City,如< code>America/New_York或< code>Europe/London)。避免使用3个字母的缩写(如< code>CET或< code>PST),因为它们不明确且不标准。

您可以通过调用ZoneId.get可用区Ids()来获取可用时区列表(并选择最适合您系统的时区)。如果需要,您也可以继续使用JVM默认时区,但要提醒一下,即使在运行时也可以在不另行通知的情况下进行更改,因此最好始终明确您正在使用哪个时区。

柴宏阔
2023-03-14

通常最简单的解决方案最难找到:

public LocalDate convertDateObject(java.util.Date suspectDate) {

    try {
        // Don't do this if there is the smallest chance 
        // it could be a java.sql.Date!
        return suspectDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

    } catch (UnsupportedOperationException e) {
        // BOOM!!
    }

    // do this first:
    java.util.Date safeDate = new Date(suspectDate.getTime());

    return safeDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

}
 类似资料:
  • 问题内容: 在保留时间戳的同时将java.sql.Date对象转换为java.util.Date的最简单方法是什么? 我试过了: 没有运气。它仍然只将日期部分存储到变量中。 问题答案: java.sql.Date类设计为仅包含日期而没有时间,因此您看到的转换结果对该类型是正确的。您需要使用java.sql.Timestamp来获取带时间的完整日期。

  • 问题内容: 我在函数上发现错误,从DatatypeFactory df初始化newInstance()方法后,它显示错误结果,我得到了另一个错误: 我只是将包裹名称从 然后投射: 问题答案: 这是不可能的 投 自到。您需要从一种类型 转换 为另一种类型:

  • 相反,将引发“UnsupportedOperationException”。看起来ContainerRequest没有从修改的请求中提取UserPrincipal。 修改是通过 问题是如何将主体信息从HttpServerProbe传输到ContainerRequestFilter。request具有安全信息(在本例中是SSL客户机证书信息),而com.sun.jersey.spi.containe

  • 问题内容: 我正在尝试使用作为输入,然后使用它创建查询-所以我需要一个。 我很惊讶地发现它不能隐式或显式地进行转换-但我什至不知道该怎么做,因为对我来说还很新。 问题答案: 没关系....

  • 我不知道;我不太明白在哪里可以抛出这个异常。 例如,我正在实现

  • 问题内容: 我得到一个在一个表上(重复键)违反唯一性约束。本质上,我的表如下所示: 唯一性约束在上;也就是说,没有2条记录可以具有相同的日期/时间“时间戳”。 在将记录插入该表如下所示: 因此,您可以看到我正在使用(“现在”)并将其转换为实例。 我看到的确切错误(重复键)一直抱怨我试图将其插入表中,但该错误已经存在。因此,很明显,我使用了错误的Date API,并且插入了具有无效时间成分的日期,从