如何转换UTC日期字符串并删除Java中的T和Z?

Pac*_*ver 4 java utc parseexception java-7 datetime-parsing

我正在使用Java 1.7。

尝试转换:

2018-05-23T23:18:31.000Z 
Run Code Online (Sandbox Code Playgroud)

进入

2018-05-23 23:18:31
Run Code Online (Sandbox Code Playgroud)

DateUtils类:

public class DateUtils {

    public static String convertToNewFormat(String dateStr) throws ParseException {
        TimeZone utc = TimeZone.getTimeZone("UTC");
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        sdf.setTimeZone(utc);
        Date convertedDate = sdf.parse(dateStr);
        return convertedDate.toString();
    }
}
Run Code Online (Sandbox Code Playgroud)

尝试使用它时:

String convertedDate = DateUtils.convertToNewFormat("2018-05-23T23:18:31.000Z");
System.out.println(convertedDate);
Run Code Online (Sandbox Code Playgroud)

得到以下异常:

Exception in thread "main" java.text.ParseException: Unparseable date: "2018-05-23T23:22:16.000Z"
   at java.text.DateFormat.parse(DateFormat.java:366)
   at com.myapp.utils.DateUtils.convertToNewFormat(DateUtils.java:7)
Run Code Online (Sandbox Code Playgroud)

我可能做错了什么?

有没有更简单的方法(例如Apache Commons lib)?

Bas*_*que 7

tl; dr

Instant.parse( "2018-05-23T23:18:31.000Z" )                // Parse this String in standard ISO 8601 format as a `Instant`, a point on the timeline in UTC. The `Z` means UTC.
.atOffset( ZoneOffset.UTC )                                // Change from `Instant` to the more flexible `OffsetDateTime`.
.format(                                                   // Generate a String representing the value of this `OffsetDateTime` object.
    DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" )   // Specify a formatting pattern as desired.
)                                                          // Returns a `String` object.
Run Code Online (Sandbox Code Playgroud)

2018-05-23 23:18:31

ISO 8601

您的输入字符串为标准ISO 8601格式。

解析/生成字符串时,java.time类默认使用这些标准格式。

T年月日部分与时分秒分开。的Z发音Zulu是“ UTC”

java.time

您正在使用麻烦的旧日期时间类,而该类早已java.time类取代。DateUtils也不再需要Apache ,因为您还将在java.time中找到其功能。

将该输入字符串解析为一个Instant对象。该Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多小数的9个位数)。

String input = "2018-05-23T23:18:31.000Z" ;
Instant instant = Instant.parse( input ) ;
Run Code Online (Sandbox Code Playgroud)

要生成另一种格式的字符串,我们需要一个更灵活的对象。该Instant班是意味着是一个基本构建块。s convert it to a使用UTC本身作为指定的UTC偏移量,让OffsetDateTime`。

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ; 
Run Code Online (Sandbox Code Playgroud)

定义格式模式以匹配所需的输出。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" ) ;
String output = odt.format( f ) ;
Run Code Online (Sandbox Code Playgroud)

提示:考虑使用一些DateTimeFormatter::ofLocalized…方法来自动对每个字符串生成进行本地化,Locale而不是对格式设置模式进行硬编码。


关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要类。java.sql.*

在哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多


jku*_*anc 5

尝试这个。您必须使用一种模式进行解析,而使用另一种模式进行格式化。

public static String convertToNewFormat(String dateStr) throws ParseException {
    TimeZone utc = TimeZone.getTimeZone("UTC");
    SimpleDateFormat sourceFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
    SimpleDateFormat destFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sourceFormat.setTimeZone(utc);
    Date convertedDate = sourceFormat.parse(dateStr);
    return destFormat.format(convertedDate);
}
Run Code Online (Sandbox Code Playgroud)


Ram*_*i.Q 5

对于没有 Java 1.7 限制的其他人:

从 Java 1.8 开始,您可以使用LocalDateTimeZonedDateTime从包中完成java.time

public static void main(String[] args) {
    String sourceDateTime           = "2018-05-23T23:18:31.000Z";
    DateTimeFormatter sourceFormat  = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
    DateTimeFormatter targetFormat  = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    LocalDateTime dateTime          = LocalDateTime.parse(sourceDateTime, sourceFormat);
    String formatedDateTime         = dateTime.atZone(ZoneId.of("UTC")).format(targetFormat);
    System.out.println(formatedDateTime);
}
Run Code Online (Sandbox Code Playgroud)

编辑:(见评论)

引自LocalDateTime的 Oracle Java 文档:

LocalDateTime 是一个不可变的日期时间对象,表示日期时间,通常被视为年-月-日-时-分-秒。也可以访问其他日期和时间字段,例如一年中的某一天、一周中的某一天和一年中的一周。时间以纳秒精度表示。例如,值“2nd October 2007 at 13:45.30.123456789”可以存储在 LocalDateTime 中。

此类不存储或表示时区。相反,它是对日期的描述,用于生日,结合挂钟上的当地时间。如果没有偏移量或时区等附加信息,它就无法表示时间线上的瞬间。

OP 要求仅将输入字符串解析为日期时间(如年-月-日-时-分-秒)并且文档说

LocalDateTime ... 表示日期时间,通常被视为年-月-日-时-分-秒

所以这里不会丢失任何重要信息。如果用户需要使用时区...等,则该部分dateTime.atZone(ZoneId.of("UTC"))返回一个ZonedDateTime因此此时再次处理 ZimeZone。

所以不要试图强迫用户使用您在答案中提供的“唯一”解决方案。