首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >即时对决ZonedDateTime

即时对决ZonedDateTime
EN

Stack Overflow用户
提问于 2018-10-07 16:44:06
回答 1查看 11.2K关注 0票数 18

我只是不太明白在下面的例子中应该使用哪一种:

我们有一个OfferEntity,它有一个成员availableDay,这是提供报价的日期。

现在,这张桌子看起来像这样:

代码语言:javascript
复制
CREATE TABLE IF NOT EXISTS offer (
  created   timestamp with time zone NOT NULL DEFAULT NOW(),
  id        BIGSERIAL PRIMARY KEY,
  available timestamp with time zone
);

PostgreSQL文档我们知道:

对于timestamp with time zone,内部存储的值总是以UTC (通用协调时间,传统上称为格林威治标准时间(格林尼治标准时间))。指定了显式时区的输入值将使用该时区的适当偏移量转换为UTC。如果输入字符串中没有指定时区,则假定它位于由系统的TimeZone参数指示的时区,并使用时区的偏移量将其转换为UTC。

这意味着我在保存任何日期/时间信息时应该很好。

但是这对我的OfferEntity和我在OfferController中定义的其他端点意味着什么?

代码语言:javascript
复制
@Entity
@Table(name = "offer")
public class OfferEntity {    
    @Column(name = "available", nullable = false)
    private ZonedDateTime availableDay;
}

vs

代码语言:javascript
复制
@Entity
@Table(name = "offer")
public class OfferEntity {    
    @Column(name = "available", nullable = false)
    private Instant availableDay;
}

据我所知-这不应该有什么区别。PostgreSQL以UTC的方式存储所有东西,所以我应该可以使用InstantZonedDateTime,对吗?写些-> UTC的东西。再读一遍,->仍然是UTC。

即使是客户也无法分辨出区别:

代码语言:javascript
复制
@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();
}

将返回:

代码语言:javascript
复制
{
  "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",
}

但肯定有一个关键的差别,我显然没有看到。

我能分辨出两个不同之处。看来,Spring在将"2018-10-07T15:30:08.579Z"转换为Instant对象方面没有问题,但是如果我将类型更改为ZonedDateTime,则无法做到这一点。至少从盒子里拿出来。

代码语言:javascript
复制
@RequestMapping("/places/{placeId}/offers", method = RequestMethod.GET)
public List<OfferDto> getOffers(
        @PathVariable(name = "placeId") Long placeId,
        @RequestParam(name = "date") ZonedDateTime date) {
    return this.offerService.getOffers(placeId, date);
}

另一个不同之处在于,如果我使用Instant,我将迫使客户端首先将其所有日期/时间字符串转换为UTC。因此,任何客户都必须首先使用myDate.toUTCString()。只要有时区设置,ZonedDateTime就会采取任何措施,但为什么我们会在意呢?

那么这两种选择中哪一种更好,为什么我会选择一种而另一种?

EN

回答 1

Stack Overflow用户

发布于 2019-10-23 09:17:22

以下链接中的答案比我以往任何时候都能更好地解释它。答案涉及Java中所有不同的日期/时间类,以及它们与sql类型的关系。

Instant和LocalDateTime有什么区别?

一个简短的总结:类Instant和ZonedDateTime (以及OffsetDateTime)代表着相同的东西:瞬间。区别在于ZonedDateTime和OffsetDateTime提供了关于时区或时差的额外上下文和功能,而Instant没有指定时区或偏移量。这可能导致差异,特别是当涉及到夏令时。例如,以以下代码片段为例:

代码语言:javascript
复制
    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);

其结果将是:

代码语言:javascript
复制
    2019-10-27T05:00:00Z
    2019-10-27T04:00:00Z

不同之处在于阿姆斯特丹时区10月27日有一个额外的小时。当我们转换为即时的时区信息丢失,所以添加一天将只增加24小时。

LocalDateTime是一个完全不同的野兽。它表示没有时区信息的日期和时间。它并不代表时间上的某个时刻。它对于写诸如“圣诞节早晨从12月25日00:00:00开始”之类的东西很有用。无论时区如何,这都是正确的,因此ZonedDateTime或Instant是不合适的。

票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52690684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档