在Postgres中存储时间并在应用程序(Java)端处理

在Postgres中存储时间并在应用程序(Java)端处理,java,postgresql,Java,Postgresql,我听说postgres支持在有时区和无时区的情况下存储日期时间和时间。现在,在JST时区中运行的应用程序必须在数据库端存储时间。现在,无论我读到哪里,建议您始终将存储在UTC中的东西保存在datetime中,因为在应用层接收datetime时,我可以根据我的首选时区对其进行操作。但若我只想把时间存储在数据库端,那个么我应该把它存储为UTC时间吗?如果是,则JST中的凌晨1点将导致前一天UTC下午4点。所以,有人能告诉我,在数据库中存储时间的首选方式是什么吗 正如其中一个答案中所建议的,如果我在本

我听说postgres支持在有时区和无时区的情况下存储日期时间和时间。现在,在JST时区中运行的应用程序必须在数据库端存储时间。现在,无论我读到哪里,建议您始终将存储在UTC中的东西保存在datetime中,因为在应用层接收datetime时,我可以根据我的首选时区对其进行操作。但若我只想把时间存储在数据库端,那个么我应该把它存储为UTC时间吗?如果是,则JST中的凌晨1点将导致前一天UTC下午4点。所以,有人能告诉我,在数据库中存储时间的首选方式是什么吗


正如其中一个答案中所建议的,如果我在本地时间中读取时间,那么如果我将时间存储为12:00 JST,那么在应用程序端读取时,它将是12:00 JST或12:00 UTC

如果时间在多个时区中的可能性极小,那么您需要将它们存储在一个常见的已知时区中,UTC是最好的选择

如果毫无疑问,您完全确定应用程序将只在单个时区中使用,并且应用程序和数据库服务器都将在该时区中运行,那么您可以将时间存储在该本地时区中

由于这种确定性很少见,建议使用UTC

如果必须保留原始时区,则需要一个单独的列来存储时区,以便从数据库加载时可以重新应用它。

tl;博士 显然,您希望存储一天中没有日期和时区的时间

使用Java类
Java.time.LocalTime
和标准SQL类型
time(不带时区)

LocalTime.of( 15 , 30 )
……还有

myPreparedStatement.setObject( … , LocalTime.of( 15 , 30 ) )
细节 请注意,时间仅仅是小时分秒数,仅此而已。A更重要。时区是特定地区人民使用的偏移量的过去、现在和未来变化的历史

我听说postgres支持在有时区和无时区的情况下存储日期时间和时间

实际上,SQL标准定义了:

  • 带有时区的时间戳

    跟踪一个时刻,即时间线上的一个特定点。表示日期、时间以及与UTC或时区的偏移量。常见的实现使用UTC
  • 不带时区的时间戳

    跟踪一天中的日期和时间,但不包含偏移量或区域的上下文。所以这种类型不能代表一个时刻,不是时间线上的一个点。例如,对于“2020年1月23日中午”的值,我们不知道这是指东京的中午、巴黎的中午还是蒙特勒尔的中午——所有这些时刻都非常不同,相隔数小时
现在有一个在JST时区运行的应用程序

JST
不是真正的时区。以
大陆/地区
格式命名。切勿使用3-4个字母的伪时区,如
EST
IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)

如果您所说的
JST
是指在日本的时间,请使用
Asia/Tokyo

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
在数据库端存储时间以了解时隙

我不知道那是什么意思

现在,无论我读到哪里,都建议您始终将东西存储在UTC中

当跟踪实际时刻时,是的,通常最好在0小时分秒的UTC偏移量内进行跟踪。将UTC视为一个真实时间,将其他偏移和分区视为仅仅是变化,将其视为向用户呈现数据的本地化问题。在UTC中执行大部分业务逻辑、数据存储、数据交换、调试和登录。认真地说,把桌上的第二个时钟设为UTC。程序员和系统管理员应该学会在UTC环境下思考和工作,在工作中留下狭隘的时区

它可以在datetime的情况下工作,因为在应用层上接收datetime时,我会根据我的首选时区对其进行操作

是的,如上所述,使用UTC(通常)处理您的逻辑,并将其本地化到用户期望的区域。关键时,与用户确认其所需的时区。并养成在显示日期或时间时始终包含区域/偏移信息的习惯,以避免歧义和混淆

但若我只想将时间存储在数据库端,那个么我也应该将其存储为UTC时间。如果是,则JST中的凌晨1点将导致前一天UTC下午4点。有人能建议我如何在数据库端单独存储时间吗

你的意思是只存储一天中没有日期和时区的时间吗?如果是,请使用:

  • Java中的本地时间
  • 标准SQL中不带时区的时间
SQL标准奇怪地定义了一个带有时区的
时间,但是这毫无意义。想想看。不要惊讶;这不是SQL标准中唯一的反功能。博士后确实提供这种类型,因为遵循标准是博士后的主要目标之一。同样,java中的java.time框架包含一个兼容的
java.time.OffsetTime
类,但您永远不会使用它

Postgres具有出色的日期-时间处理能力,并提供了无时区的
时间数据类型

LocalTime localTime = LocalTime.of( 15 , 30 ) ;
myPreparedStatement.setObject( … , localTime ) ;
检索

LocalTime localTime = myResultSet.getObject( … , LocalTime.class ) ;
您可能希望通过实例化
ZonedDateTime
,将该时间应用于日期和时区,以确定某个时刻

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
LocalDate localDate = LocalDate.of( 2019 , Month.JANUARY , 23 ) ;
ZonedDateTime zdt = ZonedDateTime.of( localDate, localTime, z ) ;
通过UTC的挂钟可以看到同一时刻。同一时刻,时间线上的同一点,但不同的挂钟时间

Instant instant = zdt.toInstant() ;
ZonedDateTime zdtMontréal = instant.atZone( ZoneId.of( "America/Montreal" ) ) ;
如果需要,调整到另一个时区。同样,时间线上的同一时刻、同一点,但墙上的时钟时间不同

Instant instant = zdt.toInstant() ;
ZonedDateTime zdtMontréal = instant.atZone( ZoneId.of( "America/Montreal" ) ) ;
也许你想看看魁北克的时间