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

时间:2015-08-23 05:58:27

标签: java string time

我正在尝试以 2015-08-20T08:26:21.000Z 的格式创建字符串 至 2015-08-20T08:26:21Z

我知道可以使用一些字符串拆分技术来完成,但我想知道是否有一个优雅的解决方案(最少的代码更改)。

上述两个都是时间字符串,我需要的最后一个是ISO 8601中的日期。 http://tools.ietf.org/html/rfc3339#section-5.6

我尝试了一些像converting a date string into milliseconds in java这样的类似问题,但实际上并没有解决目的。

还尝试使用:

<table class="table table-hover" ng-controller="emailViewController">
    <tbody data-ng-controller="settingsController">
    <tr ng-repeat="email in emails | limitTo: conversation" >
        <td><input type="checkbox" ng-checked="checkAllEmail" ng-model="selectedEmail"/>
            <a href="#">
                <span class="glyphicon glyphicon-star-empty"></span>
            </a></td>
        <td><label ng-bind="email.from"></label></td>
        <td><label ng-bind="email.subject"></label></td>
        <td><label ng-bind="email.time"></label></td>
    </tr>
    </tbody>
</table>

但它仍然不会执行任何String to String转换。得到以下错误:

23:04:13,829 WARN [RuntimeExceptionMapper]捕获到RuntimeException:{}:java.lang.IllegalArgumentException:无法将给定对象格式化为日期

是否有人可以建议的图书馆?

感谢。

3 个答案:

答案 0 :(得分:10)

TL;博士

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

2015-08-20T08:26:21Z

日期时间格式化程序

如果您要做的就是消除.000,那么使用日期时间对象来解析输入字符串值,然后以不同的格式生成该日期时间值的新字符串表示。

ISO 8601

顺便说一句,如果这是你的目标,那么问题的标题就没有意义,因为第一句中提到的两个字符串都是有效的ISO 8601格式字符串。

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

java.time

Java 8及更高版本具有新的java.time package。这些新类取代了旧的java.util.Date/.Calendar&amp; java.text.SimpleDateFormat类。那些旧课程令人困惑,麻烦和有缺陷。

即时

如果你想要的只是UTC时区,那么你可以使用Instant类。此类表示时间轴上的一个点,不考虑任何特定时区(基本上是UTC)。

DateTimeFormatter.ISO_INSTANT

使用toString格式化程序实例调用Instant DateTimeFormatter.ISO_INSTANT生成日期时间值的字符串表示形式。此格式化程序自动灵活地关于小数秒。如果值有一整秒,则不会生成小数位(显然是问题想要的)。对于小数秒,数字显示在3,6或9的组中,根据需要表示高达纳秒分辨率的值。注意:此格式可能超过ISO 8601毫秒限制(3位小数)。

示例代码

以下是Java 8 Update 51中的一些示例代码。

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

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

更改为小数秒,.08

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

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

如果对UTC以外的任何时区感兴趣,请从Instant创建ZonedDateTime个对象。

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

答案 1 :(得分:2)

你的格式不合适试试这个: -

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

答案 2 :(得分:2)

将未知格式的日期String转换为使用已知格式的日期String可以使用两个DateFormat对象来完成 - 一个动态配置来解析输入的格式{ {1}},并配置一个生成格式化输出String。对于您的情况,输入String格式是未指定的,必须由调用者提供,但是,输出String格式可以配置为使用ISO 8601格式而无需额外输入。实质上,生成ISO 8601格式的日期String输出需要调用者提供两个输入 - 包含格式化日期的String和包含String格式的另一个String

以下是所描述的转换为Java代码(我故意省略了空检查和验证,根据您的代码添加这些代码):

SimpleDateFormat

如果要修改该方法,请注意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); } 不是线程安全的,并且如果没有多线程代码(SimpleDateFormat的解决方法,则不应在静态上下文中使用它通常用于ThreadLocal)的这种解决方法。

另外一个&#34;陷阱&#34;是在构造SimpleDateFormat对象期间使用Locale - 不要删除SimpleDateFormat配置。允许系统选择使用默认Locale是不安全的,因为这是用户/机器特定的。如果您允许它使用默认的Locale,则可能会遇到暂时性错误的风险,因为您的开发计算机使用的Locale与最终用户的Locale不同。您不必使用我选择的英语Locale,使用不同的区域设置是完全正确的(您应该理解Locale的规则并根据需要修改代码)。没有Locale的规范和系统默认的使用是不正确的,并且可能会导致许多令人沮丧的小时试图诊断难以捉摸的错误。

请理解,此解决方案与Java 8不同,并且包含基于JodaTime的类,如Locale。我选择使用过时的API来回答,因为这些是您在问题中似乎关注的内容。如果您使用的是Java 8,我强烈建议您学习和使用新课程,因为它们几乎是所有可能的方式都在改进。