Gson 使用时区反序列化 Java.util.Date
Gson deserialize Java.util.Date with timezone
我用日期反序列化一个 json 字符串:
"created_at": "2015-12-24T17:41:54+01:00",
我为 gsonBuilder 设置了日期格式:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create();
反序列化工作没有崩溃;不幸的是,当我打印结果时,它是不正确的:
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ssZ");
String str = ft.format(response.createdAt);
结果是:
2015-12-24T11:41:54-0500
而不是:
2015-12-24T17:41:54+01:00
您没有设置时区,只是在 date/time 的末尾添加了一个 Z,因此它看起来像 GMT date/time,但这不会改变值。
将时区设置为 GMT,这将是正确的。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
java.time
接受的答案是正确的。但是过时了。 java.text.SimpleDateFormat 和 java.util.Date classes 已被添加到 Java 8 及更高版本的 java.time 框架淘汰。更容易使用和更明智。
ISO 8601
您输入的字符串格式符合ISO 8601标准。当 parsing/generating 字符串表示 date-time 值时,java.time classes 使用 ISO 8601 作为它们的默认格式。
String input = "2015-12-24T17:41:54+01:00";
Offset-From-UTC
该输入字符串包含 +01:00
的 offset-from-UTC,这意味着比 UTC 早一个小时。
ZonedDateTime zdt = ZonedDateTime.parse ( input );
ZoneId z = zdt.getZone ();
偏移量与时区
但是那个偏移量不是时区。时区是一个偏移加上 规则,用于处理异常调整,例如夏令时 (DST)。所以你可能想要分配 a specific time zone you have in mind as being intended by that string. Perhaps you intended Amsterdam time。
我们可以申请一个时区以获得另一个ZonedDateTime
object. This pattern of creating a new object based on an old object’s values rather than changing the old values directly is known as immutable objects。
A ZoneId
is a full time zone in java.time. Its subclass ZoneOffset
用于没有调整规则的简单 offset-from-UTC 值。
ZoneId zoneIdAmsterdam = ZoneId.of ( "Europe/Amsterdam" );
ZonedDateTime zdtAmsterdam = zdt.withZoneSameInstant ( zoneIdAmsterdam );
toString
当您在 System.out.println
中调用 toString
时,java.time class 会使用 ISO 8601 格式生成 date-time 值的字符串表示形式.
请注意,除了 offset-from-UTC 编号之外,java.time 通过在方括号中附加指定时区的名称来扩展 ISO 8601。例如,[Europe/Amsterdam]
.
System.out.println ( "zdt: " + zdt + " at zoneId z: " + z + " adjusted to zoneIdAmsterdam: " + zoneIdAmsterdam + " is zdtAmsterdam: " + zdtAmsterdam );
zdt: 2015-12-24T17:41:54+01:00 at zoneId z: +01:00 adjusted to zoneIdAmsterdam: Europe/Amsterdam is zdtAmsterdam: 2015-12-24T17:41:54+01:00[Europe/Amsterdam]
Instant
通常在我们的业务逻辑和数据存储中,我们严格按照 UTC 工作,应用时区只是为了向用户展示。为此,传递并存储 Instant
class 的实例。此 class 表示 UTC 时间轴上的一个时刻。
Instant instant = zdt.toInstant();
我用日期反序列化一个 json 字符串:
"created_at": "2015-12-24T17:41:54+01:00",
我为 gsonBuilder 设置了日期格式:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create();
反序列化工作没有崩溃;不幸的是,当我打印结果时,它是不正确的:
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ssZ");
String str = ft.format(response.createdAt);
结果是:
2015-12-24T11:41:54-0500
而不是:
2015-12-24T17:41:54+01:00
您没有设置时区,只是在 date/time 的末尾添加了一个 Z,因此它看起来像 GMT date/time,但这不会改变值。
将时区设置为 GMT,这将是正确的。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
java.time
接受的答案是正确的。但是过时了。 java.text.SimpleDateFormat 和 java.util.Date classes 已被添加到 Java 8 及更高版本的 java.time 框架淘汰。更容易使用和更明智。
ISO 8601
您输入的字符串格式符合ISO 8601标准。当 parsing/generating 字符串表示 date-time 值时,java.time classes 使用 ISO 8601 作为它们的默认格式。
String input = "2015-12-24T17:41:54+01:00";
Offset-From-UTC
该输入字符串包含 +01:00
的 offset-from-UTC,这意味着比 UTC 早一个小时。
ZonedDateTime zdt = ZonedDateTime.parse ( input );
ZoneId z = zdt.getZone ();
偏移量与时区
但是那个偏移量不是时区。时区是一个偏移加上 规则,用于处理异常调整,例如夏令时 (DST)。所以你可能想要分配 a specific time zone you have in mind as being intended by that string. Perhaps you intended Amsterdam time。
我们可以申请一个时区以获得另一个ZonedDateTime
object. This pattern of creating a new object based on an old object’s values rather than changing the old values directly is known as immutable objects。
A ZoneId
is a full time zone in java.time. Its subclass ZoneOffset
用于没有调整规则的简单 offset-from-UTC 值。
ZoneId zoneIdAmsterdam = ZoneId.of ( "Europe/Amsterdam" );
ZonedDateTime zdtAmsterdam = zdt.withZoneSameInstant ( zoneIdAmsterdam );
toString
当您在 System.out.println
中调用 toString
时,java.time class 会使用 ISO 8601 格式生成 date-time 值的字符串表示形式.
请注意,除了 offset-from-UTC 编号之外,java.time 通过在方括号中附加指定时区的名称来扩展 ISO 8601。例如,[Europe/Amsterdam]
.
System.out.println ( "zdt: " + zdt + " at zoneId z: " + z + " adjusted to zoneIdAmsterdam: " + zoneIdAmsterdam + " is zdtAmsterdam: " + zdtAmsterdam );
zdt: 2015-12-24T17:41:54+01:00 at zoneId z: +01:00 adjusted to zoneIdAmsterdam: Europe/Amsterdam is zdtAmsterdam: 2015-12-24T17:41:54+01:00[Europe/Amsterdam]
Instant
通常在我们的业务逻辑和数据存储中,我们严格按照 UTC 工作,应用时区只是为了向用户展示。为此,传递并存储 Instant
class 的实例。此 class 表示 UTC 时间轴上的一个时刻。
Instant instant = zdt.toInstant();