如何使用 Java 8 DateTime API 从序列值本地日期时间获取 POSIX 时间 (UTC)

2024-01-08

我有一个类似于POSIX 时间 https://en.wikipedia.org/wiki/Unix_time唯一的例外是它不被计算在内UTC https://en.wikipedia.org/wiki/Coordinated_Universal_Time.

相反,它是自 1970 年 1 月 1 日午夜以来经过的毫秒数在特定的当地时区。为了使这个值变成Instant,我必须首先知道它与 UTC/GMT 的偏移量(以毫秒为单位)。

所以问题是这样的:知道本地时区 ID,例如。 “America/Chicago”和自本地纪元以来的毫秒数,如何创建一个 Instant(必须使用自 POSIX 纪元以来的毫秒数构建)?

似乎没有任何一个java.time API http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html构造函数接受本地 Epoch 中的毫秒参数。

我有一个解决方案,首先将本地毫秒日期时间转换为本地公历日期时间(然后我可以从中构造一个LocalDateTime并获得 UTC 的偏移量),但这似乎是一个很大的麻烦,因为它看起来应该非常简单。


跟踪日期时间的错误方法

首先我必须说一下 count-from- 的使用epoch https://en.wikipedia.org/wiki/Epoch_(reference_date)各种日期时间值的整数时区 https://en.wikipedia.org/wiki/Time_zone而不是使用 UTC 是一个非常非常糟糕的主意。我见过一些处理日期时间的糟糕方法,包括我自己发明的一两种糟糕的方法。但这是最糟糕的。想出这个主意的人应该被判一年每天阅读 StackOverflow 上标有“java”、“date”和“Jon Skeet”的答案。

在应用程序代码中使用 count-from-epoch 处理日期时间就像使用位数组处理文本一样。我们有 CharSequence、String、StringBuilder、Printer、Reader 等类/接口来处理文本、字符、字符编码、排序规则等的具体复杂细节,使我们可以更轻松地编写应用程序。想象一下尝试调试、排除故障并将文本数据记录为位数组。疯了,对吧?尝试调试、排除故障并将日期时间数据记录为长整数也是疯狂的。

日期时间也是如此,我们有乔达时间 http://www.joda.org/joda-time/现在有了它的继任者java.time http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html (Tutorial http://docs.oracle.com/javase/tutorial/datetime/TOC.html)内置于 Java 8 及更高版本中。

其次,隐式地将纪元计数调整为时区,然后丢失该事实会使不良做法变得更糟。

Fix

解决此问题的方法是将某个任意时区中的纪元计数转换为本地日期和本地时间,其中local意味着挂钟时间 https://en.wikipedia.org/wiki/Wall-clock_time正如比时区的人们所看到的那样。

有了本地日期时间,我们创建一个具有指定时区的日期时间对象,ZonedDateTime http://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html. A 分区日期时间基本上是一个Instant http://docs.oracle.com/javase/8/docs/api/java/time/Instant.html(UTC 时间线上的一个点)加上ZoneId http://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html(时区)。

由于问题的作者未能提供任何示例数据,让我们以这种奇怪的方式创建一个值。获取芝加哥时区的当前时刻。获取合法的纪元计数,调整自纳秒 https://en.wikipedia.org/wiki/Nanosecond决议毫秒 https://en.wikipedia.org/wiki/Millisecond。然后任意添加/减去该时区与 UTC 的偏移量。

在此示例中,我们使用时区America/Chicago https://en.wikipedia.org/wiki/List_of_tz_database_time_zones。我们的样本在夏令时的偏移量是-05:00。以毫秒为单位,5 * 60 * 60 * 1,000 = 18,000,000。

    // First, create sample data, a count-from-epoch but not in UTC, instead adjusted for the time zone’s offset.
ZoneId zoneId = ZoneId.of( "America/Chicago" );

// 2015-09-19T12:34:56.000-05:00[America/Chicago]
ZonedDateTime zdtTemp = ZonedDateTime.of( 2015 , 9 , 19 , 12 , 34 , 56 , 0 , zoneId );
long millisecondsFromEpoch = zdtTemp.toInstant().toEpochMilli(); // Loosing data, goin from nanosecond
long offsetInMillisecondsForChicagoInDaylightSavingTime = 18_000_000L;  // Offset of `-05:00` is in milliseconds, 5 * 60 * 60 * 1,000 = 18,000,000.
long input = ( millisecondsFromEpoch - offsetInMillisecondsForChicagoInDaylightSavingTime );

