java和postgresql中从日期到长的转换是不一样的
Posted
技术标签:
【中文标题】java和postgresql中从日期到长的转换是不一样的【英文标题】:Convert from date to long are not the same in java and postgresql 【发布时间】:2017-11-30 13:26:30 【问题描述】:我在 postgresql 中有一个表,其中有一列 created_date
日期类型。我创建了以毫秒为单位返回日期而不是日期的视图:
select date_part('epoch'::text, timezone('UTC'::text, created_date::timestamp with time zone)), created_date
from table
这将返回以下结果:
date_part created_date
1497384000 2017-06-14
1497384000 2017-06-14
1498420800 2017-06-26
1498420800 2017-06-26
在 Java 中,我做了以下操作:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate date = LocalDate.parse(view.getStartDate(), formatter);
long longDate = date.atStartOfDay(ZoneId.of("UTC")).toEpochSecond();
longDate 结果是1497398400
对应2017-06-14
和1498435200
对应2017-06-26
。
为什么postgresql和Java从日期到长的转换不一样?
PS:数据库的时区是Asia/Baku
。
【问题讨论】:
24 小时? @pnuts 区域偏移通常在距 UTC 的 +/- 14 小时内,因此听起来不太可能。巴库全年为 UTC+4:00。 虽然您认为两个区域偏移可能相隔 24 小时是正确的,但使用中的区域偏移不存在 与 UTC 相差 24 小时。这是因为 UTC 几乎位于所有区域偏移的中间。 @pnuts 没错,@pnuts 【参考方案1】:你打电话给atStartOfDay(ZoneId)
。由于ZoneId
是UTC,它将小时设置为午夜,区域设置为UTC。因此,您的日期变为2017-06-14T00:00:00Z
,等效的纪元秒值为1497398400
。
如果检查数据库返回的值(1497384000
):
System.out.println(Instant.ofEpochSecond(1497384000L));
你得到:
2017-06-13T20:00:00Z
如果您将其转换为您的系统使用的时区 (Asia/Baku
):
System.out.println(Instant.ofEpochSecond(1497384000L).atZone(ZoneId.of("Asia/Baku")));
你得到:
2017-06-14T00:00+04:00[亚洲/巴库]
因此,1497384000
的值相当于 UTC 中的 2017-06-13T20:00:00Z
。数据库返回 2017-06-14
,因为它正在将此 UTC 日期/时间转换为系统的时区 (Asia/Baku
)。
如果您想获得相同的结果,则必须使用数据库使用的相同时区:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate date = LocalDate.parse("2017-06-14", formatter);
// using Asia/Baku timezone instead of UTC
long longDate = date.atStartOfDay(ZoneId.of("Asia/Baku")).toEpochSecond();
System.out.println(longDate);
输出将是:
1497384000
【讨论】:
数据库时区为“亚洲/巴库”以上是关于java和postgresql中从日期到长的转换是不一样的的主要内容,如果未能解决你的问题,请参考以下文章
在 SQL 中从 POSTGRE/SQL 数据库转换 UTC 时间字段
Java中从字符串到sql日期的日期转换给出不同的输出? [复制]
Java中从LocalDateTime到joda DateTime的不正确日期转换