节省和检索从客户端到数据库的时间



在我的一个Web应用程序中,我必须安排一个事件。 我的服务器、客户端和数据库位于不同的时区。 客户端将安排一个事件,服务器必须执行该事件。

我该怎么做?

目前从客户端,我发送自纪元以来的事件时间(以毫秒为单位):(使用 javascript 中的日期的 getTime() 方法)

在服务器中,我使用 Java 将其转换为日期对象,并将其存储为数据库中的日期类型值。

在数据库中,存储的值比我从客户端给出的日期晚一天。 为什么会这样?如何在服务器时间中存储它?

你的问题是许多其他问题的副本。所以我会简短一点。

有两种方法可以表示三种日期时间值:

  • 如果实际时刻已过去(付款、收到的发票、送达的法庭文件、货物到达等),或者将来您知道您希望在时间线上有一个特定的时刻,无论政治家是否重新定义时区,例如更改夏令时 (DST),则以 UTC 格式存储和交换日期时间值。 对于 Java,请使用Instant类。在 SQL 中使用TIMESTAMP WITH TIME ZONE.
  • 存储和交换日期时间值,不带区域/偏移量,以便将未来事件安排得足够远,以至于政治家可能会改变时区规则(明年的牙科预约,两个月的面试,派对公告等)。世界各地的政治家都表现出了摆弄我们的时钟的嗜好,通常几乎没有警告,有时只提前几周通知。对于 Java,请使用LocalDateTime类。在 SQL 中,使用TIMESTAMP WITHOUT TIME ZONE。要显示计划,请使用ZonedDateTime类通过Instant::atZone方法在 Java 中生成瞬态数据。
  • 存储和交换日期时间值,不带区域/偏移量,用于非特定事件,例如圣诞节开始或说"我们在德里、杜塞尔多夫和底特律的所有工厂都将在今年 10 月 30 日中午关闭半天",我们的意思是每个当地时间的中午,而不是同时。对于 Java,请使用LocalDateTime类。在 SQL 中,使用TIMESTAMP WITHOUT TIME ZONE

作为程序员和系统管理员,学习在UTC和24小时内思考。在工作中忘记你自己的狭隘时区。在办公室中将第二个时钟设置为 UTC。

您如何知道用户的预期/期望时区?最终唯一确定的方法就是问她/他。

序列化为文本时,请使用标准 ISO 8601 格式。

避免糟糕的旧日期时间类,例如java.util.Datejava.sql.Date等。这些现在已成为遗产,被优秀的行业领先的java.time类所取代。

Instant表示时间轴上的时刻(以 UTC 格式表示)。

Instant instant = Instant.ofEpochMilli( millis ) ;

为了向用户演示,请将 UTC 调整为他们期望/想要的时区。将此视为国际化,其中存储对键的引用,然后使用检索到的键查找本地化的文本值进行演示。

切勿使用 3-4 个字符的伪时区。真正的时区有一个continent/region名称,例如Asia/KolkataPacific/Auckland

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

请注意,数据库在处理日期时间方面差异很大。SQL标准几乎没有涉及这个主题。研究文档并进行实验,以确保您了解它的行为。JDBC 驱动程序也是如此。提示:Postgres 对日期时间类型和函数有一些最好的支持。

在 JDBC 4.2 及更高版本中,通过 java.time 对象与数据库交换数据,方法是调用:

  • PreparedStatement::setObject
  • ResultSet::getObject

示例代码

myPStmt.setObject.( … , myInstant ) ;

。和。。。

Instant instant = myResultSet.getObject( … , Instant.class ) ;

当你存储时间时,最好的办法是将其存储在纪元时间(如果你愿意,也可以使用 unix 时间)的任何位置,并在前端反序列化它。这意味着您可以确信自己已经保留了正确的时间,然后可以在前端转换它。在不知道细节的情况下,我怀疑您在 Java 中创建的日期对象导致了偏移,然后您在数据库中存储了错误的日期值。

相关内容

  • 没有找到相关文章

最新更新