为什么 GregorianCalendar 在日期结束时随机添加 "Z" 而有时不添加
Why GregorianCalendar randomly add "Z" at the end of date and sometimes don't
我必须获取当前日期,加上 20 年,然后将其转移到 XML 对象中。
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "XMLCommande", propOrder = {
...
"dateLivSouhaitee",
...
})
public class XMLCommande {
...
@XmlElement(name = "date_liv_souhaitee", required = true)
@XmlSchemaType(name = "date")
protected XMLGregorianCalendar dateLivSouhaitee;
...
}
没有指定日期格式,都是默认的:
XMLCommande xmlMessage = new XMLCommande();
GregorianCalendar gregorianCalendar = new GregorianCalendar();
gregorianCalendar.add(Calendar.YEAR, 20);
ligne.setDateLivSouhaitee(DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar2));
问题是,出于某种未知原因,有时我在日期末尾有一个“Z”,但有时却没有:
<date_liv_souhaitee>2041-05-26Z</date_liv_souhaitee>
<date_liv_souhaitee>2041-05-26+02:00</date_liv_souhaitee>
这是同一台服务器,为什么有时我的 Z 带有“+02:00”而有时却没有?
如何强制格式始终为:
<date_liv_souhaitee>2041-05-26+02:00</date_liv_souhaitee>
日期时间字符串中的 Z
是零时区偏移量的 timezone designator。它代表祖鲁语并指定 Etc/UTC
时区(时区偏移量为 +00:00
小时)。
在另一种情况下,您在日期时间字符串中添加了 +02:00
时区偏移量,即 UTC 中相应的日期时间将为给定的日期时间减去 2 小时。您可以将 UTC 日期时间转换为具有 +02:00
时区偏移的日期时间,例如
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class Main {
public static void main(String[] args) throws DatatypeConfigurationException {
ZonedDateTime zdtUtc = LocalDate.of(2041, 5, 26).atStartOfDay(ZoneOffset.UTC);
System.out.println(zdtUtc);
ZonedDateTime zdtOffsetTwoHrs = zdtUtc.withZoneSameInstant(ZoneOffset.of("+02:00"));
System.out.println(zdtOffsetTwoHrs);
GregorianCalendar gregorianCalendar = GregorianCalendar.from(zdtOffsetTwoHrs);
XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gregorianCalendar);
System.out.println(xmlGregorianCalendar);
}
}
输出:
2041-05-26T00:00Z
2041-05-26T02:00+02:00
2041-05-26T02:00:00.000+02:00
为什么我有时得到 Z 而有时得到 +02:00?
如果两者都来自使用无参数构造函数创建 GregorianCalendar
并将其转换为 XMLGregorianCalendar
,那么最好的解释是有人正在修改您的 JVM 的默认时区。您自己的程序的一部分可能会在同一 JVM 中执行此操作或某些其他程序 运行。演示:
TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Europe/Paris")));
GregorianCalendar gc = new GregorianCalendar();
System.out.println(DatatypeFactory.newInstance().newXMLGregorianCalendar(gc));
TimeZone.setDefault(TimeZone.getTimeZone(ZoneOffset.UTC));
gc = new GregorianCalendar();
System.out.println(DatatypeFactory.newInstance().newXMLGregorianCalendar(gc));
这些代码行的输出是:
2021-05-26T19:41:29.744+02:00
2021-05-26T17:41:29.776Z
new GregorianCalendar()
创建一个 GregorianCalendar
,它在创建时具有 JVM 的默认时区。正如 Arvind Kumar Avinash 已经解释的那样,UTC 的偏移量 0 根据 ISO 8601 标准呈现为 Z
。
我怎样才能总是强制+02:00?
我建议您使用 java.time,现代 Java 日期和时间 API,用于约会工作。 OffsetDateTime
class 表示具有 UTC 偏移量的日期和时间,因此只需将偏移量设置为 +2。
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.ofHours(2));
OffsetDateTime in20Years = now.plusYears(20);
String dateStringWithOffset0200 = in20Years.format(DateTimeFormatter.ISO_OFFSET_DATE);
System.out.println(dateStringWithOffset0200);
2041-05-26+02:00
如果您确实需要 XMLGregorianCalendar
,请根据我们刚刚获得的字符串构建一个:
XMLGregorianCalendar xmlgc = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(dateStringWithOffset0200);
System.out.println(xmlgc);
2041-05-26+02:00
链接
- Oracle tutorial: Date Time 解释如何使用 java.time.
- Wikipedia article: ISO 8601
我必须获取当前日期,加上 20 年,然后将其转移到 XML 对象中。
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "XMLCommande", propOrder = {
...
"dateLivSouhaitee",
...
})
public class XMLCommande {
...
@XmlElement(name = "date_liv_souhaitee", required = true)
@XmlSchemaType(name = "date")
protected XMLGregorianCalendar dateLivSouhaitee;
...
}
没有指定日期格式,都是默认的:
XMLCommande xmlMessage = new XMLCommande();
GregorianCalendar gregorianCalendar = new GregorianCalendar();
gregorianCalendar.add(Calendar.YEAR, 20);
ligne.setDateLivSouhaitee(DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar2));
问题是,出于某种未知原因,有时我在日期末尾有一个“Z”,但有时却没有:
<date_liv_souhaitee>2041-05-26Z</date_liv_souhaitee>
<date_liv_souhaitee>2041-05-26+02:00</date_liv_souhaitee>
这是同一台服务器,为什么有时我的 Z 带有“+02:00”而有时却没有? 如何强制格式始终为:
<date_liv_souhaitee>2041-05-26+02:00</date_liv_souhaitee>
日期时间字符串中的 Z
是零时区偏移量的 timezone designator。它代表祖鲁语并指定 Etc/UTC
时区(时区偏移量为 +00:00
小时)。
在另一种情况下,您在日期时间字符串中添加了 +02:00
时区偏移量,即 UTC 中相应的日期时间将为给定的日期时间减去 2 小时。您可以将 UTC 日期时间转换为具有 +02:00
时区偏移的日期时间,例如
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class Main {
public static void main(String[] args) throws DatatypeConfigurationException {
ZonedDateTime zdtUtc = LocalDate.of(2041, 5, 26).atStartOfDay(ZoneOffset.UTC);
System.out.println(zdtUtc);
ZonedDateTime zdtOffsetTwoHrs = zdtUtc.withZoneSameInstant(ZoneOffset.of("+02:00"));
System.out.println(zdtOffsetTwoHrs);
GregorianCalendar gregorianCalendar = GregorianCalendar.from(zdtOffsetTwoHrs);
XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gregorianCalendar);
System.out.println(xmlGregorianCalendar);
}
}
输出:
2041-05-26T00:00Z
2041-05-26T02:00+02:00
2041-05-26T02:00:00.000+02:00
为什么我有时得到 Z 而有时得到 +02:00?
如果两者都来自使用无参数构造函数创建 GregorianCalendar
并将其转换为 XMLGregorianCalendar
,那么最好的解释是有人正在修改您的 JVM 的默认时区。您自己的程序的一部分可能会在同一 JVM 中执行此操作或某些其他程序 运行。演示:
TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Europe/Paris")));
GregorianCalendar gc = new GregorianCalendar();
System.out.println(DatatypeFactory.newInstance().newXMLGregorianCalendar(gc));
TimeZone.setDefault(TimeZone.getTimeZone(ZoneOffset.UTC));
gc = new GregorianCalendar();
System.out.println(DatatypeFactory.newInstance().newXMLGregorianCalendar(gc));
这些代码行的输出是:
2021-05-26T19:41:29.744+02:00 2021-05-26T17:41:29.776Z
new GregorianCalendar()
创建一个 GregorianCalendar
,它在创建时具有 JVM 的默认时区。正如 Arvind Kumar Avinash 已经解释的那样,UTC 的偏移量 0 根据 ISO 8601 标准呈现为 Z
。
我怎样才能总是强制+02:00?
我建议您使用 java.time,现代 Java 日期和时间 API,用于约会工作。 OffsetDateTime
class 表示具有 UTC 偏移量的日期和时间,因此只需将偏移量设置为 +2。
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.ofHours(2));
OffsetDateTime in20Years = now.plusYears(20);
String dateStringWithOffset0200 = in20Years.format(DateTimeFormatter.ISO_OFFSET_DATE);
System.out.println(dateStringWithOffset0200);
2041-05-26+02:00
如果您确实需要 XMLGregorianCalendar
,请根据我们刚刚获得的字符串构建一个:
XMLGregorianCalendar xmlgc = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(dateStringWithOffset0200);
System.out.println(xmlgc);
2041-05-26+02:00
链接
- Oracle tutorial: Date Time 解释如何使用 java.time.
- Wikipedia article: ISO 8601