gpt4 book ai didi

java - 将自 01-01-1900 以来的秒数转换为巴西时间戳

转载 作者:搜寻专家 更新时间:2023-11-01 01:24:38 26 4
gpt4 key购买 nike

我管理的设备将其系统时钟报告为自 1900 年 1 月 1 日午夜以来的秒数。
我需要将其转换为时间戳。

到目前为止,我是这样做的:

import java.text.SimpleDateFormat;
import java.util.Calendar;

public class TestTime
{
// Pass seconds since 01-01-1900 00:00:00 on the command line
public static void main(String[] args)
{
// ---------------------
// Create time formatter
// ---------------------
SimpleDateFormat format;
format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

// ---------------------------
// Compose 01-01-1900 00:00:00
// ---------------------------
Calendar cal;
cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1900);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);

// -------------------
// Show what we've got
// -------------------
System.out.println(format.format(cal.getTime()));

// ---------------------------------------------
// Add the seconds as passed on the command line
// ---------------------------------------------
long secs = Long.parseLong(args[0]);
while (secs > Integer.MAX_VALUE)
{
cal.add(Calendar.SECOND, Integer.MAX_VALUE);
secs -= Integer.MAX_VALUE;
}
cal.add(Calendar.SECOND, (int)secs);

// -------------------
// Show what we've got
// -------------------
System.out.println(args[0] + " corresponds to " + format.format(cal.getTime()));

} // main

} // class TestTime

在我的本地 PC(意大利,Windows 7)上运行它时,我得到以下信息:

java -cp . TestTime 3752388800
1900-01-01 00:00:00
3752388800 corresponds to 2018-11-28 10:13:20

这是完全正确的。
在 Linux 机器(仍在意大利)上运行时,我得到了相同的结果。

然而,在巴西的 Linux 机器上运行完全相同的程序,我得到了不同的结果:

java -cp . TestTime 3752388800
1900-01-01 00:00:00
3752388800 corresponds to 2018-11-28 11:19:48

无论我在命令行上传递什么值,差异总是 01:06:28。
知道这种差异从何而来吗?

顺便说一句,我不关心时区。我只需要一个时间戳

更新 1:
使用 Java 6(这是我们在巴西的生产环境中使用的实际版本)时也会发生同样的事情。
所以,这个问题不依赖于java版本

更新 2:
输入低于 441763200(对应于 01-01-1914 00:00:00)的秒数时不会出现此问题问题仍然是为什么我们对巴西有所不同?

最佳答案

java.time

一个解决方案是确保您在 UTC 中进行转换:

    Instant base = LocalDate.of(1900, Month.JANUARY, 1)
.atStartOfDay(ZoneOffset.UTC)
.toInstant();

String secsSince1900String = "3752388800";
long secsSince1900 = Long.parseLong(secsSince1900String);
Instant target = base.plusSeconds(secsSince1900);
System.out.println(target);

输出(独立于 JVM 时区):

2018-11-28T10:13:20Z

输出中尾随的 Z 表示 UTC。我在将 JVM 的默认时区设置为 America/Sao_Paulo 时进行了测试,没有任何区别。如果需要,您可以根据自己的喜好设置日期和时间,例如:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = target.atOffset(ZoneOffset.UTC).format(formatter);
System.out.println(formattedDateTime);

2018-11-28 10:13:20

在巴西运行时出了什么问题?

巴西有多个时区。我以圣保罗为例,很容易地复制了您的输出。在 1900 世纪之交,圣保罗与格林威治标准时间的偏移量为 -03:06:28。您的 Calendar 使用 JVM 的默认时区,因此您实际上将其时间设置为格林威治标准时间 03:06:28,这解释了差异。

也就是说,您使用的日期时间类 — SimpleDateFormatCalendar — 存在设计问题,幸运的是已被现代 Java 日期 java.time 取代和时间 API,近 5 年前使用 Java 8。现代 API 的一个特点是我们更自然地使时区明确,这样可以更容易地避免像您这样的问题,并且如果我们遇到它们也可以修复它们。

问题:我们的生产 Java 版本是 Java 6,我可以使用 java.time 吗?

是的,java.time 在 Java 6 上运行良好。它已被向后移植。

  • 在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 开始)中,现代 API 是内置的。
  • 在 Java 6 和 7 中获取 ThreeTen Backport,新类的反向端口(ThreeTen for JSR 310;查看底部的链接)。
  • 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它叫做 ThreeTenABP。并确保使用子包从 org.threeten.bp 导入日期和时间类。

链接

关于java - 将自 01-01-1900 以来的秒数转换为巴西时间戳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53517467/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com