Java 将ISO 8601日期转换为标准字符串格式

Java 将ISO 8601日期转换为标准字符串格式,java,jodatime,iso8601,Java,Jodatime,Iso8601,我正在尝试将有效字符串转换为一致的格式,以便使用简单的字典顺序进行排序和搜索 我的应用程序可以接收以下任何格式的日期/时间,例如: 2015-02-05T02:05:17.000+00:00 2015-02-05T02:05:17+00:00 2015-02-05T02:05:17Z 2015-02-05T02:05:17Z 2015-02-05T02:05Z 2015-02-05Z 2015-02Z 2015Z 这些都表示相同的日期/时间,我想将它们全部转换为存储的标准形式,例如: 201

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

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

2015-02-05T02:05:17.000+00:00
2015-02-05T02:05:17+00:00
2015-02-05T02:05:17Z
2015-02-05T02:05:17Z
2015-02-05T02:05Z
2015-02-05Z
2015-02Z
2015Z
这些都表示相同的日期/时间,我想将它们全部转换为存储的标准形式,例如:

2015-02-05T02:05:17.000Z
我的第一个想法是使用技术从解析它们,然后将其转换回所需的字符串,但在处理不太精确的日期/时间时,这会发生故障,例如:

2015-02-05T02:05:17.000+00:00
2015-02-05T02:05:17+00:00
2015-02-05T02:05:17Z
2015-02-05T02:05:17Z
2015-02-05T02:05Z
2015-02-05Z
2015-02Z
2015Z
应该保留这些时间的不精确性。它们不应转换为:

2015-02-05T00:00:00.000Z
我看过Java8和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
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
2015-02-05T02:05:17Z
请注意,java已经放弃了毫秒精度。指定000与不指定任何内容一样,这似乎不太正确

在Java 8中,如果字符串采用ISO 8601格式,则可以在
字符串上使用或,而无需为其提供模式

parse()
, 从文本字符串(如2007-12-03)获取LocalDate的实例。 字符串必须表示有效日期,并使用 DateTimeFormatter.ISO\u本地\u日期

以及

DateTimeFormatter.ISO\u LOCAL\u 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);

更新:

您的日期,即
“2015-02-05T02:05:17.000+00:00”
在 它们都是零,如果nano seconds的值不是零,那么它将显示得很好,但是,如果你想也显示零,那么你可以简单地添加
if/else
块并将零附加到日期
如果你的nano seconds是零(
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());
会给,

把你的约会改成

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

将日期更改为

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

改成

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


您必须了解,保持精度只能发生在文本空间,而不能发生在值空间。因此,不同程度的精度可以用文本的方式表示(请参见您的输入),但不能用value对象来表示(这里的类型为
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

2015-02-05T02:05:17+0000
不是有效的ISO日期。维基百科建议+0000是有效的偏移量。你有更好的参考吗?我不认为有一个对象可以用你定义的限制(即部分精度)保存日期。所以你最好的办法是使用你自己的表示法。@JamesScriven,如果WP这么说,那就错了。您可以以扩展格式或标准格式提供所有零件,但不能以混合方式提供。关于这件事,请看我的球衣。如果你愿意的话,我可以引用ISO8601的章节。@Michael-O基本符号和扩展符号之间的区别在我脑子里并不清楚。我已经更新了问题,删除了不好的例子。谢谢。这非常有用,但请查看我的更新,了解它为什么不起作用。我不清楚这是如何解决保持精度(和缺少精度)的问题的
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