将日期和时间字符串解析为ZonedDateTime对象

时间:2019-03-09 00:49:03

标签: java java-8 zoneddatetime java.time

我正在尝试使用已知时区中的日期和时间来解析String。 字符串具有以下格式:

2019-03-07 00:05:00-05:00

我已经尝试过了:

package com.example.test;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Test {

    public static void main( String[] args ) {

        ZoneId myTimeZone = ZoneId.of("US/Eastern");

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ssXX");

        ZonedDateTime zdt = ZonedDateTime.parse("2019-03-07 00:05:00-05:00", dateTimeFormatter.withZone(myTimeZone));

        System.out.println(zdt);

    }

}

这是引发的异常:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2019-03-07 00:05:00-05:00' could not be parsed at index 19
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
    at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)
    at com.example.test.Test.main(Test.java:24)
C:\Users\user\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)

我正在使用Java 1.8.0_191。

2 个答案:

答案 0 :(得分:4)

使用此模式:yyyy-MM-dd HH:mm:ssXXX

来自docs

  

偏移X和x:...两个字母输出小时和分钟,不带   冒号,例如“ +0130”。三个字母输出小时和分钟,   带有冒号,例如“ +01:30”。

因此,如果您的字符串在时区内包含冒号,则应使用3个“ X-es”。

大写字母Y表示“以周为基础的年”,而不是常规的(y)。

答案 1 :(得分:4)

tl; dr

OffsetDateTime.parse( 
    "2019-03-07 00:05:00-05:00".replace( " " , "T" ) 
)

使用偏移Luke

您不需要时区。您的字符串的UTC偏移量比UTC落后五个小时。这告诉我们一个特定的时刻,即时间表上的一点。

ISO 8601

在输入中间用T替换空格以符合ISO8601。 java.time 类默认使用标准格式。因此,无需指定格式化模式。

OffsetDateTime

解析为OffsetDateTime

String input = "2019-03-07 00:05:00-05:00".replace( " " , "T" ) ;
OffsetDateTime odt = OffsetDateTime.parse( input ) ;

ZonedDateTime

如果您确定该值是针对特定时区的,则可以应用ZoneId来获得ZonedDateTime

请注意,US/Easterndeprecated as a time zone name。现代方法是Continent/Region。也许您是说America/New_York

ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;