Java XMLGregorianCalendar 正在更改时间 - 奇怪的行为
Java XMLGregorianCalendar is changing the time - Strange behavior
我有一个日期作为输入 = 2021-03-12T10:42:01.000Z.... 我想转换成这种格式:
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
public String getDate(XMLGregorianCalendar input) {
DateFormat f = new SimpleDateFormat(pattern);
input.toGregorianCalendar().setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));
String output = f.format(input.toGregorianCalendar().getTime());
System.out.println(output);
}
2021-03-12T12:42:01+0200
基本上,它增加了 2 小时。可能跟时区有关,我没在别的电脑上测试过。我有 2 个问题:
- 为什么会这样
- 我能做些什么来避免它?这是一个遗留应用程序,所以我不想做大的改变
谢谢
Basically, it's adding 2hs more
不是真的。它为您提供同一时间的输出,但在您的系统本地时区 - 因为您正在创建 SimpleDateFormat
而不指定时区(或文化):
DateFormat f = new SimpleDateFormat(pattern);
我个人建议完全避免使用 java.text.SimpleDateFormat
,而更喜欢 java.time
类型和格式化程序。但是,如果您确定要使用 SimpleDateFormat
,只需确保将时区设置为 UTC(假设您始终需要 UTC)并理想地设置文化(例如 Locale.ROOT
)。
是正确的,也是聪明的。您似乎只是看到了时区调整。您的两个字符串 2021-03-12T10:42:01.000Z
& 2021-03-12T12:42:01+0200
代表同一时刻。中午 12 点,如果比 UTC 早两个小时,则与上午 10 点相同,与 UTC 的偏移量为零小时-分钟-秒。
而且,正如其他答案中提到的,您真的应该避免使用与 Java.
的最早版本捆绑在一起的糟糕的日期时间 classes
tl;博士
myXMLGregorianCalendar // Legacy class, representing a moment as seen in some time zone.
.toGregorianCalendar() // Another legacy class, also representing a moment as seen in some time zone.
.toZonedDateTime() // A modern *java.time* class, representing a moment as seen in some time zone.
.toInstant() // Another *java.time* class, for representing a moment as seen in UTC.
.truncatedTo( // Lopping off some smaller part of the date-time value.
ChronoUnit.SECONDS // Specifying whole seconds as our granularity of truncation, so lopping off any fractional second.
) // Returns another `Instant` object, rather than altering (mutating) the original, per immutable objects pattern.
.toString() // Generating text representing the content of our `Instant` object, using standard ISO 8601 format.
java.time
现代方法使用 java.time classes,多年前取代了 SimpleDateFormat
、XMLGregorianCalendar
、GregorianCalendar
,等等。
转换传统<——>现代
您可以轻松地将旧类型转换为 java.time。在旧 classes.
上寻找新的 to
/from
方法
ZonedDateTime zdt = myXMLGregorianCalendar.toGregorianCalendar().toZonedDateTime() ;
调整为零偏移
通过提取 Instant
从任何时区调整为 UTC。此 class 表示以 UTC 格式显示的时刻,始终以 UTC 格式显示。
Instant instant = zdt.toInstant() ;
了解 zdt
和 instant
都代表同一时刻,时间轴上的同一点,但挂钟时间不同。
截断
鉴于您在问题中看到的格式化模式,您似乎希望以整秒为粒度进行工作。要去掉任何小数秒,请截断为秒。
Instant truncated = instant.truncatedTo( ChronoUnit.SECONDS ) ;
ISO 8601
您需要的文本格式在 ISO 8601 标准中定义。该标准在 java.time 中默认用于 parsing/generating 字符串。因此无需指定任何格式模式。
String output = truncated.toString() ;
我有一个日期作为输入 = 2021-03-12T10:42:01.000Z.... 我想转换成这种格式:
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
public String getDate(XMLGregorianCalendar input) {
DateFormat f = new SimpleDateFormat(pattern);
input.toGregorianCalendar().setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));
String output = f.format(input.toGregorianCalendar().getTime());
System.out.println(output);
}
2021-03-12T12:42:01+0200
基本上,它增加了 2 小时。可能跟时区有关,我没在别的电脑上测试过。我有 2 个问题:
- 为什么会这样
- 我能做些什么来避免它?这是一个遗留应用程序,所以我不想做大的改变
谢谢
Basically, it's adding 2hs more
不是真的。它为您提供同一时间的输出,但在您的系统本地时区 - 因为您正在创建 SimpleDateFormat
而不指定时区(或文化):
DateFormat f = new SimpleDateFormat(pattern);
我个人建议完全避免使用 java.text.SimpleDateFormat
,而更喜欢 java.time
类型和格式化程序。但是,如果您确定要使用 SimpleDateFormat
,只需确保将时区设置为 UTC(假设您始终需要 UTC)并理想地设置文化(例如 Locale.ROOT
)。
2021-03-12T10:42:01.000Z
& 2021-03-12T12:42:01+0200
代表同一时刻。中午 12 点,如果比 UTC 早两个小时,则与上午 10 点相同,与 UTC 的偏移量为零小时-分钟-秒。
而且,正如其他答案中提到的,您真的应该避免使用与 Java.
的最早版本捆绑在一起的糟糕的日期时间 classestl;博士
myXMLGregorianCalendar // Legacy class, representing a moment as seen in some time zone.
.toGregorianCalendar() // Another legacy class, also representing a moment as seen in some time zone.
.toZonedDateTime() // A modern *java.time* class, representing a moment as seen in some time zone.
.toInstant() // Another *java.time* class, for representing a moment as seen in UTC.
.truncatedTo( // Lopping off some smaller part of the date-time value.
ChronoUnit.SECONDS // Specifying whole seconds as our granularity of truncation, so lopping off any fractional second.
) // Returns another `Instant` object, rather than altering (mutating) the original, per immutable objects pattern.
.toString() // Generating text representing the content of our `Instant` object, using standard ISO 8601 format.
java.time
现代方法使用 java.time classes,多年前取代了 SimpleDateFormat
、XMLGregorianCalendar
、GregorianCalendar
,等等。
转换传统<——>现代
您可以轻松地将旧类型转换为 java.time。在旧 classes.
上寻找新的to
/from
方法
ZonedDateTime zdt = myXMLGregorianCalendar.toGregorianCalendar().toZonedDateTime() ;
调整为零偏移
通过提取 Instant
从任何时区调整为 UTC。此 class 表示以 UTC 格式显示的时刻,始终以 UTC 格式显示。
Instant instant = zdt.toInstant() ;
了解 zdt
和 instant
都代表同一时刻,时间轴上的同一点,但挂钟时间不同。
截断
鉴于您在问题中看到的格式化模式,您似乎希望以整秒为粒度进行工作。要去掉任何小数秒,请截断为秒。
Instant truncated = instant.truncatedTo( ChronoUnit.SECONDS ) ;
ISO 8601
您需要的文本格式在 ISO 8601 标准中定义。该标准在 java.time 中默认用于 parsing/generating 字符串。因此无需指定任何格式模式。
String output = truncated.toString() ;