如何使用 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) 的相关文章

  • 通过 SSH 隧道远程访问 MySQL 数据库

    我正在尝试编写 Java 程序来使用 ssh 隧道访问远程 mySQL 数据库 下面是我的代码 int lport 5656 int rport 3306 String rhost 111 222 333 444 String host 1
  • 安卓。 onEditorAction 从未被调用

    我正在尝试捕捉从屏幕上移除键盘的事件 并且我正在使用OnEditorActionListener班级 然而 其onEditorAction方法永远不会被调用 这是我的 XML 格式的 EditText
  • 如何使用 IO Codenameone 发布图片/图像

    因为 codenameone 不能使用外部库 HttpConnection 所以我必须使用 Codenameone 提供的内部库 API 只是我已经设法使用 ConnectionRequest 将数据发布到格式化文本 字符串 我想知道是否有
  • 将比较器对象存储在数组中

    我为我的对象定义了 4 个比较器 如下所示 public static Comparator
  • 面试问题 - 在排序数组 X 中搜索索引 i,使得 X[i] = i

    昨天面试时 我被问到了以下问题 考虑一个 Java 或 C 数组X它已排序并且其中没有两个元素是相同的 如何最好地找到索引i这样该索引处的元素也是i 那是X i i 作为澄清 她还给了我一个例子 Array X 3 1 0 3 5 7 in
  • Hamcrest 泛型地狱 #2:iterable With Size 给出错误“不适用于参数”

    在 hamcrest 中 1 3 RC2 没有 JUnit 依赖项 我使用失败iterableWithSize 我有一个 扩展 Iterator参数化为Content像这样EndResult
  • 如何从 .t​​xt 文件读取数据并将数据放入对象的数组列表中?

    到目前为止 我所写的内容是基于我目前对基本数组的了解 但我只是不明白如何使用数组列表 或如何从文件中读取 到目前为止我所写的内容有效 任何有助于修复我的代码以从文件中读取并使用数组列表的链接或建议将不胜感激 谢谢 public class
  • 使用 ScheduledExecutorService 安排每月任务

    我想在该月的某一天的特定时间安排一项任务 每次运行之间的间隔可以设置在 1 到 12 个月之间 在java中 可以使用ScheduledExecutorService以固定的时间间隔调度任务 既然一个月的天数不固定 那么如何实现呢 提前致谢
  • JTable AutoCreateRowSorter 将数字排序为字符串

    我有一个 JTable JTable table new JTable String colNames c1 DefaultTableModel model new DefaultTableModel Integer x new Integ
  • 如何在 Android 中将 EditText 绘制到画布上?

    我想画画 EditText username new EditText context 到我画布上的特定位置 protected void onDraw Canvas canvas 是否可以在基础上画出x y在我的 Java 文件中协调而不
  • Java HttpURLConnection:内容长度计算

    我目前正在为 bitbucket issues RESTful API 开发一个库 我取得了很大的进步 现在我要解决这个部分更新问题 http confluence atlassian com display BBDEV Issues Is
  • Spring Batch:比较数据库之间的数据

    我有两个数据库 Oracle 和 MySQL 目标是将Oracle表中的值保存到MySQL中 要求 MySQL表中不存在数据 但我在理解 Spring Batch 时遇到了困难 步骤中 它包含itemReader itemProcessor
  • 小米和oppo等中国ROM上的工作管理器,在电池优化时,将工作的计划延迟增加几个小时

    小米和 Oppo 等中国 ROM 上的工作管理器在进行电池优化时 会将计划的工作延迟增加几个小时 但是 我注意到一些应用程序即使在电池优化下也能够让计划的作业安静地完美运行 我注意到的一个区别是 它们每次运行作业时都会显示一条通知 那么这是
  • 如何提高 Guice 启动时的性能

    好吧 我知道我的计算不客观等等 但无论如何 我讨厌在执行单元测试时等待这么多时间 我的 guice swing 应用程序需要大约 7 秒来初始化 这是一个简单的 IRC 客户端 在那一刻 没有打开连接 我什至还没有调用任何 java io
  • 按位非运算符

    为什么要按位运算 0 打印 1 在二进制中 不是0应该是1 为什么 你实际上很接近 在二进制中 不是0应该是1 是的 当我们谈论一位时 这是绝对正确的 然而 一个int其值为0的实际上是32位全零 将所有 32 个 0 反转为 32 个 1
  • 用java解密AES加密文件

    我有一个使用 AES 使用 java 应用程序加密的文件 我还有一个加密的密钥文件 但我不明白如何使用密钥来解密文件 大多数教程和示例都会在一个地方创建临时随机密钥 加密文件和解密 所以 问题是如何指定解密时必须使用的密钥 EDIT 我发现
  • 如何迭代SparseArray?

    有没有办法迭代 Java SparseArray 适用于 Android 我用了sparsearray通过索引轻松获取值 我找不到 看来我找到了解决方案 我没有正确注意到keyAt index 功能 所以我会这样做 for int i 0
  • 在java中设置Process对象的安全性

    有人可以告诉我如何限制通过进程对象访问系统属性吗 如果我通过进程对象运行以下代码 我可以抛出安全异常吗 System getProperty user home 请告诉我如何为流程对象配置证券 在ProcessBuilder类文档中 环境方
  • Android:如何以编程方式仅圆化位图的顶角?

    我目前正在使用这段代码 Override public Bitmap transform Bitmap source Bitmap result Bitmap createBitmap source getWidth source getH
  • 何时以及为何使用缓冲输入和输出流? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我读到这些是为了减少磁盘 网络调用开销而使用的 这在写操作的情况下似乎很好 但是进行缓冲读取有什么好处呢 如果您按字节读取文件 则每次都会进

随机推荐