简体   繁体   English

将字符串解析为特定格式的日期

[英]Parse string to date of specific format

I have a string with the following format String stringDate = "2019-04-25T07:03:17.428Z";我有一个格式如下的String stringDate = "2019-04-25T07:03:17.428Z"; and I need to convert it to a LocalDateTime object of format 2019-04-25 07:03:17我需要将其转换为格式为 2019-04-25 07:03:17 的 LocalDateTime object

I have tried with LocalDateTime.parse(stringDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) but I get this parse exception:我已经尝试过LocalDateTime.parse(stringDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))但我得到了这个解析异常:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2019-04-25T07:03:17.428Z' could not be parsed at index 10
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
    at com.company.Main.main(Main.java:12)

What would be the way to convert to specific format?转换为特定格式的方法是什么?

What you asked for (but don't want)你要求的(但不想要的)

    String stringDate = "2019-04-25T07:03:17.428Z";
    LocalDateTime ldt = LocalDateTime.parse(stringDate, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
            .truncatedTo(ChronoUnit.SECONDS);
    System.out.println(ldt);

Output is Output 是

2019-04-25T07:03:17 2019-04-25T07:03:17

It gives you what you said you wanted, but as rzwitserloot points out in the other answer , it does not make sense.它给了你你想要的东西,但正如rzwitserloot在另一个答案中指出的那样,它没有意义。 It ignores the offset Z that was in your string.它忽略了字符串中的偏移量Z The offset is crucial for interpreting the date and time as a point in time.偏移量对于将日期和时间解释为时间点至关重要。 If the string had been 2019-04-25T07:03:17.428+13:00 instead, you would still have got the same output even though the string denotes a point in time that is 13 hours earlier.如果字符串是2019-04-25T07:03:17.428+13:00而不是,您仍然会得到相同的 output 即使该字符串表示一个时间点早于 13 小时。

The call to truncatedTo() gets rid of the fraction of second.truncatedTo()的调用摆脱了秒的小数部分。 If you can live with that fraction of second, leave out that call.如果你能忍受那几分之一秒,那就不要打那个电话了。

What you may want instead你可能想要什么

For a more sensible conversion:为了更明智的转换:

    ZoneId zone = ZoneId.of("Europe/Zagreb");
    
    Instant pointInTime = Instant.parse(stringDate);
    LocalDateTime ldt = pointInTime.atZone(zone)
            .toLocalDateTime()
            .truncatedTo(ChronoUnit.SECONDS);

    System.out.format("Date and time in %s: %s%n", zone, ldt);

Date and time in Europe/Zagreb: 2019-04-25T09:03:17欧洲/萨格勒布的日期和时间:2019-04-25T09:03:17

Now the time 07:03 UTC has been converted to 09:03 Central European Summer Time.现在时间 07:03 UTC 已转换为 09:03 中欧夏令时间。

Edit: If you positively need a LocalDateTime in UTC, for example for a database column requiring this, you may make this fact explicit in your code in this way:编辑:如果您确实需要 UTC 中的LocalDateTime ,例如对于需要此的数据库列,您可以通过这种方式在代码中明确说明这一事实:

    LocalDateTime ldt = pointInTime.atOffset(ZoneOffset.UTC)
            .toLocalDateTime()
            .truncatedTo(ChronoUnit.SECONDS);

    System.out.format("Date and time in UTC: %s%n", ldt);

Date and time in UTC: 2019-04-25T07:03:17 UTC 日期和时间:2019-04-25T07:03:17

What went wrong in your code?你的代码出了什么问题?

To understand what failed for you let's look at the exception message you got:要了解您失败的原因,让我们看看您收到的异常消息:

Text '2019-04-25T07:03:17.428Z' could not be parsed at index 10无法在索引 10 处解析文本“2019-04-25T07:03:17.428Z”

Index 10 is where the T that signifies the start of the time part is.索引 10 是表示时间部分开始的T所在的位置。 Let's compare to your format pattern string: yyyy-MM-dd HH:mm:ss .让我们比较一下您的格式模式字符串: yyyy-MM-dd HH:mm:ss This has a space instead of a T before the time part.这在时间部分之前有一个空格而不是T This was the reason for the exception.这就是异常的原因。 If you needed to specify in the pattern that a T must be there, we would need to enclose it in single quotes, for example yyyy-MM-dd'T'HH:mm:ss .如果您需要在模式中指定T必须存在,我们需要将其括在单引号中,例如yyyy-MM-dd'T'HH:mm:ss

Your input, fundamentally, isn't an LDT.从根本上说,您的输入不是 LDT。 It's a ZDT - that Z is a zone (ZonedDateTime).这是一个 ZDT - Z 是一个区域 (ZonedDateTime)。 Thus, it is not possible to convert this string directly to an LDT, and that's good, because that'd make no sense.因此,不可能将此字符串直接转换为 LDT,这很好,因为这没有任何意义。

Convert it to a ZDT.将其转换为 ZDT。 Then convert that to an LDT.然后将转换为 LDT。 It's a single method call.这是一个单一的方法调用。

You can parse it first using java.time.Instant and then use method ofInstant of java.time.LocalDateTime example:您可以先使用java.time.Instant解析它,然后使用java.time.LocalDateTime示例的Instant方法:

String stringDate = "2019-04-25T07:03:17.428Z";
var instant = Instant.parse(stringDate);
var localDateTime = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

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

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