简体   繁体   English

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

[英]Convert ISO 8601 Date to a Standard String Format

I am trying to convert a valid ISO 8601 string to a consistent format so that sort and search using simple lexicographical order is possible. 我正在尝试将有效的ISO 8601字符串转换为一致的格式,以便可以使用简单的字典顺序进行排序和搜索。

My application could receive a date/time in any of the following formats, for example: 我的应用程序可以使用以下任何格式接收日期/时间,例如:

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

These all represent the same date/time and I would like to convert them all to a canonical form for storage, say: 这些都代表相同的日期/时间,我想将它们全部转换为规范的存储形式,例如:

2015-02-05T02:05:17.000Z

My first thought was to just parse them using a technique from Converting ISO 8601-compliant String to java.util.Date , and then convert back to the desired string, but this breaks down when dealing with less precise date/times, for example: 我的第一个想法是使用从将ISO 8601兼容的String转换为java.util.Date的技术解析它们,然后转换回所需的字符串,但在处理不太精确的日期/时间时会出现故障,例如:

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

The imprecision of these times should be preserved. 应该保留这些时代的不精确性。 They should not be converted to: 它们不应转换为:

2015-02-05T00:00:00.000Z

I've looked Java 8 and Joda-Time, but they seem to want to treat everything as specific points in time, and can't model the imprecise nature or partial dates/times. 我看过Java 8和Joda-Time,但他们似乎想把所有内容都视为特定的时间点,并且不能模拟不精确的性质或部分日期/时间。

UPDATE: 更新:

Using Java 8, I can do: 使用Java 8,我可以这样做:

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

which gives me: 这给了我:

2015-02-05T02:05:17Z

which is what I want, but: 这是我想要的,但是:

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

also gives me: 也给了我:

2015-02-05T02:05:17Z

Notice that java has thrown away the millisecond precision. 请注意,java已经抛弃了毫秒精度。 Specifying 000 is treated the same as not specifying anything, which doesn't seem quite right. 指定000与未指定任何内容相同,这似乎不太正确。

In Java 8, you can use LocalDate.parse() or LocalDateTime.parse() on a String without providing it with a pattern, if the String is in ISO 8601 format. 在Java 8中,您可以使用LocalDate.parse()LocalDateTime.parse()String没有为它提供一个模式,如果String为ISO 8601格式。

parse() , Obtains an instance of LocalDate from a text string such as 2007-12-03. parse() ,从文本字符串(如2007-12-03 parse()获取LocalDate的实例。 The string must represent a valid date and is parsed using DateTimeFormatter.ISO_LOCAL_DATE. 该字符串必须表示有效日期,并使用DateTimeFormatter.ISO_LOCAL_DATE进行解析。

and, 和,

DateTimeFormatter.ISO_LOCAL_DATE , This returns an immutable formatter capable of formatting and parsing the ISO 8601 DateTimeFormatter.ISO_LOCAL_DATE ,这将返回一个能够格式化和解析ISO 8601的不可变格式化程序

for example, 例如,

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);

gives, 给,

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

Update: 更新:

your date, ie "2015-02-05T02:05:17.000+00:00" would only throw zeros away when they are all zeros, if the value of nano seconds is other than zeros then it will display just fine, however, if you want to display zeros too then you can simply add if/else block and append zeros to your date if your nano-of-seconds are zeros ( yourdate.getNano()==0 ), else print it as it is, 你的日期,即"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());

will give, 会给,

2015-02-05T02:05:17.000Z

changing your date to, 把你的约会时间改为,

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

gives, 给,

2015-02-05T02:05:17Z

changing date to, 将日期改为

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

gives, 给,

2015-02-05T02:05:17.100Z

changing it to, 改变它,

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

gives, 给,

2015-02-05T02:05:17Z

You have to understand that the preservation of precision can only happen in textual space but not in value space . 您必须明白, 精度保留只能发生在文本空间中,而不能发生在价值空间中 So a different degree of precision can be expressed in a textual way (see your input), but not in the value object (here of type OffsetDateTime ). 因此,可以以文本方式表示不同的精度(请参阅输入),但不能在值对象(此处为OffsetDateTime类型)中表示。 Latter only stores the date-time-value but not any extra precision information. Latter仅存储日期时间值,但不存储任何额外的精度信息。 If you really want to achieve this goal then you have no other choice than to write your own class as wrapper around an OffsetDateTime and the precision (expressed as ChronoUnit -enum). 如果你真的想要实现这个目标,那么你别无选择,只能将自己的类编写为OffsetDateTime和精度(表示为ChronoUnit -enum)的包装器。

Otherwise, if you always want to preserve the precision in milliseconds for your output then you should not use the toString() -method but a dedicated formatter. 否则,如果您始终希望保留输出的精度(以毫秒为单位),则不应使用toString() - 方法,而应使用专用格式化程序。 In Java-8 this would be like: 在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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM