从 ZonedDateTime 获取 java.sql.Timestamp

Getting java.sql.Timestamp from ZonedDateTime

我想根据某些逻辑在 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
     }

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

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

    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) 和历史偏移量更改。我在 之后 调整了一个月中的日期。两者都有效,但这使 reader 无需考虑将一个月添加到 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 class(或 Date)。