【问题标题】:DateTimeFormatter trouble with a patternDateTimeFormatter 模式问题
【发布时间】:2014-07-20 15:01:02
【问题描述】:

我正在编写一个股票程序,它(到目前为止)通过如下请求从“Markit on Demand”获取数据:

http://dev.markitondemand.com/Api/v2/Quote/xml?symbol=aapl

这将返回 xml 中的数据,以及股票的各种度量(符号、名称、最后价格、变化、时间戳等)。

我无法在 Java 8 中创建 DateTimeFormatter 来制作时间戳。

时间戳的一个例子:

Fri Jul 18 15:59:00 UTC-04:00 2014

目前我的模式如下:

EEE MMM d HH:mm:ss OOOO yyyy

我相信你们中的一些人会发现,我在偏移方面遇到了问题。

来自文档:

偏移 X 和 x:这会根据模式字母的数量来格式化偏移。一个字母仅输出小时,例如“+01”,除非分钟不为零,在这种情况下也会输出分钟,例如“+0130”。两个字母输出小时和分钟,不带冒号,如'+0130'。三个字母输出小时和分钟,带有冒号,例如'+01:30'。四个字母输出小时和分钟以及可选的秒,不带冒号,例如'+013015'。五个字母输出小时和分钟以及可选的秒,带有冒号,例如'+01:30:15'。六个或更多字母会引发 IllegalArgumentException。当要输出的偏移量为零时,模式字母“X”(大写)将输出“Z”,而模式字母“x”(小写)将输出“+00”、“+0000”或“+00” :00'。

Offset O:这会根据模式字母的数量来格式化本地化的偏移量。一个字母输出本地化偏移量的简写形式,即本地化偏移量文本,例如“GMT”,小时不带前导零,如果非零,则可选两位数分钟和秒,以及冒号,例如“GMT+8” '。四个字母输出完整形式,即本地化偏移文本,例如“GMT”,带有 2 位小时和分钟字段,如果非零,则可选第二个字段和冒号,例如“GMT+08:00”。任何其他字母计数都会引发 IllegalArgumentException。

偏移 Z:这会根据图案字母的数量来格式化偏移。一个、两个或三个字母输出小时和分钟,不带冒号,例如'+0130'。当偏移量为零时,输出将为“+0000”。四个字母输出本地化偏移的完整形式,相当于四个字母的Offset-O。如果偏移量为零,则输出将是相应的本地化偏移量文本。五个字母输出小时、分钟,如果非零,则可选秒,带冒号。如果偏移量为零,则输出“Z”。六个或更多字母会引发 IllegalArgumentException。

// String rawDate = Fri Jul 18 15:59:00 UTC-04:00 2014   
DateTimeFormatter PARSER_PATTERN = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss 'UTC'XXX yyyy");
ZonedDateTime timeStamp = ZonedDateTime.parse(rawDate, PARSER_PATTERN);

这可行,但我很好奇为什么(代替 'UTC'XXX)OOOO 不起作用。

【问题讨论】:

  • Java 8 解析格式模式 OOOO 时会不会有 bug?我在尝试解析字符串末尾的偏移量为GMT+02:00 的字符串时得到StringIndexOutOfBoundsException。在 Java 9 中,同样的解析工作很顺利,这就是我怀疑 Java 8 中存在错误的原因。
  • 来自the bug database: java.time.format.DateTimeFormatter can't parse localized zone-offset。 “DateTimeFormatter 无法解析自己的输出以查找包含“O”的格式字符串。”
  • 在我的 Java 9 中,它适用于 GMT-04:00,但我仍然无法使其适用于 UTC-04:00。不知道为什么。

标签: java java-8 java-time datetimeoffset datetimeformatter


【解决方案1】:

我决定使用字符串“UTC”,因为时间戳总是以“UTC+00:00”的形式给出。

我想出的与分区日期时间匹配的最终模式:

Fri Jul 18 15:59:00 UTC-04:00 2014

EEE MMM d HH:mm:ss 'UTC'XXX yyyy

【讨论】:

  • 看起来很合理,但这将匹配OffsetDateTime,而不是ZonedDateTime
  • 但是,它并没有真正回答您关于为什么 OOOO 不起作用的原始问题。根据文档,它应该。在on the same page 部分的正上方,它显示了UTC-08:00 的示例。
  • 这就是我有点困惑的原因......我回答了我最初的问题,即它应该是什么,但没有回答为什么OOOO 不起作用。
  • 也许如果您编辑原始问题以删除有关您的股票程序的部分并仅显示使用 DateTimeFormatter 与此特定输入字符串的 Java 代码,比我更熟悉的人可以回答这个问题至于为什么OOOO 不起作用。但是很好地找出解决方法。
【解决方案2】:

时区不要使用固定文本:

不要为时区使用固定文本(例如'UTC'),因为这种方法可能会在其他语言环境中失败。

您可以使用E MMM d H:m:s VV u 模式解析您的日期时间字符串。

演示:

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "Fri Jul 18 15:59:00 UTC-04:00 2014";
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E MMM d H:m:s VV u", Locale.ENGLISH);
        ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
        System.out.println(zdt);
    }
}

输出:

2014-07-18T15:59-04:00[UTC-04:00]

ONLINE DEMO


Trail: Date Time 了解有关现代日期时间 API 的更多信息。

【讨论】:

  • 太棒了!我在 Java 8、9 和 11 上进行了测试。它可以工作。同时使用 UTC-04:00GMT-04:00
  • 我非常喜欢这个。它之所以有效,是因为VV 解析了 ZoneId (per the format patterns table),并且根据 ZoneId 的定义,“UTC”、“GMT”和“UT”被识别为偏移样式 ID 的前缀(根据 third paragraph under "Time-zone IDs" here)。请注意,完全相同的格式字符串适用于任何有效的 ZoneID,例如输入字符串中的America/Los_Angeles
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-20
  • 1970-01-01
  • 1970-01-01
  • 2021-11-05
  • 2019-11-12
  • 1970-01-01
  • 2021-12-08
相关资源
最近更新 更多