如何在Java中使用时间戳 48962-08-06T23:16:59.000Z 获取Instant对象

huangapple go评论73阅读模式
英文:

How do I get an Instant object with the timestamp 48962-08-06T23:16:59.000Z in Java

问题

我有一个日期字符串,我想将其解析为Instant:48962-08-06T23:16:59.000Z,但是由于大多数标准的DateTimeFormatter规则不支持它,所以无法实现。

参考:https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

以下是我尝试使用自定义格式化器的操作示例:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendValue(YEAR, 5, 10, SignStyle.EXCEEDS_PAD)
            .appendLiteral('-')
            .appendValue(MONTH_OF_YEAR, 2)
            .appendLiteral('-')
            .appendValue(DAY_OF_MONTH, 2)
            .appendLiteral('T')
            .appendValue(HOUR_OF_DAY, 2).appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR, 2).appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE, 2)
            .appendFraction(NANO_OF_SECOND, 0, 9, true)
            .appendLiteral('Z')
            .toFormatter();
    
    Instant value = Instant.from(formatter.parse("48962-08-06T23:16:59.000Z"));

但是它失败并显示错误消息:无法从TemporalAccessor获取Instant:{},ISO解析为类型为java.time.format.Parsed的+48962-08-06T23:16:59

英文:

I have a date string which I want to parse as Instant
48962-08-06T23:16:59.000Z but unable to do as most of standard DateTimeFormatter rules are not supporting it.

Ref: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

Here is what I was trying to do, using my custom formatter

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendValue(YEAR, 5, 10, SignStyle.EXCEEDS_PAD)
            .appendLiteral('-')
            .appendValue(MONTH_OF_YEAR, 2)
            .appendLiteral('-')
            .appendValue(DAY_OF_MONTH, 2)
            .appendLiteral('T')
            .appendValue(HOUR_OF_DAY, 2).appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR, 2).appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE, 2)
            .appendFraction(NANO_OF_SECOND, 0, 9, true)
            .appendLiteral('Z')
            .toFormatter();
    
    Instant value = Instant.from(formatter.parse("48962-08-06T23:16:59.000Z"));

But it fails with Unable to obtain Instant from TemporalAccessor: {},ISO resolved to +48962-08-06T23:16:59 of type java.time.format.Parsed

答案1

得分: 4

在我的机器上,以下代码解析了您未来的年份:

public static void main(String[] args) {
	String dateTime = "48962-08-06T23:16:59.000Z";
	DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuuu-MM-dd'T'HH:mm:ss.SSSz");
	Instant instant = Instant.from(dtf.parse(dateTime));
	System.out.println(instant);
}

并且输出

+48962-08-06T23:16:59Z

我认为您的代码问题可能出在以下一行(或两行):

            .appendFraction(NANO_OF_SECOND, 0, 9, true)
            .appendLiteral('Z')

因为在String中,点号后面且Z前面的三个数字可能不是纳秒,而是秒的分数部分。另一行代码也可能有问题,但我不能确定问题所在。我只知道,将模式中的小写z更改为大写Z时,我的答案会抛出异常。

您可以调整DateTimeFormatter中的内容,然后再次尝试,可能会起作用。

英文:

On my machine, the following code parses your future year:

public static void main(String[] args) {
	String dateTime = "48962-08-06T23:16:59.000Z";
	DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuuu-MM-dd'T'HH:mm:ss.SSSz");
	Instant instant = Instant.from(dtf.parse(dateTime));
	System.out.println(instant);
}

and outputs

+48962-08-06T23:16:59Z

I think the problem with your code is one (or both) of the lines

            .appendFraction(NANO_OF_SECOND, 0, 9, true)
            .appendLiteral('Z')

because the three digits after the dot and before the Z in the String might not be nanos of second but rather fraction of second.
And the other line might be problematic, too, but I can't really tell you why. I only know that my answer would throw an exception when the z (lower case) in the pattern is changed to a Z (upper case).

You could adjust that in your DateTimeFormatter and try again, might work.

答案2

得分: 3

我同意你的观点,使用构建器是一个不错的解决方案。以下代码解析了包含4位和5位数年份的日期:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .appendValue(ChronoField.YEAR, 4, 5, SignStyle.NOT_NEGATIVE)
        .appendPattern("-MM-dd'T'")
        .append(DateTimeFormatter.ISO_LOCAL_TIME)
        .appendOffsetId()
        .toFormatter();

String dateTime = "48962-08-06T23:16:59.000Z";

Instant i = formatter.parse(dateTime, Instant::from);

System.out.println(i);

代码片段的输出结果为:

+48962-08-06T23:16:59Z

你的基本问题在于你的字符串不符合 ISO 8601 标准,而 java.time 类的默认解析方式就是按照这个标准进行解析的,即在没有明确指定格式化器的情况下。ISO 8601 允许使用超过4位数字的年份,但在这种情况下需要使用符号(正如你在输出中看到的)。在你的代码中出了什么问题?正如 Joachim Sauer 在评论中指出的,将 Z 硬编码为文字是错误的。Z 代表与 UTC 的偏移量为0,并且需要被解析为一个偏移量。由于你的格式化器没有解析任何偏移量,它无法从解析的信息中确定一个时间点,即一个时刻。这就是你收到的错误消息的含义:

Unable to obtain Instant from TemporalAccessor: {},ISO resolved to
+48962-08-06T23:16:59 of type java.time.format.Parsed
英文:

I agree with you that the nice solution is using a builder. The following one parses years with both 4 and 5 digits:

	DateTimeFormatter formatter = new DateTimeFormatterBuilder()
			.appendValue(ChronoField.YEAR, 4, 5, SignStyle.NOT_NEGATIVE)
			.appendPattern("-MM-dd'T'")
			.append(DateTimeFormatter.ISO_LOCAL_TIME)
			.appendOffsetId()
			.toFormatter();
	
	String dateTime = "48962-08-06T23:16:59.000Z";
	
	Instant i = formatter.parse(dateTime, Instant::from);
	
	System.out.println(i);

Output from the snippet is:

> +48962-08-06T23:16:59Z

Your basic problem is that your string doesn’t conform with ISO 8601, the standard that the classes of java.time parse as their default, that is, without any explicit formatter. Years with more than 4 digits can be allowed in ISO 8601, but then a sign is required (as you can also see in the output above).

What went wrong in your code? Joachim Sauer is correct in the comment: Hardcoding Z as a literal is wrong. It’s an offset of 0 from UTC and needs to be parsed as an offset. Since your formatter didn’t parse any offset, it was unable to determine a point int time, an instant, from the parsed information. This was what your error message meant:

> Unable to obtain Instant from TemporalAccessor: {},ISO resolved to
> +48962-08-06T23:16:59 of type java.time.format.Parsed

huangapple
  • 本文由 发表于 2020年9月11日 16:56:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/63843844.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定