gpt4 book ai didi

java - 在 Java 中将纪元转换为 ZonedDateTime

转载 作者:行者123 更新时间:2023-11-30 07:50:02 26 4
gpt4 key购买 nike

如何在 java 中将 1413225446.92000 等纪元转换为 ZonedDateTime

给定的代码需要 long 值,因此这将为上面给定的值抛出 NumberFormatException

ZonedDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(dateInMillis)), ZoneId.of(TIME_ZONE_PST));

最佳答案

java.time可以直接解析你的字符串

编辑:如果您的毫秒值始终为非负值,则以下 DateTimeFormatter 可以解析它。

private static final String TIME_ZONE_PST = "America/Los_Angeles";
private static final DateTimeFormatter epochFormatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.INSTANT_SECONDS, 1, 19, SignStyle.NEVER)
.optionalStart()
.appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
.optionalEnd()
.toFormatter()
.withZone(ZoneId.of(TIME_ZONE_PST));

现在解析为 ZonedDateTime 只是一个方法调用:

    ZonedDateTime zdt = ZonedDateTime.parse(dateInMillis, epochFormatter);
System.out.println(zdt);

输出是:

2014-10-13T11:37:26.920-07:00[America/Los_Angeles]

它不能正确处理负值:分数仍会被解析为正数,我认为这是不正确的。为确保在出现负值时收到通知,我已在格式化程序中指定数字无法签名。

更通用的解决方案:使用 BigDecimal

如果您需要更通用的解决方案,例如包括负数,我认为最好让 BigDecinmal 解析数字并进行数学计算。

    BigDecimal bd = new BigDecimal(dateInMillis);
BigDecimal[] wholeAndFractional = bd.divideAndRemainder(BigDecimal.ONE);
long seconds = wholeAndFractional[0].longValueExact();
int nanos = wholeAndFractional[1].movePointRight(9).intValue();
ZonedDateTime zdt = Instant.ofEpochSecond(seconds, nanos)
.atZone(ZoneId.of(TIME_ZONE_PST));

输出与之前相同。只是现在我们也可以按照预期来处理负数了:

    String dateInMillis = "-1.5";

1969-12-31T15:59:58.500-08:00[America/Los_Angeles]

甚至接受科学记数法:

    String dateInMillis = "1.41322544692E9";

2014-10-13T11:37:26.920-07:00[America/Los_Angeles]

如果字符串中的精度可能高于纳秒,请考虑您希望如何截断或舍入,并相应地指示 BigDecimal,有多种选择。

原始答案

Basil Bourque’s answer是一个很好的。将纳秒从小数部分取出为纳秒的整数可能会导致一两个陷阱。我建议:

    String dateInMillis = "1413225446.92000";
String[] secondsAndFraction = dateInMillis.split("\\.");
int nanos = 0;
if (secondsAndFraction.length > 1) { // there’s a fractional part
// extend fractional part to 9 digits to obtain nanoseconds
String nanosecondsString
= (secondsAndFraction[1] + "000000000").substring(0, 9);
nanos = Integer.parseInt(nanosecondsString);
// if the double number was negative, the nanos must be too
if (dateInMillis.startsWith("-")) {
nanos = -nanos;
}
}
ZonedDateTime zdt = Instant
.ofEpochSecond(Long.parseLong(secondsAndFraction[0]), nanos)
.atZone(ZoneId.of("Asia/Manila"));
System.out.println(zdt);

这打印

2014-10-14T02:37:26.920+08:00[Asia/Manila]

纳秒不需要 64 位,所以我只使用 int

假设:我假设你的字符串包含一个 float 并且它可能是有符号的,例如 -1.50 意味着一秒半之前时代。如果有一天你的纪元时间以科学计数法 (1.41322544692E9) 出现,上面的方法将不起作用。

如果不是亚洲/马尼拉,请以地区/城市格式替换您想要的时区,例如美国/温哥华、美国/洛杉矶或太平洋/皮特凯恩。避免使用三个字母的缩写,例如 PST,它们含糊不清,而且通常不是真正的时区。

关于java - 在 Java 中将纪元转换为 ZonedDateTime,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47975195/

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