我希望根据某些逻辑在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
对象添加一个月。
答案 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
)。