我在Java 8中使用了新的java.time包。我有一个旧数据库,它给了我java.util.Date
,我将其转换为Instant
。Java 8 java.time:在Instant中添加TemporalUnit与LocalDateTime
我想要做的是添加一段基于另一个数据库标志的时间。我可以增加几天,几周,几个月或几年。我不想关心我所添加的内容,我希望能够在未来添加更多选项。
我的第一个想法是Instant.plus()
,但这给了我一个UnsupportedTemporalTypeException
值大于一天。即时显然不支持大单位时间的操作。好吧,无论如何,LocalDateTime
呢。
所以这给了我这个代码:
private Date adjustDate(Date myDate, TemporalUnit unit){
Instant instant = myDate.toInstant();
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
dateTime = dateTime.plus(1, unit);
Instant updatedInstant = dateTime.atZone(ZoneId.systemDefault()).toInstant();
return new Date(dueInstant.toEpochMilli());
}
现在,这是使用新的API时我的第一次,所以我会在这里错过了一些东西。但似乎笨重,我认为我必须去:
Date --> Instant --> LocalDateTime --> do stuff--> Instant --> Date.
即使我没有使用日期部分,我仍然认为这是一个有点尴尬。所以我的问题是,我是否完全错误,做这件事的最好方法是什么?
编辑:扩大对注释的讨论。
我想我现在有更好的想法了解LocalDateTime和Instant如何与java.util.Date和java.sql.Timestamp一起玩。感谢大家。
现在,更实际的考虑。假设用户向我发送一个来自世界任何地方的任意时间的日期。他们发给我2014-04-16T13:00:00
,我可以解析成LocalDateTime。然后我直接将其转换为java.sql.Timestamp并保存在我的数据库中。
现在,没有做任何事情,我从我的数据库中取出java.sql.timestamp,使用timestamp.toLocalDateTime()
转换为LocalDateTime
。都好。然后我使用ISO_DATE_TIME格式将此值返回给我的用户。结果是2014-04-16T09:00:00
。
我认为这种差异是由于某种类型的隐式转换为/从UTC。我认为我的默认时区可能会被应用到数值(EDT,UTC-4),这可以解释为什么数字关闭了4个小时。
新的问题。本地时间到UTC的隐式转换在哪里发生?什么是更好的方式来保存时区。我不应该直接从当地时间作为一个字符串(2014-04-16T13:00:00)到LocalDateTime
?我是否应该期待用户输入的时区?
你打算在这里代表什么价值? “即时”在逻辑上不知道日历系统 - 这只是一个时间点 - 所以增加一个月没有意义。您还应该仔细考虑您是否真的想要使用系统时区 - 您是否希望针对相同的值获得不同的结果,具体取决于您正在运行的位置? –
@JonSkeet那么随意选择ZoneId会更合适吗?总是格林威治时间什么的看起来这可能会带来一系列的问题。也许问题是我不知道如何表示我的java.util.date。我有一个时间点。如果符合某些条件,我想在未来将这一点改为一个月(或日,年,无论)。 – jacobhyphenated
使用UTC可能是最佳选择,但您确实需要考虑您的要求。它甚至意味着将一个时间点(没有时区或日历)改变一个月? –