将java.util.Date截断为LocalDate,而不必将inTunst()截断,因为java.sql.Date提供了UnsupportedOperationException

Ada*_*dam 6 java datetime date date-conversion java-time

如果我用java.util.DatetoInstant()上这恰好是一个变量java.sql.Date,我得到一个UnsupportedOperationException

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

java.util.Date,我很担心经由传统API的MySQL数据库来自一个日期字段,而实际上是一个java.sql.Date

现在,以下相关问题都很有趣:

UnsupportedOperationException-为什么不能在java.sql.Date上调用toInstant()?

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

LocalDate到java.util.Date的转换,反之亦然?

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

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

我怀疑解决方案将涉及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
Run Code Online (Sandbox Code Playgroud)

小智 7

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

LocalDate date = ((java.sql.Date) input).toLocalDate();
Run Code Online (Sandbox Code Playgroud)

不幸的是,你不能调用toInstant()a java.sql.Date,因为根据 javadoc,它总是抛出UnsupportedOperationException.

如果你不知道类型(它可以是 ajava.util.Date或 a 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();
Run Code Online (Sandbox Code Playgroud)

toLocalDate()方法获取日期部分(日/月/年),忽略其余部分,因此无需截断它:无论时间是午夜、上午 10 点还是一天中的任何其他时间,toLocalDate()都将忽略它并只获取日期部分。

但是,如果您真的想将时间设置为午夜,则可以使用该with方法并将 a 传递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();
Run Code Online (Sandbox Code Playgroud)

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


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

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

除了使用JVM默认时区(中ZoneId.systemDefault()),你可以使用任何其它时区,根据您的需要,通过调用ZoneId.of("zoneName"),其中区域名称为任何有效的IANA时区的名称(总是在格式Region/City,如America/New_YorkEurope/London)。避免使用 3 个字母的缩写(如CETPST),因为它们含糊不清且不标准

您可以通过调用获取可用时区列表(并选择最适合您系统的时区)ZoneId.getAvailableZoneIds()。如果需要,您也可以继续使用 JVM 默认时区,但请注意,即使在运行时,也可以在没有通知的情况下更改它,因此最好始终明确您正在使用的时区。


Ada*_*dam 7

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

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

}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

4689 次

最近记录:

7 年,3 月 前