简体   繁体   English

将时间字符串转换为ISO 8601格式

[英]Converting a time String to ISO 8601 format

I am trying to create a String in a format like 2015-08-20T08:26:21.000Z 我正在尝试以2015-08-20T08:26:21.000Z这样的格式创建一个String
to 2015-08-20T08:26:21Z 2015-08-20T08:26:21Z

I know it can be done with some String splitting techniques, but i am wondering if there is an elegant solution for that (with minimal code changes). 我知道它可以通过一些字符串拆分技术来完成,但我想知道是否有一个优雅的解决方案(最小的代码更改)。

Both of the above are time strings, the final one which i need is Date in ISO 8601 . 以上两个都是时间字符串,我需要的最后一个是ISO 8601中的日期。 http://tools.ietf.org/html/rfc3339#section-5.6 http://tools.ietf.org/html/rfc3339#section-5.6

I have tried a few similar questions like converting a date string into milliseconds in java but they dont actually solve the purpose. 我尝试了一些类似的问题,比如在java中将日期字符串转换为毫秒,但它们实际上并没有解决目的。

Also tried using : 还尝试使用:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ");
String nowAsString = df.format(new Date());

But it still does not do any String to String conversions. 但它仍然不执行任何String to String转换。 Getting the following error: 收到以下错误:

23:04:13,829 WARN [RuntimeExceptionMapper] caught RuntimeException: {}: java.lang.IllegalArgumentException: Cannot format given Object as a Date 23:04:13,829 WARN [RuntimeExceptionMapper]捕获到RuntimeException:{}:java.lang.IllegalArgumentException:无法将给定的Object格式化为Date

Is there some library which someone can suggest ? 是否有人可以建议的图书馆?

Thanks. 谢谢。

tl;dr TL;博士

Instant.parse( "2015-08-20T08:26:21.000Z" )
       .toString()

2015-08-20T08:26:21Z 2015-08-20T08:26:21Z

Date-Time Formatter 日期时间格式化程序

If all you want to do is eliminate the .000 , then use date-time objects to parse your input string value, then generate a new string representation of that date-time value in a different format. 如果您要做的就是消除.000 ,那么使用日期时间对象来解析输入字符串值,然后以不同的格式生成该日期时间值的新字符串表示。

ISO 8601 ISO 8601

By the way, if that is your goal, the Question's title make no sense as both strings mentioned in the first sentence are valid ISO 8601 formatted strings. 顺便说一句,如果这是你的目标,那么问题的标题就没有意义,因为第一句中提到的两个字符串都是有效的ISO 8601格式字符串。

  • 2015-08-20T08:26:21.000Z
  • 2015-08-20T08:26:21Z

java.time java.time

Java 8 and later has the new java.time package . Java 8及更高版本具有新的java.time包 These new classes supplant the old java.util.Date/.Calendar & java.text.SimpleDateFormat classes. 这些新类取代了旧的java.util.Date/.Calendar和java.text.SimpleDateFormat类。 Those old classes were confusing, troublesome, and flawed. 那些旧课程令人困惑,麻烦和有缺陷。

Instant 瞬间

If all you want is UTC time zone, then you can use the Instant class. 如果你想要的只是UTC时区,那么你可以使用Instant类。 This class represents a point along the timeline without regard to any particular time zone (basically UTC). 此类表示沿时间线的点,而不考虑任何特定时区(基本上是UTC)。

DateTimeFormatter.ISO_INSTANT

Calling an Instant's toString generates a String representation of the date-time value using a DateTimeFormatter.ISO_INSTANT formatter instance. 调用Instant的toString使用DateTimeFormatter.ISO_INSTANT格式化程序实例生成日期时间值的String表示形式。 This formatter is automatically flexible about the fractional second. 此格式化程序自动灵活地关于小数秒。 If the value has a whole second, no decimal places are generated (apparently what the Question wants). 如果值有一整秒,则不会生成小数位(显然是问题想要的)。 For a fractional second, digits appear in groups of 3, 6, or 9, as needed to represent the value up to nanosecond resolution. 对于小数秒,数字显示在3,6或9的组中,根据需要表示高达纳秒分辨率的值。 Note: this format may exceed ISO 8601 limit of milliseconds (3 decimal places). 注意:此格式可能超过ISO 8601毫秒限制(3位小数)。

Example code 示例代码

Here is some example code in Java 8 Update 51. 以下是Java 8 Update 51中的一些示例代码。

String output = Instant.parse( "2015-08-20T08:26:21.000Z" ).toString( );
System.out.println("output: " + output );

output: 2015-08-20T08:26:21Z 产量:2015-08-20T08:26:21Z

