Java 8 java.time:在 Instant 与 LocalDateTime 中添加 TemporalUnit

2023-12-28

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

我想做的是添加基于另一个数据库标志的一段时间。我可以添加天、周、月或年。我不想关心我要添加的内容,并且我希望将来能够添加更多选项。

我的第一个想法是Instant.plus(),但这给了我一个UnsupportedTemporalTypeException对于大于一天的值。 Instant 显然不支持大时间单位的操作。好吧,无论如何,LocalDateTime does.

所以这给了我这个代码:

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.

即使我不必使用 Date 部分,我仍然会觉得这有点尴尬。所以我的问题是,我这样做完全错误吗?最好的方法是什么?


Edit:扩展评论中的讨论。

我想我现在对 LocalDateTime 和 Instant 如何使用 java.util.Date 和 java.sql.Timestamp 有了更好的了解。感谢大家。

现在,有一个更实际的考虑。假设用户向我发送了来自世界任何地方、任意时区的日期。他们送我2014-04-16T13:00:00我可以将其解析为 LocalDateTime。然后,我将其直接转换为 java.sql.Timestamp 并保留在我的数据库中。

现在,无需执行任何其他操作,我从数据库中提取 java.sql.timestamp,转换为LocalDateTime using timestamp.toLocalDateTime()。都好。然后我使用 ISO_DATE_TIME 格式将此值返回给我的用户。结果是2014-04-16T09:00:00.

我认为这种差异是由于某种类型的 UTC 隐式转换造成的。我认为我的默认时区可能会应用于该值(EDT、UTC-4),这可以解释为什么该数字相差 4 小时。

新问题。从本地时间到 UTC 的隐式转换发生在哪里?保留时区的更好方法是什么?我是否应该直接从当地时间作为字符串 (2014-04-16T13:00:00) 到LocalDateTime?我应该从用户输入中期待时区吗?


我将继续根据我的最终解决方案和很长的评论链的总结发布答案。

首先,整个转换链:

Date --> Instant --> LocalDateTime --> Do stuff --> Instant --> Date

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

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

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

//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);

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

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.

Timestamp timestamp = ....
LocalDateTime time = LocalDateTime.ofInstant(timestamp.toInstant(), ZoneOffset.ofHours(0));
String formatted = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(time);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 8 java.time:在 Instant 与 LocalDateTime 中添加 TemporalUnit 的相关文章

