首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java8 java.time:在Instant vs LocalDateTime中添加TemporalUnit

Java8 java.time:在Instant vs LocalDateTime中添加TemporalUnit
EN

Stack Overflow用户
提问于 2014-04-02 01:56:29
回答 1查看 40.3K关注 0票数 30

我正在使用Java8中新的java.time包,我有一个遗留的数据库,它提供了java.util.Date,我将其转换为Instant

我尝试做的是添加一个基于另一个数据库标志的时间段。我可以添加几天、几周、几个月或几年。我不想关心我添加了什么,我希望将来能够添加更多的选项。

我的第一个想法是Instant.plus(),但它给了我一个大于一天的值的UnsupportedTemporalTypeException。Instant显然不支持大时间单位的操作。好吧,不管怎么说,LocalDateTime做了。

这就给出了这个代码:

代码语言:javascript
复制
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());
}

现在,这是我第一次使用新的time API,所以我可能遗漏了一些东西。但对我来说,我必须走了,这似乎很笨拙:

代码语言:javascript
复制
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吗?我应该期待来自用户输入的时区吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-21 20:45:32

我将根据我的最终解决方案和对非常长的评论链的一种总结,继续发布一个答案。

首先,整个转换链:

代码语言:javascript
复制
Date --> Instant --> LocalDateTime --> Do stuff --> Instant --> Date

需要保留时区信息,并且仍然对知道Calendar和其中所有上下文的类似Date的对象执行操作。否则,我们将面临隐式转换为本地时区的风险,如果我们尝试将其转换为人类可读的日期格式,时间可能会因此而更改。

例如,java.sql.Timestamp类上的toLocalDateTime()方法隐式转换为默认时区。这对我的目的来说是不可取的,但不一定是坏行为。然而,重要的是要意识到这一点。这就是直接从遗留java date对象转换为LocalDateTime对象的问题。由于传统对象通常假定为UTC,因此转换使用本地时区偏移量。

现在,假设我们的程序接受2014-04-16T13:00:00的输入并作为java.sql.Timestamp保存到数据库中。

代码语言:javascript
复制
//Parse string into local date. LocalDateTime has no timezone component
LocalDateTime time = LocalDateTime.parse("2014-04-16T13:00:00");

//Convert to Instant with no time zone offset
Instant instant = time.atZone(ZoneOffset.ofHours(0)).toInstant();

//Easy conversion from Instant to the java.sql.Timestamp object
Timestamp timestamp = Timestamp.from(instant);

现在我们获取一个时间戳,并在其上添加一些天数:

代码语言:javascript
复制
Timestamp timestamp = ...

//Convert to LocalDateTime. Use no offset for timezone
LocalDateTime time = LocalDateTime.ofInstant(timestamp.toInstant(), ZoneOffset.ofHours(0));

//Add time. In this case, add one day.
time = time.plus(1, ChronoUnit.DAYS);

//Convert back to instant, again, no time zone offset.
Instant output = time.atZone(ZoneOffset.ofHours(0)).toInstant();

Timestamp savedTimestamp = Timestamp.from(output);

现在我们只需要以ISO_LOCAL_DATE_TIME格式输出一个人类可读的字符串。

代码语言:javascript
复制
Timestamp timestamp = ....
LocalDateTime time = LocalDateTime.ofInstant(timestamp.toInstant(), ZoneOffset.ofHours(0));
String formatted = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(time);
票数 26
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22793315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档