Java 8日期时间格式化日期+偏移量

3

我需要构建一个 XMLGregorianCalendar 用于一个期望以 yyyy-MM-dd+01:00 格式接收日期的Webservice,+ 后面的值是根据时区偏移量计算得出的。

目前我已经尝试了以下方法:

DateTimeFormatter formatterDateWithOffset = DateTimeFormatter.ofPattern("yyyy-MM-ddZZ");

XMLGregorianCalendar xcal = DatatypeFactory.newInstance()
    .newXMLGregorianCalendar(zonedDateTime.format(formatterDateWithOffset));

但这会导致一个 IllegalArgumentException,因为格式化程序会生成 2017-09-29+0200

是否有可能定义所需格式的格式字符串?


1
为什么要使用ZonedDateTime而不是LocalDateTime? - daniu
你试过使用 yyyy-MM-ddZZZZ 吗?JavaDoc 中写道:“一个、两个或三个字母输出小时和分钟,不带冒号,例如 '+0130',... 多个字母输出本地化偏移的完整形式”。 - Thomas
3个回答

1
如果你查看DateTimeFormatter的JavaDoc,你会看到这样的内容: Offset X and x:这基于模式字母数量格式化偏移量。一个字母只输出小时,例如'+01',除非分钟不为零,在这种情况下还会输出分钟,例如'+0130'。两个字母输出小时和分钟,没有冒号,例如'+0130'。三个字母输出小时和分钟,有冒号,例如'+01:30'。... 模式字母“X”(大写)将在要输出的偏移量为零时输出“Z”,而模式字母“x”(小写)将输出“+00”、“+0000”或“+00:00”。
因此,DateTimeFormatter formatterDateWithOffset = DateTimeFormatter.ofPattern("yyyy-MM-ddxxx");应该可以工作。
在我的评论中,我建议使用ZZZZ,因为JavaDoc也暗示了这一点,但它也会添加GMT部分(即使JavaDoc指出:“五个字母输出小时、分钟,可选秒钟如果不为零,带有冒号”),ZZZZZ似乎也能工作。

0

你可以创建一个XMLGregorianCalendar实例,而不是解析它,将年、月等传递给它:

XMLGregorianCalendar xcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(year, month....)

0

正如@Thomas的回答所说,一种替代方案是使用xxx(或XXX),如在javadoc中解释的那样。它们之间唯一的区别是当偏移量为零时:XXX格式化为Z,而xxx格式化为+00:00

Pattern  Count  Equivalent builder methods
-------  -----  --------------------------
XXX      3      appendOffset("+HH:MM","Z")
xxx      3      appendOffset("+HH:MM","+00:00")

无论如何,只需选择其中一个(我已经使用ZonedDateTimeZoneOffset.UTC进行了测试,两者都可以):

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-ddXXX");
String str = formatter.format(zonedDateTime);
XMLGregorianCalendar xcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(str);

如果您拥有一个ZonedDateTime,将其转换为一个GregorianCalendar更容易,然后将其传递给您的DatatypeFactory

ZonedDateTime zonedDateTime = ZonedDateTime.now();
GregorianCalendar cal = GregorianCalendar.from(zonedDateTime);
XMLGregorianCalendar xcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);

一个棘手的细节是,当使用上述String模式(仅包含日期)时,结果将把时间字段(小时、分钟、秒和毫秒)设置为零,而转换为GregorianCalendar将使用在ZonedDateTime中设置的时间。
但是,在将其转换为GregorianCalendar之前,您可以将时间设置为午夜。
// convert to calendar (set the time to 00:00:00.000)
GregorianCalendar cal = GregorianCalendar.from(zonedDateTime.with(LocalTime.MIDNIGHT));

通过这样做,结果将与使用String相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接