Changing to a fractional second, .08 改为小数秒, .08

String output = Instant.parse( "2015-08-20T08:26:21.08Z" ).toString( );

output: 2015-08-20T08:26:21.080Z 输出:2015-08-20T08:26:21.080Z

If interested in any time zone other than UTC, then make a ZonedDateTime object from that Instant . 如果对UTC以外的任何时区感兴趣,请从该Instant创建ZonedDateTime对象。

ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , ZoneId.of( "America/Montreal" ) ) ;

Your format is just not right try this :- 你的格式不合适试试这个: -

try {
        String s = "2015-08-20T08:26:21.000Z";
         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
    Date d = df.parse(s);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
        System.out.println(sdf.format(d));
    } catch (ParseException e) {
        e.printStackTrace();
    }

Conversion of a date String of unknown formatting into a date String that uses known formatting can be accomplished using two DateFormat objects- one dynamically configured to parse the format of the input String , and one configured to generate the formatted output String . 将日期未知格式的String转换为日期使用已知格式的String可以使用两个DateFormat来完成 - 一个动态配置为解析输入String的格式,另一个配置为生成格式化的输出String For your situation the input String formatting is unspecified and must be provided by the caller, however, the output String formatting can be configured to use ISO 8601 formatting without additional input. 对于您的情况,输入String格式是未指定的,必须由调用者提供,但是,输出String格式可以配置为使用ISO 8601格式而无需其他输入。 Essentially, generating an ISO 8601 formatted date String output requires two inputs provided by the caller- a String containing the formatted date and another String that contains the SimpleDateFormat format. 本质上,产生一个ISO 8601格式的日期String输出需要由呼叫者提供的两个输入String含有格式化的日期和另一个String包含SimpleDateFormat格式。

Here is the described conversion as Java code (I deliberately have left out null checks and validations, add these as appropriate for your code): 这里描述的转换为Java代码(我故意省略了空检查和验证,根据您的代码添加这些代码):

private String formatDateAsIso8601(final String inputDateAsString, final String inputStringFormat) throws ParseException {

     final DateFormat iso8601DateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.ENGLISH);
     iso8601DateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));

     final DateFormat inputDateFormatter = new SimpleDateFormat(inputStringFormat, Locale.ENGLISH);
     final Date inputDate = inputDateFormatter.parse(inputDateAsString);

     return iso8601DateFormatter.format(inputDate);
}

If you want to modify that method please note that SimpleDateFormat is not thread-safe, and that you should not use it from a static context without a workaround for multi-threaded code ( ThreadLocal is commonly used to do just such a workaround for SimpleDateFormat ). 如果要修改该方法,请注意SimpleDateFormat不是线程安全的,并且如果没有多线程代码的解决方法,则不应在静态上下文中使用它( ThreadLocal通常用于为SimpleDateFormat执行此类变通方法) 。

An additional "gotcha" is the use of a Locale during the construction of the SimpleDateFormat objects- do not remove the Locale configuration. 另一个“问题”是在构造SimpleDateFormat期间使用Locale - 不要删除Locale配置。 It is not safe to allow the system to choose to use the default Locale because that is user/machine specific. 允许系统选择使用默认的Locale是不安全的,因为这是用户/机器特定的。 If you do allow it to use the default Locale , you run the risk of transient bugs because your development machine uses a Locale different than the Locale of your end-user. 如果您允许它使用默认的Locale ,则存在暂时性错误的风险,因为您的开发计算机使用的Locale Locale与最终用户的Locale Locale不同。 You do not have to use my selected ENGLISH Locale , it is perfectly fine to use a different Locale (you should understand the rules of that Locale and modify the code as appropriate however). 您不必使用我选择的ENGLISH Locale ,使用不同的Locale完全没问题(您应该了解该Locale的规则并根据需要修改代码)。 Specification of no Locale and utilization of the system default is incorrect however, and likely will lead to many frustrating hours trying to diagnose an elusive bug. 没有Locale规范和系统默认的使用是不正确的,并且可能会导致许多令人沮丧的小时试图诊断难以捉摸的bug。

Please understand this solution is not ideal as of Java 8 and the inclusion of the JodaTime based classes, like Instant . 请理解这个解决方案并不像Java 8那样理想,并且包含了基于JodaTime的类,比如Instant I chose to answer using the outdated API's because those were what you seemed concerned with in your question. 我选择使用过时的API来回答,因为这些是您在问题中看起来很关注的内容。 If you are using Java 8 I strongly urge to learn and utilize the new classes as they are an improvement in almost every conceivable way. 如果您使用的是Java 8,我强烈建议您学习和使用新课程,因为它们几乎是所有可能的方式都在改进。

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

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