Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java DateTimeFormatter不';t解析自定义日期格式_Java_Datetime_Java Time_Datetime Parsing - Fatal编程技术网

Java DateTimeFormatter不';t解析自定义日期格式

Java DateTimeFormatter不';t解析自定义日期格式,java,datetime,java-time,datetime-parsing,Java,Datetime,Java Time,Datetime Parsing,我对javaDataTimeFormmater有问题。 我觉得我错过了一些东西,但却不知道到底是什么 String format = "yyyy-MM-dd'T'HH:mm:ss[.S]'T'zxxx"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); String date = "2017-07-05T12:28:36.4TGMT+03:00"; System.out.println(formatter.

我对java
DataTimeFormmater
有问题。 我觉得我错过了一些东西,但却不知道到底是什么

String format = "yyyy-MM-dd'T'HH:mm:ss[.S]'T'zxxx";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);

String date = "2017-07-05T12:28:36.4TGMT+03:00";

System.out.println(formatter.format(ZonedDateTime.now()));
System.out.println(formatter.parse(date));
上面的代码生成当前
ZonedDateTime
的字符串,并尝试使用相同的日期格式化程序解析日期时间字符串。 结果成功生成
2017-07-05T06:07:51.0TCDT-05:00
,但未能解析
2017-07-05T12:28:36.4TGMT+03:00


我的目标是解析
2017-07-05T12:28:36.4TGMT+03:00
,并提出适当的
DateTimeFormatter
,您必须将格式更改为:

String format = "yyyy-MM-dd'T'HH:mm:ss[.S]'T'[zzz][xxx]";
[zzz]
[xxx]
都在可选部分中,因为
zzz
可以解析整个
GMT+03:00
部分,或者只解析区域短名称(例如
CDT
),并且
xxx
只解析偏移部分(例如
-05:00
,因此如果找到
GMT+03:00
,则不需要它)

只是提醒一下,
formatter.parse(date)
返回一个
TemporalAccessor
对象。如果要创建特定类型,最好使用类各自的
parse
方法:

System.out.println(ZonedDateTime.parse(date, formatter)); // 2017-07-05T12:28:36.400+03:00[GMT+03:00]

PS:此格式化程序的唯一问题是,格式化时,它会打印所有可选部分。所以,如果你这样做:

String date = "2017-07-05T12:28:36.4TGMT+03:00";
ZonedDateTime z  = ZonedDateTime.parse(date, formatter);
System.out.println(formatter.format(z));
输出将是:

2017-07-05T12:28:36.4TGMT+03:00+03:00

这是因为
GMT+03:00
zzz
的结果,第二个
+03:00
xxx
的结果。如果您不想这样做,我建议使用两个不同的
DateTimeFormatter
(一个用于解析,另一个用于格式化)

或者(更丑陋的方法),使用两种不同的格式化程序:

DateTimeFormatter noGMT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.S]'T'zzzxxx");
DateTimeFormatter gmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.S]'TGMT'xxx");
然后,您尝试使用第一个进行解析—如果您遇到异常,请尝试使用第二个(或者检查您的输入是否包含
GMT
,以了解使用哪一个)

我个人不喜欢这样,因为
GMT
是区域名称的一部分,不应被视为文字。但最终,您会得到一个具有正确偏移量的
ZoneDateTime
,因此我不确定这种方法有多错误


时区缩写 请注意,您应该(尽可能)避免使用三个字母的缩写(如
CDT
PST
),因为它们是
CDT
既可以是
中央夏时制
(UTC-05:00)、
古巴夏时制
(UTC-04:00),也可以是
中国夏时制
(UTC+09:00)

如果可能,更愿意使用(始终采用
大陆/城市
格式,如
美国/圣保罗
欧洲/柏林
)。根据该列表,有40多个时区使用(或在过去某个地方使用过)CDT缩写

CDT
适用于这种情况,因为有些缩写配置了默认值,可能是由于追溯兼容性的原因,但您不应该在所有情况下都依赖它们

为了确保时区缩写始终有效(以防无法避免使用它们),您可以创建一个使用一组首选区域的格式化程序。在本例中,我使用的是
America/Chicago
(因此,
CST
CDT
将被解析为芝加哥的时区):

Set preferedZones=new HashSet();
首选区域。添加(“美国/芝加哥”)区域ID;
DateTimeFormatter formatter=新的DateTimeFormatterBuilder()
//追加模式的第一部分(时区之前)
.appendPattern(“yyyy-MM-dd'T'HH:MM:ss[.S]'T'”)
//附加区域名称,使用首选区域(可选)
.optionalStart().appendZoneText(TextStyle.SHORT,PreferredZones)。optionalEnd()
//偏移量(可选)
.appendPattern(“[xxx]”)
//创建格式化程序
.toFormatter();
此格式化程序的工作方式与上述相同,适用于您的两种输入(带和不带
GMT
),并在输入中包含
CDT
时使用
America/Chicago
作为默认时区。根据您的用例,您可以在集合中添加任意数量的区域

只是提醒一下,这个格式化程序在输出方面有相同的问题(它打印所有可选部分),如上所述。

tl;博士 细节 您的格式很奇怪,比如对标准格式的奇怪误解或损坏

如果您的所有输入在最后一部分中都有“TGMT”,请将其去掉以符合ISO 8601

在解析/生成字符串时,java.time类默认使用标准格式,因此无需定义格式模式

OffsetDateTime odt = OffsetDateTime.parse( "2017-07-05T12:28:36.4TGMT+03:00".replace( "TGMT" , "" ) ) ;

不要使用3-4个字母的伪时区,如
CMT
EST
IST
。这些时区不是实际时区,也不是标准时区,甚至不是唯一的(!)。实时时区名称的格式为
大陆/地区
,例如
美国/蒙特利尔
太平洋/奥克兰

也可以使用
ooooo
作为时区,但解析在Java 8中有缺陷,在Java 9中得到纠正:@CarlosHeuberger确实!我尝试过
ooo
,但它只适用于格式化。它将d的使用是正确的,但代码是错误的fist+second line
int pos=position;int end=pos+text.length();
end大于字符串长度最终导致StringIndexOutOfBoundsException(位置是开始查找时区的位置),这是一种奇怪的格式。请尽可能使用标准格式。
OffsetDateTime.parse(
    "2017-07-05T12:28:36.4TGMT+03:00".replace( "TGMT" , "" ) 
)
OffsetDateTime odt = OffsetDateTime.parse( "2017-07-05T12:28:36.4TGMT+03:00".replace( "TGMT" , "" ) ) ;