dis*_*ame 6 postgresql utc timestamp-with-timezone zoneddatetime java.time.instant
我只是不太了解在以下示例中应该使用这两个中的哪一个:
我们有OfferEntity一个成员availableDay,该成员是要约可用的日期。
现在,该表将如下所示:
CREATE TABLE IF NOT EXISTS offer (
created timestamp with time zone NOT NULL DEFAULT NOW(),
id BIGSERIAL PRIMARY KEY,
available timestamp with time zone
);
Run Code Online (Sandbox Code Playgroud)
从PostgreSQL文档中我们知道:
对于
timestamp with time zone,内部存储的值始终以UTC(通用协调时间,通常称为格林威治标准时间,GMT)表示。使用该时区的适当偏移量,将指定了明确时区的输入值转换为UTC。如果在输入字符串中未指定时区,则假定该时区位于系统TimeZone参数指示的时区中,并使用时区的偏移量将其转换为UTC。
这意味着在保留任何日期/时间信息时我应该没问题。
但这对我OfferEntity和我定义的REST端点意味着什么OfferController?
@Entity
@Table(name = "offer")
public class OfferEntity {
@Column(name = "available", nullable = false)
private ZonedDateTime availableDay;
}
Run Code Online (Sandbox Code Playgroud)
与
@Entity
@Table(name = "offer")
public class OfferEntity {
@Column(name = "available", nullable = false)
private Instant availableDay;
}
Run Code Online (Sandbox Code Playgroud)
据我了解-这不会有所作为。PostgreSQL无论如何都将所有内容存储为UTC,所以我应该可以接受Instant还是ZonedDateTime正确?写点东西-> UTC。再次阅读->仍然是UTC。
甚至客户也无法分辨出区别:
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public Object hello() {
class Hello {
public Instant instant = Instant.now();
public ZonedDateTime zonedDateTime = ZonedDateTime.now();
public ZonedDateTime viennaTime = ZonedDateTime.now(ZoneId.of("GMT+2"));
public LocalDateTime localDateTime = LocalDateTime.now();
}
return new Hello();
}
Run Code Online (Sandbox Code Playgroud)
将返回:
{
"instant": "2018-10-07T15:30:08.579Z",
"zonedDateTime": "2018-10-07T15:30:08.579Z",
"viennaTime": "2018-10-07T17:30:08.579+02:00",
"localDateTime": "2018-10-07T15:30:08.579",
}
Run Code Online (Sandbox Code Playgroud)
但是必须存在一个关键的区别,我显然没有看到。
我有两个区别。看来Spring转换"2018-10-07T15:30:08.579Z"为Instant对象没有问题,但是如果我将类型更改为,则这样做失败ZonedDateTime。至少开箱即用。
{
"instant": "2018-10-07T15:30:08.579Z",
"zonedDateTime": "2018-10-07T15:30:08.579Z",
"viennaTime": "2018-10-07T17:30:08.579+02:00",
"localDateTime": "2018-10-07T15:30:08.579",
}
Run Code Online (Sandbox Code Playgroud)
另一个区别是这样一个事实,即如果我使用的话,我将Instant迫使我的客户首先将其所有日期/时间字符串转换为UTC。因此,任何客户都必须myDate.toUTCString()首先。ZonedDateTime只要设置了时区,它将花费任何时间,但是我们为什么要关心呢?
那么,哪两个是更好的选择,为什么我要选择一个呢?
Joo*_*gts 11
以下链接中的答案比我以往任何时候都更好地解释了它。答案涉及 Java 中所有不同的日期/时间类,以及它们与 sql 类型的关系。
Instant 和 LocalDateTime 有什么区别?
简短摘要:类 Instant 和 ZonedDateTime(以及 OffsetDateTime)代表相同的事物:时间。不同之处在于 ZonedDateTime 和 OffsetDateTime 提供有关时区或时间偏移的额外上下文和功能,而 Instant 没有指定时区或偏移。这可能会导致差异,尤其是在涉及夏令时时。例如,采用以下代码片段:
ZonedDateTime z1 = zonedDateTime.of(LocalDateTime.of(2019,10,26,6,0,0),ZoneId.of("Europe/Amsterdam"));
Instant i1 = z1.plus(1,ChronoUnit.DAYS).toInstant();
Instant i2 = z1.toInstant().plus(1,ChronoUnit.DAYS);
System.out.println(i1);
System.out.println(i2);
Run Code Online (Sandbox Code Playgroud)
结果将是这样的:
2019-10-27T05:00:00Z
2019-10-27T04:00:00Z
Run Code Online (Sandbox Code Playgroud)
差异源于这样一个事实,即在阿姆斯特丹时区,10 月 27 日有一个额外的小时。当我们转换为 Instant 时,时区信息会丢失,因此添加一天只会添加 24 小时。
LocalDateTime 是一个不同的野兽。它表示没有时区信息的日期和时间。它并没有在时间代表了一会儿。这对于编写诸如“圣诞节早上从 12 月 25 日 00:00:00 开始”之类的内容很有用。无论时区如何,这都是正确的,因此 ZonedDateTime 或 Instant 不合适。