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

How to convert UTC Date String and remove the T and Z in Java?

我正在使用 Java 1.7。

正在尝试转换:

2018-05-23T23:18:31.000Z 

进入

2018-05-23 23:18:31

DateUtils class:

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

尝试使用时:

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

得到如下异常:

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)

我可能做错了什么?

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

YYYY 与年份部分不匹配。在 java 7 你需要 yyyy.

对于T,用'T'来匹配

您还缺少毫秒部分的派系:.SSS

试试这个:

String dateStr="2018-05-23T23:18:31.000Z";
TimeZone utc = TimeZone.getTimeZone("UTC");
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss.SSS'Z'");
sdf.setTimeZone(utc);
Date convertedDate = sdf.parse(dateStr);
convertedDate.toString();

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

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

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

从 Java 1.8 开始,您可以使用包 java.time

中的 LocalDateTimeZonedDateTime 来完成
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);
}

编辑:(见评论)

引自 LocalDateTime 的 Oracle Java 文档:

LocalDateTime is an immutable date-time object that represents a date-time, often viewed as year-month-day-hour-minute-second. Other date and time fields, such as day-of-year, day-of-week and week-of-year, can also be accessed. Time is represented to nanosecond precision. For example, the value "2nd October 2007 at 13:45.30.123456789" can be stored in a LocalDateTime.

This class does not store or represent a time-zone. Instead, it is a description of the date, as used for birthdays, combined with the local time as seen on a wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.

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

LocalDateTime ... represents a date-time, often viewed as year-month-day-hour-minute-second

所以这里没有丢失任何重要信息。 dateTime.atZone(ZoneId.of("UTC")) returns 和 ZonedDateTime 部分,因此如果用户需要使用时区等,ZimeZone 将在此时再次处理......等

所以不要试图强迫用户使用您在回答中提供的 "One and Only" 解决方案。

tl;博士

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.

2018-05-23 23:18:31

ISO 8601

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

当 parsing/generating 字符串时,java.time classes 默认使用这些标准格式。

T 将年-月-日部分与时-分-秒分开。 Z 发音为 Zulu,意思是 UTC

java.time

您正在使用多年前被 java.time classes 取代的麻烦的旧日期时间 classes。 Apache DateUtils 也不再需要,因为您也会在 java.time 中找到它的功能。

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

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

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

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ; 

定义格式模式以匹配您想要的输出。

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

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


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

您可以直接与您的数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes。 Hibernate 5 和 JPA 2.2 支持 java.time.

从哪里获得 java.time classes?

在 Kotlin 中并使用 ThreeTenABP,

fun getIsoString(year: Int, month: Int, day: Int): String {
    val localTime = ZonedDateTime.of(year, month, day, 0, 0, 0, 0, ZoneId.of("Z"))

    val utcTime = localTime.toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC)

    val isoString = utcTime.toInstant().toString() // 1940-15-12T00:00:00Z

    val formattedIsoString = val formattedIsoString =
        Instant.parse(isoString)
            .atOffset(ZoneOffset.UTC)
            .format(DateTimeFormatter
                .ofPattern("uuuu-MM-dd'T'HH:mm:ss")) // 'T' in quotes so that it is retained.

    return formattedIsoString
}

// print it
print(getIsoString(1940, 15, 12)) // 1940-15-12T00:00:00

你可以试试下面这个思路。 我不是 JAVA 方面的专家,但我在 javascript/node.js

中做到了
import * as momentTimeZone from 'moment-timezone';

let d = new Data(); // d = '2018-05-23T23:18:31.000Z'; or we can take this date
let finalOutput = momentTimeZone(d).tz(this.locationService.locationTimeZone).utc().format('YYYY-MM-DD HH:mm:ss');
console.log('Result: ', finalOutput); // Result: "2018-05-23 23:18:31";

它也适用于 moment.js。 这里有更多关于 format.