简体   繁体   English

Java将ISO 8601字符串转换为忽略偏移量的日期

[英]Java convert ISO 8601 string to Date ignoring offset

I have a string coming to me in the following format "yyyy-MM-dd'T'HH:mm:ssZ" ex: 2020-09-09T09:58:00+0000" offset is UTC.我收到一个字符串,格式为“yyyy-MM-dd'T'HH:mm:ssZ”,例如:2020-09-09T09:58:00+0000" 偏移量是UTC。

I need the string to be converted to a Date object without the offset "+0000" being applied, but I keep getting a different time when running my code:我需要将字符串转换为 Date 对象而不应用偏移量“+0000”,但是在运行我的代码时我总是得到不同的时间:

DateTimeFormatter isoFormat = ISODateTimeFormat.dateTimeParser();
Date date = isoFormat.parseDateTime("2020-09-09T09:58:00+0000").toDate();
// Wed Sep 09 05:58:00 EDT 2020

As you can see above the date has changed.如您所见,日期已更改。

Instead, I would like to keep the same date and time like: Wed Sep 09 09:58:00, so I can convert this Date object to a String with "yyyy-MM-dd", "HH:mm:ss", and "yyyy-MM-dd'T'HH:mm:ss" format respectively.相反,我想保持相同的日期和时间,例如:Wed Sep 09 09:58:00,所以我可以将此日期对象转换为带有“yyyy-MM-dd”、“HH:mm:ss”的字符串,和“yyyy-MM-dd'T'HH:mm:ss”格式。

I recommend you do it with the modern java.time date-time API and the corresponding formatting API (package, java.time.format ).我建议您使用现代java.time日期时间 API 和相应的格式化 API(包, java.time.format )来完成。 Learn more about the modern date-time API from Trail: Date Time .Trail: Date Time 中了解有关现代日期时间 API 的更多信息。

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        // The given date-time string
        String strDateTime = "2020-09-09T09:58:00+0000";

        // Define the formatter
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ");

        // Parse the given date-time string into OffsetDateTime
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime, formatter);

        // Output OffsetDateTime in the default format
        System.out.println(odt);

        // Print OffsetDateTime using the defined formatter
        String formatted = formatter.format(odt);
        System.out.println(formatted);
    }
}

Output:输出:

2020-09-09T09:58Z
2020-09-09T09:58:00+0000

Note: java.util.Date does not represent a Date/Time object.注意: java.util.Date不代表日期/时间对象。 It simply represents the no.它只是代表没有。 of milliseconds from the epoch of 1970-01-01T00:00:00Z .1970-01-01T00:00:00Z时代开始的毫秒数。 It does not have any time-zone or zone-offset information.它没有任何时区或区域偏移信息。 When you print it, Java prints the string obtained by applying the time-zone of your JVM.当您打印它时,Java 会打印通过应用 JVM 的时区获得的字符串。 I suggest you stop using java.util.Date and switch to the modern date-time API.我建议您停止使用java.util.Date并切换到现代日期时间 API。

Using joda date-time API, you can do it as follows:使用 joda 日期时间 API,您可以按如下方式进行:

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;

public class Main {
    public static void main(String[] args) {
        // The given date-time string
        String strDateTime = "2020-09-09T09:58:00+0000";

        // Define the formatter
        DateTimeFormatter isoFormat = ISODateTimeFormat.dateTimeParser();
        DateTime dateTime = isoFormat.parseDateTime("2020-09-09T09:58:00+0000");

        // Display DateTime in the default format
        System.out.println(dateTime);

        // Define formatter for ouput
        DateTimeFormatter outputFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ").withZoneUTC();

        // Display DateTime in the defined output format
        String formatted = outputFormat.print(dateTime);
        System.out.println(formatted);
    }
}

Output:输出:

2020-09-09T10:58:00.000+01:00
2020-09-09T09:58:00+0000

The first and most important part of the answer is: don't convert to an old-fashioned Date .答案的第一个也是最重要的部分是:不要转换为老式的Date Either stick to Joda-Time or migrate to java.time, the modern Java date and time API, as already covered in the good answer by Arvind Kumar Avinash.要么坚持使用 Joda-Time,要么迁移到 java.time,现代 Java 日期和时间 API,正如 Arvind Kumar Avinash 的好答案中已经介绍的那样。

Since you are already using Joda-Time, I am showing you a Joda-Time solution.由于您已经在使用 Joda-Time,我向您展示了一个 Joda-Time 解决方案。 The trick for persuading the formatter into keeping the time and offset from the string parsed is withOffsetParsed() .说服格式化程序保留解析字符串的时间和偏移量的技巧是withOffsetParsed()

    DateTimeFormatter isoFormat
            = ISODateTimeFormat.dateTimeParser().withOffsetParsed();
    String incomingString = "2020-09-09T09:58:00+0000";
    DateTime dateTime = isoFormat.parseDateTime(incomingString);

However!然而! If I have guessed correctly that you want to store date and time in UTC (a recommended practice), better than withOffsetParsed() is to specify UTC on the parser:如果我猜对了您想以 UTC 存储日期和时间(推荐的做法),比withOffsetParsed()更好的是在解析器上指定 UTC:

    DateTimeFormatter isoFormat
            = ISODateTimeFormat.dateTimeParser().withZoneUTC();

Now you will also get the correct time if one day a string with a non-zero UTC offset comes in.现在,如果有一天出现具有非零 UTC 偏移量的字符串,您也将获得正确的时间。

In any case we may now format your obtained DateTime into the strings you requested.在任何情况下,我们现在都可以将您获得的DateTime格式化为您请求的字符串。

    String dateString = dateTime.toString(ISODateTimeFormat.date());
    System.out.println(dateString);
    
    String timeString = dateTime.toString(ISODateTimeFormat.hourMinuteSecond());
    System.out.println(timeString);
    
    String dateTimeString = dateTime.toString(ISODateTimeFormat.dateHourMinuteSecond());
    System.out.println(dateTimeString);

Output:输出:

 2020-09-09 09:58:00 2020-09-09T09:58:00

What was wrong with using Date ?使用Date什么问题? First, the Date class is poorly designed and long outdated.首先, Date类的设计很差,而且已经过时了。 Second, a Date was just a point in time, it didn't have a concept of date and time of day (they tried building that into it in Java 1.0, but gave up and deprecated it in Java 1.1 in 1997).其次, Date只是一个时间点,它没有日期和时间的概念(他们尝试在 Java 1.0 中构建它,但在 1997 年的 Java 1.1 中放弃并弃用了它)。 So a Date cannot hold the date and time of day in UTC for you.因此Date不能为您保存 UTC 中的日期和时间。

What happened in your code was that you got a Date representing the correct point in time.您的代码中发生的事情是您获得了一个代表正确时间点的Date Only when you printed that Date you were implicitly invoking its toString method.仅当您打印该Date时,您才隐式调用其toString方法。 Date.toString() confusingly grabs the JVM's time zone setting (in your case apparently North American Eastern Time) and uses it for rendering the string to be returned. Date.toString()令人困惑地获取 JVM 的时区设置(在您的情况下显然是北美东部时间)并使用它来呈现要返回的字符串。 So in your case the point in time was rendered as Wed Sep 09 05:58:00 EDT 2020 .因此,在您的情况下,时间点呈现为Wed Sep 09 05:58:00 EDT 2020

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

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