【问题标题】:Convert ISO 8601 Date to a Standard String Format将 ISO 8601 日期转换为标准字符串格式
【发布时间】:2015-02-05 19:33:37
【问题描述】:

我正在尝试将有效的ISO 8601 字符串转换为一致的格式,以便可以使用简单的字典顺序进行排序和搜索。

我的应用程序可以接收以下任何格式的日期/时间,例如:

2015-02-05T02:05:17.000+00:00
2015-02-05T02:05:17+00:00
2015-02-05T02:05:17Z

这些都代表相同的日期/时间,我想将它们全部转换为规范形式进行存储,例如:

2015-02-05T02:05:17.000Z

我的第一个想法是使用Converting ISO 8601-compliant String to java.util.Date 中的技术来解析它们,然后转换回所需的字符串,但是在处理不太精确的日期/时间时会出现问题,例如:

2015-02-05T02:05:17Z
2015-02-05T02:05Z
2015-02-05Z
2015-02Z
2015Z

应该保留这些时间的不精确性。它们不应转换为:

2015-02-05T00:00:00.000Z

我看过 Java 8 和 Joda-Time,但他们似乎希望将所有内容都视为特定的时间点,并且无法对不精确的性质或部分日期/时间进行建模。

更新:

使用 Java 8,我可以做到:

OffsetDateTime dateTime = OffsetDateTime.parse("2015-02-05T02:05:17+00:00");
System.out.println(dateTime.toString());

这给了我:

2015-02-05T02:05:17Z

这是我想要的,但是:

OffsetDateTime dateTime = OffsetDateTime.parse("2015-02-05T02:05:17.000+00:00");
System.out.println(dateTime.toString());

也给了我:

2015-02-05T02:05:17Z

请注意,java 已经抛弃了毫秒精度。指定 000 被视为与不指定任何内容相同,这似乎不太正确。

【问题讨论】:

  • 2015-02-05T02:05:17+0000 不是有效的 ISO 日期。
  • 维基百科建议 +0000 是一个有效的偏移量。你有更好的参考吗?
  • 我认为没有一个对象可以保存您定义的限制(即部分精度)的日期。所以你最好的选择是使用你自己的代表。
  • @JamesScriven,如果 WP 这么说,那就错了。您要么以扩展格式或以标准格式提供所有部分,但没有以混合方式提供。请参阅我在泽西岛的comment。如果你愿意,我可以引用 ISO 8601 的章节。
  • @Michael-O 基本符号和扩展符号之间的区别在我的脑海中并不清楚。我已经更新了问题以删除不良示例。谢谢。

标签: java jodatime iso8601


【解决方案1】:

在 Java 8 中,如果字符串为 ISO 8601 格式,您可以在 String 上使用 LocalDate.parse()LocalDateTime.parse() 而无需为其提供模式。

parse(), 从 2007-12-03 等文本字符串中获取 LocalDate 的实例。 该字符串必须代表一个有效的日期,并使用 DateTimeFormatter.ISO_LOCAL_DATE。

和,

DateTimeFormatter.ISO_LOCAL_DATE, 这将返回一个能够格式化和解析的不可变格式化程序 ISO 8601

例如,

String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
System.out.println("Date: " + aLD);

String strDatewithTime = "2015-08-04T10:11:30";
LocalDateTime aLDT = LocalDateTime.parse(strDatewithTime);
System.out.println("Date with Time: " + aLDT);

给予,

Date: 2015-08-04
Date with Time: 2015-08-04T10:11:30

更新:

您的日期,即"2015-02-05T02:05:17.000+00:00" 只会在以下情况下丢弃零 它们都是零,如果纳秒的值不是零,那么它会显示得很好,但是,如果你也想显示零,那么你可以简单地添加 if/else 块并将零附加到你的日期 if 你的纳秒是零 (yourdate.getNano()==0),else 按原样打印,

String dateTimestr = "2015-02-05T02:05:17.000+00:00";

OffsetDateTime dateTime = OffsetDateTime.parse(dateTimestr);

if ((dateTime.getNano() == 0) && (dateTimestr.length() > 25 ))
    System.out.println(dateTime.toLocalDateTime() + ".000Z");

else
    System.out.println(dateTime.toString());

会给,

2015-02-05T02:05:17.000Z

将日期更改为,

String dateTimestr = "2015-02-05T02:05:17+00:00";

给予,

2015-02-05T02:05:17Z

将日期更改为,

String dateTimestr = "2015-02-05T02:05:17.100+00:00";

给予,

2015-02-05T02:05:17.100Z

改成,

String dateTimestr = "2015-02-05T02:05:17Z";

给予,

2015-02-05T02:05:17Z

【讨论】:

  • 这非常有用,但请查看我的更新以了解为什么它不能正常工作。
  • 我不清楚这如何解决保持精度(和缺乏精度)的问题
【解决方案2】:

您必须了解保持精度只能发生在文本空间中,而不能发生在值空间中。因此,可以以文本方式(请参阅您的输入)表示不同程度的精度,但不能以值对象(此处为 OffsetDateTime 类型)表示。后者仅存储日期时间值,但不存储任何额外的精度信息。如果你真的想实现这个目标,那么你别无选择,只能编写自己的类作为 OffsetDateTime 和精度(表示为 ChronoUnit-enum)的包装器。

否则,如果您总是希望以毫秒为单位为您的输出保留精度,那么您不应该使用toString()-方法,而是使用专用的格式化程序。在 Java-8 中是这样的:

OffsetDateTime odt = OffsetDateTime.parse("2015-02-05T02:05:17+00:00");
String dateTimeWithMilliSecondPrecision = 
  odt.format(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxxx"));
System.out.println(dateTimeWithMilliSecondPrecision);
// output: 2015-02-05T02:05:17.000+00:00

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    • 2016-12-14
    相关资源
    最近更新 更多