java.time 无法解析秒的小数部分吗?
随着 Mac OS X (Mavericks) 上 Java 8 (b132) 的第一个版本,此代码使用新的 java.time package 工作:
String input = "20111203123456";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmss");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
渲染:
2011-12-03T12:34:56
但是当我添加“SS”作为秒分数(和“55”作为输入)时,如<一href="https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html" rel="noreferrer">DateTimeFormatter 类文档,抛出异常:
java.time.format.DateTimeParseException: Text '2011120312345655' could not be parsed at index 0
该文档表示默认使用严格模式,并且需要与输入数字相同数量的格式字符。所以我很困惑为什么这段代码会失败:
String input = "2011120312345655";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
使用文档中的示例的另一个示例(“978”)(失败):
String input = "20111203123456978";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
此示例有效,添加小数点(但我在文档中发现没有这样的要求):
String input = "20111203123456.978";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmss.SSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
渲染:
localDateTime: 2011-12-03T12:34:56.978
省略句点输入字符串或格式中的字符会导致失败。
失败:
String input = "20111203123456.978";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
失败:
String input = "20111203123456978";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmss.SSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
With the first release of Java 8 (b132) on Mac OS X (Mavericks), this code using the new java.time package works:
String input = "20111203123456";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmss");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
Rendering:
2011-12-03T12:34:56
But when I add "SS" for fraction-of-second (and "55" as input), as specified in the DateTimeFormatter class doc, an exception is thrown:
java.time.format.DateTimeParseException: Text '2011120312345655' could not be parsed at index 0
The doc says Strict mode is used by default and requires the same number of format characters as input digits. So I'm confused why this code fails:
String input = "2011120312345655";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
Another example using example from documentation ("978") (fails):
String input = "20111203123456978";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
This example works, adding a decimal point (but I find no such requirement in the doc):
String input = "20111203123456.978";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmss.SSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
Renders:
localDateTime: 2011-12-03T12:34:56.978
Omitting the period character from either the input string or the format cause a fail.
Fails:
String input = "20111203123456.978";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
Fails:
String input = "20111203123456978";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmss.SSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Bug – 在 Java 9 中已修复
此问题已在 JDK-bug-log 中报告。 Stephen Colebourne 提到了以下解决方案作为解决方案:
注意:此解决方案不涵盖仅两个模式符号 SS 的用例。调整可能只是使用其他字段,例如 MICRO_OF_SECOND(6 倍 SSSSSS)或 NANO_OF_SECOND(9 倍 SSSSSSSS)。对于两个小数位,请参阅下面我的更新。
@PeterLawrey关于模式符号“S”的含义请参见 this文档:
所以我们看到 S 代表秒的任何分数(包括纳秒),而不仅仅是毫秒。此外,不幸的是,小数部分目前在相邻值解析中表现不佳。
编辑:
作为背景,这里有一些关于相邻值解析的评论。只要字段由小数点或时间部分分隔符(冒号)之类的文字分隔,要解析的文本中的字段的解释并不困难,因为解析器然后很容易知道何时停止,即字段部分何时结束并且当下一个字段开始时。因此,如果指定小数点,JSR-310 解析器就可以处理文本序列。
但是,如果您有一系列跨越多个字段的相邻数字,那么就会出现一些实现困难。为了让解析器知道字段何时在文本中停止,有必要提前指示解析器给定字段由固定宽度的数字字符表示。这适用于所有采用数字表示的
appendValue(...)
方法。不幸的是,JSR-310 也未能很好地处理小数部分 (
appendFraction(...)
)。如果您在DateTimeFormatterBuilder
类的 javadoc 中查找关键字“adjacent”,那么您会发现此功能只能通过appendValue(...)
方法实现。请注意,模式字母 S 的规范略有不同,但内部委托给appendFraction()
方法。我认为我们至少要等到 Java 9(如 JDK-bug-log 中所报告的,或更高版本???),直到小数部分也可以管理相邻值解析。自 2015 年 11 月 25 日更新:
以下仅使用两个小数位的代码不起作用,并且会误解毫秒部分:
解决方法
不起作用,因为
SimpleDateFormat
将小数解释为也是一种错误的方式,类似于现代示例(参见输出,55 毫秒而不是 550 毫秒)。剩下的解决方案要么等待很长一段时间直到 Java 9(或更高版本?),要么编写自己的 hack 或使用第 3 方库作为解决方案。
基于肮脏黑客的解决方案:
使用 Joda-Time 的解决方案 a>:
使用我的库的解决方案Time4J:
更新自2016-04-29:
正如人们通过上面提到的 JDK 问题所看到的,它现在被标记为已解决 - 对于 Java 9。
Bug – Fixed in Java 9
This issue was already reported in JDK-bug-log. Stephen Colebourne mentions as work-around following solution:
Note: This workaround does not cover your use-case of only two pattern symbols SS. An adjustment might only be to use other fields like MICRO_OF_SECOND (6 times SSSSSS) or NANO_OF_SECOND (9 times SSSSSSSSS). For two fraction digits see my update below.
@PeterLawrey About the meaning of pattern symbol "S" see this documentation:
So we see that S stands for any fraction of second (including nanosecond), not just milliseconds. Furthermore, the fractional part does at the moment not take well in adjacent value parsing, unfortunately.
EDIT:
As background here some remarks about adjacent value parsing. As long as fields are separated by literals like a decimal point or time part separators (colon), the interpretation of fields in a text to be parsed is not difficult because the parser then knows easily when to stop i.e. when the field part is ended and when the next field starts. Therefore the JSR-310 parser can process the text sequence if you specify a decimal point.
But if you have a sequence of adjacent digits spanning over multiple fields then some implementation difficulties arise. In order to let the parser know when a field stops in text it is necessary to instruct the parser in advance that a given field is represented by a fixed-width of digit chars. This works with all
appendValue(...)
-methods which assume numerical representations.Unfortunately JSR-310 has not managed well to do this also with the fractional part (
appendFraction(...)
). If you look for the keyword "adjacent" in the javadoc of classDateTimeFormatterBuilder
then you find that this feature is ONLY realized byappendValue(...)
-methods. Note that the spec for pattern letter S is slightly different but internally delegates toappendFraction()
-method. I assume we will at least have to waint until Java 9 (as reported in JDK-bug-log, or later???) until fraction parts can manage adjacent value parsing as well.Update from 2015-11-25:
The following code using two fraction digits only does not work and misinterpretes the millisecond part:
The workaround
does not work because
SimpleDateFormat
interpretes the fraction in a wrong way, too, similar to the modern example (see output, 55 ms instead of 550 ms).What is left as solution is either waiting an undertermined long time until Java 9 (or later?) or writing your own hack or using 3rd-party libraries as solution.
Solution based on a dirty hack:
Solution using Joda-Time:
Solution using my library Time4J:
Update from 2016-04-29:
As people can see via the JDK-issue mentioned above, it is now marked as resolved - for Java 9.
像这样的事情帮助了我
Something like this helped me
下面是一个算法,用于调整通常从格式化日期
String
返回的尾随零的顺序。Here's an algorithm which adjusts the order of the trailing zeros that are conventionally returned from the formatted date
String
.