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

huangapple go评论60阅读模式
英文:

Java convert ISO 8601 string to Date ignoring offset

问题

String input = "2020-09-09T09:58:00+0000";
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
OffsetDateTime offsetDateTime = OffsetDateTime.parse(input, inputFormatter);

DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss", Locale.ENGLISH);
String desiredOutput = outputFormatter.format(offsetDateTime);

Note: The code provided above is a direct translation of the content you provided. Please make sure to test and adapt it to your specific programming environment if needed.

英文:

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.

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:

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.

答案1

得分: 1

我建议您使用 现代的 java.time 日期时间 API 以及相应的格式化 API(包括 java.time.format 包)。从 教程:日期时间 中了解更多关于现代日期时间 API 的信息。

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

public class Main {
    public static void main(String[] args) {
        // 给定的日期时间字符串
        String strDateTime = "2020-09-09T09:58:00+0000";

        // 定义格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ");

        // 将给定的日期时间字符串解析为 OffsetDateTime
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime, formatter);

        // 输出默认格式的 OffsetDateTime
        System.out.println(odt);

        // 使用定义的格式化器打印 OffsetDateTime
        String formatted = formatter.format(odt);
        System.out.println(formatted);
    }
}

输出:

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

注意: java.util.Date 不表示日期/时间对象。它只表示从 1970-01-01T00:00:00Z 开始的毫秒数。它不具有任何时区或区偏移信息。当您打印它时,Java 会使用您的 JVM 的时区来打印字符串。我建议您停止使用 java.util.Date 并切换到现代日期时间 API。

使用 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) {
        // 给定的日期时间字符串
        String strDateTime = "2020-09-09T09:58:00+0000";

        // 定义格式化器
        DateTimeFormatter isoFormat = ISODateTimeFormat.dateTimeParser();
        DateTime dateTime = isoFormat.parseDateTime("2020-09-09T09:58:00+0000");

        // 在默认格式下显示 DateTime
        System.out.println(dateTime);

        // 为输出定义格式化器
        DateTimeFormatter outputFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ").withZoneUTC();

        // 在定义的输出格式下显示 DateTime
        String formatted = outputFormat.print(dateTime);
        System.out.println(formatted);
    }
}

输出:

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

I recommend you do it with the modern java.time date-time API and the corresponding formatting API (package, java.time.format). Learn more about the modern date-time API from Trail: Date Time.

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. It simply represents the no. of milliseconds from the epoch of 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. I suggest you stop using java.util.Date and switch to the modern date-time API.

Using joda date-time API, you can do it as follows:

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

答案2

得分: 1

答案的第一部分最重要的是:不要转换为旧式的Date。要么继续使用Joda-Time,要么迁移到java.time,这是现代Java的日期和时间API,正如Arvind Kumar Avinash在很好的回答中已经涵盖的那样。

由于您已经在使用Joda-Time,我会向您展示一个Joda-Time的解决方案。说服格式化程序保留从解析的字符串中提取的时间和偏移量的技巧是withOffsetParsed()

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

然而!如果我猜得正确,您想要在UTC中存储日期和时间(这是一种推荐的做法),比起withOffsetParsed()更好的方法是在解析器上指定UTC:

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

现在,如果有一天出现带有非零UTC偏移的字符串,您还将获得正确的时间。

无论如何,我们现在可以将获得的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);

输出:

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

为什么不能使用Date 首先,Date类设计不佳且过时。其次,Date只是一个时间点,它没有日期和时间的概念(在Java 1.0中尝试将其构建其中,但在1997年的Java 1.1中将其弃用)。因此,Date不能为您保存UTC的日期和时间。

您的代码中发生的情况是,您获得了一个表示正确时间点的Date。只有当您打印该Date时,您才会隐式调用其toString方法。Date.toString()混淆地获取了JVM的时区设置(在您的情况下显然是北美东部时间),并将其用于渲染要返回的字符串。因此,在您的情况下,时间点被呈现为Wed Sep 09 05:58:00 EDT 2020

英文:

The first and most important part of the answer is: don’t convert to an old-fashioned 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.

Since you are already using Joda-Time, I am showing you a Joda-Time solution. The trick for persuading the formatter into keeping the time and offset from the string parsed is 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:

	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.

In any case we may now format your obtained DateTime into the strings you requested.

	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? First, the Date class is poorly designed and long outdated. 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). So a Date cannot hold the date and time of day in UTC for you.

What happened in your code was that you got a Date representing the correct point in time. Only when you printed that Date you were implicitly invoking its toString method. 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. So in your case the point in time was rendered as Wed Sep 09 05:58:00 EDT 2020.

huangapple
  • 本文由 发表于 2020年9月10日 05:30:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/63819809.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定