Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将YYYY-MM DDThh:MM:ssTZD格式的日期字符串转换为本地时间_Java_Spring Boot_Datetime - Fatal编程技术网

Java 将YYYY-MM DDThh:MM:ssTZD格式的日期字符串转换为本地时间

Java 将YYYY-MM DDThh:MM:ssTZD格式的日期字符串转换为本地时间,java,spring-boot,datetime,Java,Spring Boot,Datetime,在我的spring boot应用程序中,我必须在不使用JODA的情况下将ISO 8601 datetime转换为localdatetime。目前我正在做的是 String receivedDateTime = "2019-11-13T00:11:08+05:00"; ZonedDateTime zonedDateTime = ZonedDateTime.parse(receivedDateTime); DateFormat utcFormat = new SimpleDateFormat("

在我的spring boot应用程序中,我必须在不使用JODA的情况下将ISO 8601 datetime转换为localdatetime。目前我正在做的是

String receivedDateTime = "2019-11-13T00:11:08+05:00";

ZonedDateTime zonedDateTime = ZonedDateTime.parse(receivedDateTime);

DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date = new Date();
        try {
            date = utcFormat.parse(zonedDateTime.toString());
        } catch (ParseException e) {
            e.printStackTrace();
        }
当我将receivedDateTime与+00:00一起使用时,如“2019-11-13T00:11:08+00:00”,则它不会给出任何解析错误,但也不会转换。当我在结尾使用+01:00时,它也会给出解析错误

更新:1

根据@Deadpool答案,我使用它就像

String receivedDateTime  = "2019-11-13T00:11:08+05:00";

        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
                .optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
                .optionalStart().appendOffset("+HHMM", "0000").optionalEnd()
                .toFormatter();

        OffsetDateTime dt = OffsetDateTime.parse(receivedDateTime, formatter);
        LocalDateTime ldt = dt.toLocalDateTime();

        System.out.println(ldt);
并且打印的ldt值为2019-11-13T00:11:08

更新2: 我尝试使用C#同样的例子,它给出了这个日期时间{2019-11-12 11:11:08 AM},它看起来正确,因为输入时间GMT+5小时,当地时间是美国东部时间。所以,当它转换它,然后它回到11月12日。这里是代码

var timeString = "2019-11-13T00:11:08+05:00";
DateTime d2 = DateTime.Parse(timeString, null, System.Globalization.DateTimeStyles.RoundtripKind);
Console.WriteLine("Hello World!" + d2);
更新3:因此它归结为以下解决方案输入字符串“2019-11-13T06:01:41+00:00”,输出为本地日期“2019-11-13T00:01:41”,其中系统定义区域ID为“美国/芝加哥”,即-06:00 GMT

private LocalDateTime convertUtcStringToLocalDateTime(String UtcDateTime) {
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
                .optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
                .optionalStart().appendOffset("+HHMM", "0000").optionalEnd()
                .toFormatter();

        OffsetDateTime dateTime = OffsetDateTime.parse(UtcDateTime, formatter);
        return dateTime.atZoneSameInstant(ZoneId.of(ZoneId.systemDefault().getId())).toLocalDateTime();
    }

通过使用
DateTimeFormatter
,您可以使用不同的
offset
格式自定义日期格式,方法是将其设置为可选格式

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
            .optionalStart().appendOffset("+HHMM", "0000").optionalEnd()
            .toFormatter();
以及使用来解析用偏移量表示的字符串

在ISO-8601日历系统(如2007-12-03T10:15:30+01:00)中,从UTC/格林威治偏移的日期时间

如果要将其转换为本地时区时间
LocalDateTime
,请使用
atZoneWithSameInstant()


注意:不要使用
SimpleDateFormat
util.Date
这是使用java的传统旧框架

    String receivedDateTime = "2019-11-13T00:11:08+05:00";

    OffsetDateTime parsedDateTime = OffsetDateTime.parse(receivedDateTime);
    ZonedDateTime dateTimeInMyTimeZone
            = parsedDateTime.atZoneSameInstant(ZoneId.systemDefault());
    System.out.println(dateTimeInMyTimeZone);
当我在美国/多伦多时区运行时,输出为:

2019-11-12T14:11:08-05:00[美国/多伦多]

由于字符串包含偏移量,
+05:00
,并且没有时区,如
Asia/Karachi
,请使用
OffsetDateTime
对其进行解析。然后使用
atZoneSameInstant
方法转换到本地时区。即使您询问了当地时间,也不要上当使用
LocalDateTime
。该类表示没有任何时区的日期和时间,这不是您所需要的(并且很少需要)

幸运的是,很容易避免使用旧类
SimpleDateFormat
DateFormat
TimeZone
Date
。它们的设计总是很糟糕,特别是前两个,它们的麻烦是出了名的。它们现在都早已过时了。取而代之的是从java.time(现代java日期和时间API)获得我们梦想的所有功能

你的代码中发生了什么? 不要在格式模式字符串中使用
'Z'
(我重复一遍,不要使用
SimpleDateFormat


无论您使用
ZonedDateTime
还是
OffsetDateTime
,当您使用偏移量为零的
toString
时(从
+00:00
解析),偏移量打印为
Z
,这与格式模式字符串中的
'Z'
匹配,因此第二次解析工作。只解析一次,转换回字符串并再次解析是不必要的复杂。当原始偏移量为
+01:00
+05:00
时,情况更糟。从
到字符串
,它们再次呈现为相同的,因此不匹配
'Z'
,这导致了
解析异常
。切勿在格式模式字符串中使用
'Z'
Z
表示零的偏移量,需要将其作为偏移量进行分析才能得到正确的结果。

我不明白为什么要使用
ZoneDateTime。解析
将其转换回字符串,并使用
SimpleDateFormat
对其进行解析。
LocalDateTime
在哪里?当您可以使用java.time(现代java日期和时间API)时,请坚持使用它,并避免使用旧的和麻烦的类
SimpleDateFormat
DateFormat
时区
date
。现代API为您提供了所需的所有功能。古今中外的混合只是增加了额外的复杂性,却没有任何好处。我同意你的看法。你有比更新3更好的解决方案吗?请分享。谢谢Deadpool,它打印了2019-11-13T00:11:08Z 2019-11-13T00:11:08+05:00我错过了什么吗?因为我尝试将其转换为本地时间检查更新的答案只需调用
toLocalDateTime()
@Karanstrange就足够了。它为输入字符串“2019-11-13T00:11:08+05:00”提供了“2019-11-13T00:11:08”。这不可能是对的,我是这样使用它的:OffsetDateTime dt=OffsetDateTime.parse(receivedDateTime,格式化程序);LocalDateTime ldt=dt.toLocalDateTime();你期望的结果是什么?你对本地日期有什么期望@KaranI认为格式化程序,尤其是可选的偏移量是不必要的复杂因素
OffsetDateTime
在不使用任何显式格式化程序的情况下解析字符串,字符串中包含
+05:00
+00:00
+01:00
(我没有否决)。谢谢@Ole.V.V.,此解决方案简洁明了
LocalDateTime local = dateTime.atZoneSameInstant(ZoneId.of("America/New_York")).toLocalDateTime()
    String receivedDateTime = "2019-11-13T00:11:08+05:00";

    OffsetDateTime parsedDateTime = OffsetDateTime.parse(receivedDateTime);
    ZonedDateTime dateTimeInMyTimeZone
            = parsedDateTime.atZoneSameInstant(ZoneId.systemDefault());
    System.out.println(dateTimeInMyTimeZone);