从ZonedDateTime

时间:2017-08-23 07:00:55

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

我希望根据某些逻辑在Java数据库的datetime数据类型列中插入一个值。

逻辑: 如果这个月的日期是29,30或31,则在下个月的28日进行。其他放在下个月的同一天。

E.g。如果日期为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对象添加一个月。

1 个答案:

答案 0 :(得分: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)。