转储到控制台。

System.out.println( "zoneId : " + zoneId );
System.out.println( "zdtTemp : " + zdtTemp );
System.out.println( "millisecondsFromEpoch : " + millisecondsFromEpoch );
System.out.println( "offsetInMillisecondsForChicagoInDaylightSavingTime : " + offsetInMillisecondsForChicagoInDaylightSavingTime );
System.out.println( "input : " + input );

现在,做工作吧。采取这个奇怪的输入数字,假装它是 UTC,即使我们知道它不是,以产生一个 Instant。从 Instant 中获取 LocalDateTime。现在将 LocalDateTime 推入时区以获得我们最终想要的,ZonedDateTime.

// With example data in hand, proceed to convert to a valid date-time object.
Instant instantPretendingToBeInUtcButNotReally = Instant.ofEpochMilli( input );
LocalDateTime localDateTimeOfPretendInstant = LocalDateTime.ofInstant( instantPretendingToBeInUtcButNotReally , ZoneOffset.UTC );
ZonedDateTime zdt = localDateTimeOfPretendInstant.atZone( zoneId );

转储到控制台。

System.out.println( "instantPretendingToBeInUtcButNotReally : " + instantPretendingToBeInUtcButNotReally );
System.out.println( "localDateTimeOfPretendInstant : " + localDateTimeOfPretendInstant );
System.out.println( "zdt : " + zdt );

运行时。

zoneId : America/Chicago
zdtTemp : 2015-09-19T12:34:56-05:00[America/Chicago]
millisecondsFromEpoch : 1442684096000
offsetInMillisecondsForChicagoInDaylightSavingTime : 18000000
input : 1442666096000
instantPretendingToBeInUtcButNotReally : 2015-09-19T12:34:56Z
localDateTimeOfPretendInstant : 2015-09-19T12:34:56
zdt : 2015-09-19T12:34:56-05:00[America/Chicago]

