Java 如何使用默认区域解析 ZonedDateTime?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27293994/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to parse ZonedDateTime with default zone?
提问by Sergey Ponomarev
How to parse ZoneDateTime
from string that doesn't contain zone
and others fields?
如何ZoneDateTime
从不包含zone
其他字段的字符串中解析?
Here is test in Spock to reproduce:
这是在 Spock 中重现的测试:
import spock.lang.Specification
import spock.lang.Unroll
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
@Unroll
class ZonedDateTimeParsingSpec extends Specification {
def "DateTimeFormatter.ISO_ZONED_DATE_TIME parsing incomplete date: #value #expected"() {
expect:
ZonedDateTime.parse(value, DateTimeFormatter.ISO_ZONED_DATE_TIME) == expected
where:
value | expected
'2014-04-23T04:30:45.123Z' | ZonedDateTime.of(2014, 4, 23, 4, 30, 45, 123_000_000, ZoneOffset.UTC)
'2014-04-23T04:30:45.123+01:00' | ZonedDateTime.of(2014, 4, 23, 4, 30, 45, 123_000_000, ZoneOffset.ofHours(1))
'2014-04-23T04:30:45.123' | ZonedDateTime.of(2014, 4, 23, 4, 30, 45, 123_000_000, ZoneId.systemDefault())
'2014-04-23T04:30' | ZonedDateTime.of(2014, 4, 23, 4, 30, 0, 0, ZoneId.systemDefault())
'2014-04-23' | ZonedDateTime.of(2014, 4, 23, 0, 0, 0, 0, ZoneId.systemDefault())
}
}
First two test passed, all others failed with DateTimeParseException:
前两个测试通过了,所有其他测试都失败了 DateTimeParseException:
- '2014-04-23T04:30:45.123' could not be parsed at index 23
- '2014-04-23T04:30' could not be parsed at index 16
- '2014-04-23' could not be parsed at index 10
- 无法在索引 23 处解析“2014-04-23T04:30:45.123”
- 无法在索引 16 处解析“2014-04-23T04:30”
- 无法在索引 10 处解析“2014-04-23”
How can I parse incomplete dates with time and zone setted to default?
如何在时间和区域设置为默认值的情况下解析不完整的日期?
采纳答案by bowmore
Since the ISO_ZONED_DATE_TIME
formatter expects zone or offset information, parsing fails.
You'll have to make a DateTimeFormatter
that has optional parts for both the zone information and the time part.
It's not too hard reverse engineering the ZonedDateTimeFormatter
and adding optional tags.
由于ISO_ZONED_DATE_TIME
格式化程序需要区域或偏移信息,因此解析失败。您必须制作一个DateTimeFormatter
具有区域信息和时间部分的可选部分。逆向工程ZonedDateTimeFormatter
和添加可选标签并不太难。
Then you parse the String
using the parseBest()
method of the formatter. Then, for suboptimal parse results you can create the ZonedDateTime
using any default you want.
然后你String
使用parseBest()
格式化程序的方法解析。然后,对于次优的解析结果,您可以ZonedDateTime
使用任何您想要的默认值来创建。
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.optionalStart() // time made optional
.appendLiteral('T')
.append(ISO_LOCAL_TIME)
.optionalStart() // zone and offset made optional
.appendOffsetId()
.optionalStart()
.appendLiteral('[')
.parseCaseSensitive()
.appendZoneRegionId()
.appendLiteral(']')
.optionalEnd()
.optionalEnd()
.optionalEnd()
.toFormatter();
TemporalAccessor temporalAccessor = formatter.parseBest(value, ZonedDateTime::from, LocalDateTime::from, LocalDate::from);
if (temporalAccessor instanceof ZonedDateTime) {
return ((ZonedDateTime) temporalAccessor);
}
if (temporalAccessor instanceof LocalDateTime) {
return ((LocalDateTime) temporalAccessor).atZone(ZoneId.systemDefault());
}
return ((LocalDate) temporalAccessor).atStartOfDay(ZoneId.systemDefault());
回答by JodaStephen
The formatter has a withZone()
methodthat can be called to provide the missing time-zone.
格式化程序有一个withZone()
方法可以调用以提供缺少的时区。
ZonedDateTime.parse(
value,
DateTimeFormatter.ISO_ZONED_DATE_TIME.withZone(ZoneId.systemDefault()))
Bear in mind that there was a bug, so you need 8u20 or later for it to work fully.
请记住,存在一个错误,因此您需要 8u20 或更高版本才能使其完全工作。