随机推荐

  • 如何在 PHP 中验证表单

    是使用 php 验证 PHP 表单然后出现错误进行重定向更好 还是使用 javascript 验证然后在启用 javascript 的情况下允许表单提交更好 You must验证服务器端的值 因为客户端不可信 You may验证客户端的值
  • 对 PHP 文件使用括号

    我目前正在运行 wampserver 并且正在尝试使用 Brackets io 实时预览 php 文件 但是 当我单击实时预览时 我得到了 Project settings for Getting Started Live preview
  • 在自定义元素 Shadow DOM 中选择槽文本

    我用常规的 html css js 制作了一个简单的复制粘贴组件 我尝试将其变成 Web 组件 但无法再使复制粘贴行为发挥作用 Shadow DOM 内的标记基本上是 span span
  • Mac OS X 想要在编译项目时使用系统钥匙串

    当我编译 Xcode 项目时 系统要求我输入系统管理员用户名和密码 整个消息是 Mac OS X 想要做出改变 输入管理员的名称和密码以允许执行此操作 Mac OS X 希望使用系统钥匙串 有人有解决方案吗 打开钥匙串访问 在左上角 解锁钥
  • 如何将内联 JavaScript 合并为一个?

    我正在修复我们在一个网站上使用的模板 其中包含以下代码 这个片段有效
  • C/C++ 函数指针的 UML 表示

    UML 结构图中 C C 函数指针 fp 的最佳表示是什么 我正在考虑使用接口元素 即使是 退化 但最多只能声明一个操作 I found some proposal in this document But this sounds quit
  • Android - getResources().getIdentifier 替换

    在 android 中 我循环遍历数据库并分配文本和图像 Cursor res myDb getAllData while res moveToNext Actors actor new Actors actor setName res g
  • XAML 相当于 HTML 中的 DIV?

    我想要更具体的是一个可以用于对一组其他元素进行分组的元素 而不影响它们的布局 除了通过将相关元素分组到其自己的父标记中来提供更好的 XAML 之外 它唯一应该做的就是传播环境属性 例如 DataContext 它应该是一个纯粹的逻辑元素 没
  • 从张量流模型获取权重

    您好 我想从张量流中微调 VGG 模型 我有两个问题 如何从网络获取权重 trainable variables 为我返回空列表 我使用了这里的现有模型 https github com ry tensorflow vgg16 https
  • 如何在播放框架中隐藏文本字段

    如何在播放框架中隐藏文本字段 例如如何隐藏该字段 inputText userProfileForm name label gt Name 这应该适用于所有浏览器 inputText userProfileForm name label g
  • Jenkins节点连接问题

    您好 我收到以下错误 但我的节点已启动 并且在詹金斯日志中一切正常 但在我的一些在节点上进行的作业中 我遇到了以下问题 12 59 29 EnvInject Loading node environment variables 12 59
  • PHP 和重音字符 (Ba\u015f\u00e7\u0131l)

    我有一个像 Ba u015f u00e7 u0131l 这样的字符串 我假设这些是一些特殊的重音字符 我如何能 1 显示带有重音符号的字符串 即用实际字符替换代码 2 存储这样的字符串的最佳实践是什么 2 如果我不想允许这样的字符 如何将其
  • 从 ASP.net Web 应用程序扫描文档

    我有一个 ASP Net C 4 0 Web 应用程序 我需要为我的用户添加扫描功能 这就是我想要实现的目标 在我的网络应用程序上 用户单击按钮 打开一个窗口 其中可预览连接到客户端系统的扫描设备中的文档 用户确认扫描 这将以 jpg pd
  • UIImageView子类需要处理resize

    我正在创建一个 UIImageView 子类来显示音频波形 方法是加载文件 进行数学计算 保存 PNG 文件 然后self image thePNG 这样做的好处是 在调整大小或重新绘制时 UIImageView 将拉伸 PNG 并快速拉伸
  • 动态规划和 0/1 背包

    尽管我已经阅读了很多资源试图理解动态编程 但我在理解动态编程方面遇到了一些困难 我理解使用斐波那契算法给出的动态规划的示例 我明白如果你使用分而治之的方法 你最终会多次解决一些子问题 而动态编程通过解决这些重叠的子问题但只解决一次 并存储它
  • Kafka CommitFailedException 消费者异常

    创建多个消费者 使用 Kafka 0 9 java API 并且每个线程启动后 我收到以下异常 Consumer has failed with exception org apache kafka clients consumer Com
  • 如何按重复值拆分数组?

    我有一个对象数组 我必须按重复值将其拆分index财产 对于像下一个这样的对象示例数组 index 0 value 3 index 0 value 3 index 0 value 3 index 1 value 3 index 1 valu
  • 将 Flex/Bison 与外部程序集成

    我正在开发一个智能代理模型 该模型需要事件列表作为输入 这些事件来自另一个模型的输出 位于 大 文本文件中 文本文件是所有事件的列表 包括我不关心的不必要事件 因此我使用 flex 编写了一个扫描器 可以找到有用的位 智能代理模型的框架已经
  • 为什么Java更喜欢调用双重构造函数?

    public class test test double a System out println in double test Object a System out println in object public static vo
  • Java 8 java.time:在 Instant 与 LocalDateTime 中添加 TemporalUnit

    我正在使用 Java 8 中的新 java time 包 我有一个遗留数据库 它为我提供了java util Date 我将其转换为Instant 我想做的是添加基于另一个数据库标志的一段时间 我可以添加天 周 月或年 我不想关心我要添加的