【问题标题】:How to get ZoneId, LocalDateTime and Instant from TemporalAccessor如何从 TemporalAccessor 获取 ZoneId、LocalDateTime 和 Instant
【发布时间】:2019-12-07 11:58:06
【问题描述】:

我正在使用下面的代码来解析日期字符串:

    String time = "2 Jun 2019 03:51:17 PM ACST";
    String pattern = "d MMM yyyy hh:mm:ss a z"; // z detects the time zone (ACST here)
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);

 // ZonedDateTime localDateTime = LocalDateTime.from(formatter.parse(time)).atZone(ZoneId.of("Australia/Adelaide"));
 // localDateTime.toInstant().toEpochMilli();

当我通过调试检查formatter.parse(time)时,它已经具有纪元时间和时区:

// formatter.parse(time) :
{InstantSeconds=1559456477},ISO,Australia/Adelaide resolved to 2019-06-02T15:51:17

我的问题是如何从Parsed 类型的formatter.parse(time) 中提取时区(此处为澳大利亚/阿德莱德),以便在此行的atZone() 中动态使用时区? :

ZonedDateTime localDateTime = LocalDateTime.from(formatter.parse(time)).
                                     atZone(ZoneId.of("Australia/Adelaide"));

即使是 Furthur,如何从 formatter.parse(time) 响应中提取 InstantSeconds=1559456477 以避免采取以下更多步骤来获取纪元时间戳? :

ZonedDateTime localDateTime = LocalDateTime.from(formatter.parse(time)).
                                     atZone(ZoneId.of("Australia/Adelaide"));

localDateTime.toInstant().toEpochMilli();

【问题讨论】:

  • 你是不是过于复杂了? ZonedDateTime.parse(time, formatter) 为您提供具有正确区域的ZonedDateTime(除非缩写词不明确,但它们通常是)。或者 ZonedDateTime.from(formatter.parse(time)) 如果出于某种原因您更喜欢。类似地,only 获取您可以使用的区域ZoneId.from(formatter.oarse(time))
  • @OleV.V.是的,你是对的。我不知道ZonedDateTime.parse(time, formatter) 也没有类似于LocalDateTime.parse()ZoneId.from()。因此,要在一行中实现纪元时间,这可以正常工作:ZonedDateTime.parse(time, formatter).toInstant().toEpochMilli();;除了我们需要 zoneID 的地方,ZoneId.from(formatter.oarse(time)) 会派上用场。

标签: java parsing time


【解决方案1】:

您无法从DateTimeFormatter 中提取秒数或区域ID,但您可以使用ZonedDateTime 对象来完成。看看下面的代码,想知道你的时间String 似乎是在"America/Manaus",这似乎不等于澳大利亚中部标准时间...

public static void main(String args[]) throws Exception {
    String time = "2 Jun 2019 03:51:17 PM ACST";
    String pattern = "d MMM yyyy hh:mm:ss a z"; // z detects the time zone (ACST here)
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);

    // parse a time object using the formatter and the time String
    ZonedDateTime zdt = ZonedDateTime.parse(time, formatter);
    // print it using a standard formatter
    System.out.println(zdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
    // extract the zone id
    ZoneId zoneId = zdt.getZone();
    // print the zone id
    System.out.println("This time is of zone " + zoneId);

    // retrieve the instant seconds
    Instant instant = zdt.toInstant();
    // print the epoch seconds of another time zone
    System.out.println("Epoch seconds in Australia/Adelaide are " 
            + instant.atZone(ZoneId.of("Australia/Adelaide")).toEpochSecond());
}

当我运行它时,它会输出

2019-06-02T15:51:17-04:00[America/Manaus]
This time is of zone America/Manaus
Epoch seconds in Australia/Adelaide are 1559505077

它显示了如何提取纪元秒数和时区,但不知何故无法识别 ACST 应该是什么意思。

【讨论】:

  • 谢谢。我不确定为什么它会给你America/Manaus 作为时区(是你当地的时区吗?)。您的代码仍然在我的计算机上的第二行输出中生成 Australia/Adelaide
  • @DummyBeginner 很有趣,这不是我的语言环境,但德国......真的很奇怪,也许值得更多测试。
【解决方案2】:

DateTimeFormatter.parse 方法返回TemporalAccessor,其中包含日期、时间和其他一些信息,您可以通过查询获得该信息

default <R> R query(TemporalQuery<R> query)

定义对时间对象的只读访问的框架级接口,例如日期、时间、偏移量或这些的某种组合。

这是日期、时间和偏移对象的基本接口类型。它由那些可以提供信息作为字段或查询的类实现。

TemporalQuery为功能接口

最常见的实现是方法引用,例如 LocalDate::from 和 ZoneId::from。其他常见查询在 TemporalQueries 中作为静态方法提供。

String time = "2 Jun 2019 03:51:17 PM ACST";
String pattern = "d MMM yyyy hh:mm:ss a z";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);

TemporalAccessor parsedTime = formatter.parse(time);

ZoneId zone = parsedTime.query(ZoneId::from);

LocalDateTime localDateTime = parsedTime.query(LocalDateTime::from);

Instant instant = parsedTime.query(Instant::from);

System.out.println(zone);
System.out.println(localDateTime);
System.out.println(instant);

【讨论】:

    猜你喜欢
    • 2017-02-20
    • 2023-03-18
    • 2017-03-09
    • 1970-01-01
    • 2017-09-29
    • 2017-11-07
    • 2020-12-24
    • 1970-01-01
    • 2018-06-02
    相关资源
    最近更新 更多