【问题标题】:Getting java.sql.Timestamp from ZonedDateTime从 ZonedDateTime 获取 java.sql.Timestamp
【发布时间】:2018-01-31 15:10:33
【问题描述】:

我想根据一些逻辑从Java的数据库中的datetime数据类型的列中插入一个值。

逻辑: 如果该月的日期是 29、30 或 31,则输入下个月的 28 日。否则放入下个月的同一天。

例如如果日期为2017-08-31,则进入数据库的日期将为2017-09-28。但是,如果日期是2017-08-27,则进入数据库的日期将为2017-09-27

我还想要UTC 中的所有内容。

我正在尝试的代码是这样的:

ZonedDateTime utcDateTime = ZonedDateTime.now(ZoneOffset.UTC);

utcDateTime = utcDateTime.plusMonths(1);

if(utcDateTime.getDayOfMonth() >= 29){
    utcDateTime = utcDateTime.withDayOfMonth(28);
    Timestamp time = Timestamp.from(utcDateTime.toInstant());
    System.out.println(time); // DB insert here
}else{
       Timestamp time = Timestamp.from(utcDateTime.toInstant());
       System.out.println(time); // DB insert here
     }

问题:这是最正确的方法,还是使用Instant(始终使用 UTC)有更简单的 Java 8 方法?我没有任何方法可以直接从Instant 对象获取月份中的某天,也无法将月份添加到Instant 对象。

【问题讨论】:

  • 不考虑所有可能性,您的代码立即看起来不错。 Instant 不太适合您需要的日期算术,因此最好使用另一个类。我会考虑OffsetDateTime 而不是ZonedDateTime
  • 您需要一天中的时间吗?如果不是,使用LocalDate 可能更正确(即使转换为Instant 有点不那么直接)。此外,您可能想解释为什么要回到 9 月 28 日,因为 9 月有 30 天;好像有点搞笑?

标签: java sql-server date datetime java-time


【解决方案1】:

您的代码适合您的目的。为了您可能的灵感,这是我的版本:

    OffsetDateTime utcDateTime = OffsetDateTime.now(ZoneOffset.UTC);

    if (utcDateTime.getDayOfMonth() >= 29) {
        utcDateTime = utcDateTime.withDayOfMonth(28);
    } 

    utcDateTime = utcDateTime.plusMonths(1);
    Timestamp time = Timestamp.from(utcDateTime.toInstant());
    System.out.println(time); // DB insert here

我使用 OffsetDateTime 而不是 ZonedDateTime,因为我们不需要时区的任何额外功能,例如夏令时 (DST) 和历史偏移更改。我在调整月份的日期之后添加一个月。两者都有效,但这让读者不必思考当您将一个月添加到 1 月 31 日时会发生什么。最后我发现没有else 部分的版本更自然:在某些情况下,您需要调整日期-月,所以if 部分负责处理,在所有其他情况下,我们只是不进行调整。拿走你喜欢的部分(如果有的话)并丢弃其余部分。

代码(您的和我的)保留了时间。我想你想要这个。为了完整起见,如果你不这样做,你会希望你的数据库只保存一个日期而不是时间戳,所以代码将使用java.sql.Date

    LocalDate utcDate = LocalDate.now(ZoneOffset.UTC);
    if (utcDate.getDayOfMonth() > 28) {
        utcDate = utcDate.withDayOfMonth(28);
    }
    utcDate = utcDate.plusMonths(1);
    Date date = Date.valueOf(utcDate);
    System.out.println(date); // DB insert here

如果您无法更改数据库列数据类型,通常使用一天的开始时间 (0:00):

    Timestamp time = Timestamp.from(utcDate.atStartOfDay(ZoneOffset.UTC).toInstant());
    System.out.println(time); // DB insert here

最后,我强烈建议您看看是否可以为您的数据库获取 JDBC 4.2 驱动程序。这将接受直接插入Instant(或LocalDate),因此您完全摆脱了过时的Timestamp 类(或Date)。

【讨论】:

    猜你喜欢
    • 2018-12-24
    • 2016-10-30
    • 2020-10-04
    • 2019-04-16
    • 1970-01-01
    • 2014-06-29
    • 2016-06-26
    • 1970-01-01
    • 2020-10-13
    相关资源
    最近更新 更多