解析ISO_INSTANT和类似的日期时间字符串

时间:2015-09-28 14:58:00

标签: java datetime java-8 java-time

昨天我创建了这个精彩的静态方法,它工作得很好 - 昨天

然而,今天它给了我这个错误。我想这是在Z之前的太多0。

任何人都可以推荐如何以简洁的方式(Java 8)解析这种ISO_INSTANT格式的日期 - 请记住它昨天也有效,所以String也是一种有效的格式。 Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {NanoOfSecond=0, InstantSeconds=1443451604, MilliOfSecond=0, MicroOfSecond=0},ISO of type java.time.format.Parsed at java.time.LocalDate.from(LocalDate.java:368) at java.time.LocalDateTime.from(LocalDateTime.java:456) ... 9 more

/**
 *
 * @param time the time in RFC3339 format (e.g. "2013-07-03T14:30:38Z" )
 * @return
 */
public static LocalDateTime parseTimeINSTANT(String time) {
    DateTimeFormatter f = DateTimeFormatter.ISO_INSTANT;
    return LocalDateTime.from(f.parse(time));
}

在输入时间抛出异常:“2015-09-28T14:46:44.000000Z”

    string date = "9/28/2015 12:00:00 AM"; // In My Code, This Var Contain Unseen Unicode Char.
    var cleanDate = new string(date.Where(c => char.IsNumber(c) || char.IsPunctuation(c) || char.IsWhiteSpace(c) || char.IsLetter(c)).ToArray());
    DateTime date = DateTime.ParseExact(cleanDate, "M/d/yyyy hh:mm:ss tt", CultureInfo.InvariantCulture);

enter image description here

4 个答案:

答案 0 :(得分:17)

您正在解析与ISO即时一致的字符串,因此您需要将结果存储在Instant而不是LocalDateTime中:

public static Instant parseTimeINSTANT(String time) {
    DateTimeFormatter f = DateTimeFormatter.ISO_INSTANT;
    return Instant.from(f.parse(time)); // could be written f.parse(time, Instant::from);
}

请注意,此格式化程序会正确处理小数秒,因此您无需删除它们。引用DateTimeFormatter.ISO_INSTANT Javadoc(强调我的):

  

解析时,至少需要秒时间字段。 解析从0到9的小数秒

至于为什么它在昨天而不是今天工作,我不知道......

答案 1 :(得分:4)

只是为了帮助任何人以后看到这个问题。

您需要将ISO日期解析为Instant,将其转换为Instant对象,然后从中创建LocalDateTime,提供区域ID。我在这里设置了UTC的区域ID。

代码如下

public static LocalDateTime getISODate(String dateString) {
    DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_INSTANT;
    Instant dateInstant = Instant.from(isoFormatter.parse(dateString));
    LocalDateTime date = LocalDateTime.ofInstant(dateInstant, ZoneId.of(ZoneOffset.UTC.getId()));

    return date;
}

答案 2 :(得分:1)

您不需要 DateTimeFormatter

使用 Instant#parse 将符合 ISO 8601 的日期时间字符串直接解析为 Instant。现代日期时间 API 基于 ISO 8601,只要日期时间字符串符合 ISO 8601 标准,就不需要明确使用 DateTimeFormatter 对象。

演示:

import java.time.Instant;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.parse("2015-09-28T14:46:44.000000Z");
        System.out.println(instant);
    }
}

输出:

2015-09-28T14:46:44Z

ONLINE DEMO

如果我想要 UTC 的 LocalDateTime 怎么办?

Instant 可以转换为其他 java.time 类型,例如

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.parse("2015-09-28T14:46:44.000000Z");
        System.out.println(instant);

        LocalDateTime ldt = instant.atZone(ZoneOffset.UTC).toLocalDateTime();
        System.out.println(ldt);
    }
}

输出:

2015-09-28T14:46:44Z
2015-09-28T14:46:44

ONLINE DEMO

Trail: Date Time 了解有关现代 Date-Time API 的更多信息。

答案 3 :(得分:0)

ISO_INSTANT 没有区域信息。加上那个。 或者改用 DateTimeFormatter.ISO_ZONED_DATE_TIME

import java.time.*;
import java.time.format.*;

public class TestMain {

    DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT.withZone(ZoneId.of("Z"));

    DateTimeFormatter formatter2 = DateTimeFormatter.ISO_ZONED_DATE_TIME

    public static void main(String[] args) {
        ZonedDateTime.parse("2031-12-01T10:58:30Z", formatter);
        ZonedDateTime.parse("2031-12-01T10:58:30Z", formatter2);
    }
}