我想贡献现代答案。因为我不鼓励使用SimpleDateFormat
,稍后会详细介绍。
java.time
OffsetDateTime dateTime = OffsetDateTime.now(ZoneId.of("Europe/Rome"));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxx");
String text = dateTime.format(formatter);
OffsetDateTime test = OffsetDateTime.parse(text, formatter);
这会产生一个类似于 的字符串2018-02-07T17:51:21.087+0100
,非常接近我认为您在问题中所追求的字符串,并且可以很好地解析它。在SSS
格式模式字符串中,它总是在秒上产生 3 个小数,并且通过解析也需要 3 个小数。例如,您可以使用S
或SSSSSS
获得 1 位或 6 位小数。在我的 Java 9OffsetDateTime.now()
上,精度为 6 位小数(微秒),所以如果我指定的更少,我会失去格式的精度。
编辑:为了向后兼容,您不能使用以下内容,但对于任何阅读的人,我想提供一个没有显式格式化程序的变体:
String text = dateTime.toString();
OffsetDateTime test = OffsetDateTime.parse(text);
生成的字符串的两个区别是:
- 它产生尽可能多的 3 位小数组,以呈现精度。在我的 Java 8 上通常是 3 个小数,在我的 Java 9 上是 6 个小数,但有时它会达到毫秒的整数并产生更少的小数。它解析从 0 到 9 位小数的所有字符串,因此这不会在解析中出现问题。而且我始终保留原始
OffsetDateTime
对象的完整精度。
- 与 UTC 的偏移量以冒号呈现,例如
+01:00
.
你的代码出了什么问题?
这个SimpleDateFormat
类早已过时并且出了名的麻烦,所以即使你目前没有遇到问题,我仍然建议你放弃它并使用java.time
现代 Java 日期和时间 API,就像我在上面所做的那样。
SimpleDateFormat
旧版和现代版之间的一个区别DateTimeFormatter
是,虽然S
在现代格式化程序中表示秒的几分之一,SimpleDateFormat
但它表示毫秒,所以除三之外的任何其他数字都是没有意义的。但是,它接受其他数字。格式化时,您的格式化程序为毫秒生成了足够的数字,例如,89
如果有 21.089 秒或214
问题中的 13.214 时。前者不正确,21.089 秒被呈现为21.89
. 我坚信三位数的毫秒数会导致您的解析失败,而您只有一个S
. 在我的 Java 8 和 9 上,它可以工作,并且解析21.89
为 21 秒 89 毫秒,因此错误会消失。
这种行为与 Java 9 文档一致,该文档指出:“对于格式化,模式字母的数量是最小位数,较短的数字在此数量上补零。对于解析,模式字母的数量会被忽略,除非需要分隔两个相邻的字段。”</p>
关联