CAVEAT我匆忙地做了这件事。请评论或修复任何错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Java 8 DateTime API 从序列值本地日期时间获取 POSIX 时间 (UTC) 的相关文章

  • Eclipse 在源代码管理中保存操作

    我们希望找到一种在签入之前执行代码标准的 轻量级 方法 我们真的很喜欢使用 Eclipse 内置的想法保存操作 go to Preferences gt gt Java gt gt Editor gt gt Save Actions 其中有
  • 如何使用 Java 中的 Web 服务(例如 Axis2)发送复杂对象的数组或集合?

    我对 SOAP Web 服务还比较陌生 虽然我完成了一些较小的 Web 服务项目 但我偶然从来不需要返回 或用作参数 复杂 对象的数组或集合 当我尝试这样做时 根据我的 SOAP 绑定风格 我会得到不同的奇怪行为 当我使用RPC 文字 我可
  • 在文本文件中写入多行(java)

    下面的代码是运行命令cmd并使用命令行的输出生成一个文本文件 下面的代码在 Eclipse 的输出窗口中显示了正确的信息 但在文本文件中只打印了最后一行 谁能帮我这个 import java io public class TextFile
  • Java:如何从转义的 URL 获取文件?

    我收到了一个定位本地文件的 URL 事实上我收到的 URL 不在我的控制范围内 URL 按照 RFC2396 中的定义进行有效转义 如何将其转换为 Java File 对象 有趣的是 URL getFile 方法返回一个字符串 而不是文件
  • org.apache.sling.api.resource,version=[2.3,3) -- 无法解析

    您好 我无法访问我的项目内容 我已经上传了从 CQ 访问内容所需的所有包 我唯一能看到的是 org apache sling api resource version 2 3 3 无法解析 这是否是异常的原因 如果是 请告诉我如何解决 中Q
  • OpenCV 中的 Gabor 内核参数

    我必须在我的应用程序中使用 Gabor 过滤器 但我不知道这个 OpenCV 方法参数值 我想对虹膜进行编码 启动 Gabor 过滤器并获取特征 我想对 12 组 Gabor 参数值执行此操作 然后我想计算 Hamming Dystans
  • 正则表达式拆分数字和字母组,不带空格

    如果我有一个像 11E12C108N 这样的字符串 它是字母组和数字组的串联 如何在中间没有分隔符空格字符的情况下分割它们 例如 我希望分割结果为 tokens 0 11 tokens 1 E tokens 2 12 tokens 3 C
  • 当从服务类中调用时,Spring @Transactional 不适用于带注释的方法

    在下面的代码中 当方法内部 是从内部调用的方法外部 应该在交易范围内 但事实并非如此 但当方法内部 直接从调用我的控制器class 它受到事务的约束 有什么解释吗 这是控制器类 Controller public class MyContr
  • 匿名类上的 NotSerializedException

    我有一个用于过滤项目的界面 public interface KeyValFilter extends Serializable public static final long serialVersionUID 7069537470113
  • 很好地处理数据库约束错误

    再一次 它应该很简单 我的任务是在我们的应用程序的域对象中放置一个具有唯一约束的特定字段 这本身并不是一个很大的挑战 我刚刚做了以下事情 public class Location more fields Column unique tru
  • 如何知道抛出了哪个异常

    我正在对我们的代码库进行审查 有很多这样的陈述 try doSomething catch Exception e 但我想要一种方法来知道 doSomething 抛出了哪个异常 在 doSomething 的实现中没有 throw 语句
  • 替换后增量

    我自己已经有一个问题了 但我想扩展它后增量示例 https stackoverflow com questions 51308967 post increment with example char a D int b 5 System o
  • javafx android 中的文本字段和组合框问题

    我在简单的 javafx android 应用程序中遇到问题 问题是我使用 gradle javafxmobile plugin 在 netbeans ide 中构建了非常简单的应用程序 其中包含一些文本字段和组合框 我在 android
  • 具有特定参数的 Spring AOP 切入点

    我需要创建一个我觉得很难描述的方面 所以让我指出一下想法 com x y 包 或任何子包 中的任何方法 一个方法参数是接口 javax portlet PortletRequest 的实现 该方法中可能有更多参数 它们可以是任何顺序 我需要
  • hashcode 的默认实现为以相同方式构造的对象返回不同的值

    我在这里编写一个示例代码 public class Test private int i private int j public Test TODO Auto generated constructor stub public Test
  • 调整添加的绘制组件的大小和奇怪的摆动行为

    这个问题困扰了我好几天 我正在制作一个特殊的绘画程序 我制作了一个 JPanel 并添加了使用 Paint 方法绘制的自定义 jComponent 问题是 每当我调整窗口大小时 所有添加的组件都会 消失 或者只是不绘制 因此我最终会得到一个
  • 在 RESTful Web 服务中实现注销

    我正在开发一个需要注销服务的移动应用程序 登录服务是通过数据库验证来完成的 现在我陷入了注销状态 退一步 您没有提供有关如何在应用程序中执行身份验证的详细信息 并且很难猜测您在做什么 但是 需要注意的是 在 REST 应用程序中 不能有会话
  • 带有 Maven Wrapper 的 Java 17 导致无法识别的 VM 选项“MaxPermSize=512m”

    I use OpenJDK 17 https jdk java net 17 使用 Maven Wrapper 3 8 2 从春季初始化 https start spring io Maven项目 JAR打包 Java 17 Spring
  • 如何修复:“无法解析类型 java.lang.CharSequence。它是从所需的 .class 文件间接引用的”消息? [复制]

    这个问题在这里已经有答案了 我正在尝试使用这个字符串 amountStr amountStr replace replace replace 但我收到一条错误消息 我知道我收到的错误消息是因为我刚刚发布的字符串已过时 所以我想知道该字符串的
  • 如何在 JFreeChart 中设置多个系列的线条粗细?

    我创建了很多图表 在他们每个人中我都需要打电话 renderer setSeriesStroke i new BasicStroke 2 0f 对于每个系列 renderer is chart getXYPlot getRenderer 我

随机推荐