Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database PostgreSQL应用程序中的不同时区_Database_Postgresql - Fatal编程技术网

Database PostgreSQL应用程序中的不同时区

Database PostgreSQL应用程序中的不同时区,database,postgresql,Database,Postgresql,我们有一个服务于许多配送中心的系统。配送中心是全国任何地方的物理空间。一个客户可能有多个配送中心。现在我们正在扩展到更多的地方,我们将不得不面对不同时区的问题。同一客户机也可能在不同时区拥有中心 在客户中心使用我们的系统可以创建和保存很多事件(包括日期和时间)。同一客户端中不同时区的理想行为如下: 考虑一个发生在时区A中午的事件。如果时区B中另一个配送中心的主管去检查该事件,他应该看到该事件的日期和时间与最初创建该事件的时区有关(包括DST更改,如果存在)。 这是因为需要知道的是事件是否在事件时

我们有一个服务于许多配送中心的系统。配送中心是全国任何地方的物理空间。一个客户可能有多个配送中心。现在我们正在扩展到更多的地方,我们将不得不面对不同时区的问题。同一客户机也可能在不同时区拥有中心

在客户中心使用我们的系统可以创建和保存很多事件(包括日期和时间)。同一客户端中不同时区的理想行为如下:

考虑一个发生在时区A中午的事件。如果时区B中另一个配送中心的主管去检查该事件,他应该看到该事件的日期和时间与最初创建该事件的时区有关(包括DST更改,如果存在)。 这是因为需要知道的是事件是否在事件时区的中午创建。对于主管来说,事件创建时间是否为其时区的下午2点并不重要

我们使用PostgreSQL作为数据库,我发现存在两种不同的类型来保存时间戳<代码>时间戳和
时间戳
。我们所有的数据库只使用类型
时间戳

另一种可能(或不可能)发生的情况是配送中心在地理位置上发生变化。这可能会影响其时区的变化

我做了一些研究,发现更“正确”的方法(至少看起来是这样)是在
配送中心
表中保存每个中心的时区。将数据库中的所有类型从
TIMESTAMP
更改为TIMESTAMP,在每次插入保存时间戳的事件时,我们应该使用创建事件的中心的时区来保存事件的时区偏移量(
TIMESTAMP tz
仅保存时区偏移量,而不是时区本身)

我不完全相信这是处理不同时区的正确(或最佳)方法。因为我从来没有实现过这样的事情,所以我不能说

如果我必须遵循这种方法,我必须将数据库中的所有列类型从
TIMESTAMP
更改为
TIMESTAMP
。在中以某种方式依赖于该列的所有视图也必须重新创建,因为我们将更改列类型。我还必须更改所有处理该列的查询,以使用时区
应用中心时区

数据库现在已经设置了
美国/圣保罗
时区,我担心在更改
时间戳
的列类型时会出错。此更改是否可能破坏数据一致性?我应该首先更改列类型还是更改UTC的数据库时区

我描述的解决方案是实现这一点的最佳方法吗

该方法是否也正确处理DST变更


额外信息:我们的服务器使用java(jersey)。

这些问题在Stack Overflow和姐妹站点上已经讨论过多次。请在下次发帖前彻底搜索。所以,这里只是一个回顾

首先,你必须理解和之间的区别。偏移量仅是距离的小时数、分钟数和秒数。时区是特定地区人民使用的偏移量的过去、现在和未来变化的历史。因此,使用时区总是比仅仅使用偏移更可取

存在两种不同的类型来保存时间戳。时间戳和时间戳

不完全是这样。SQL标准定义的实际类型是带时区的时间戳和不带时区的时间戳。其他名称是Postgres特有的同义词。为了清晰起见,我建议使用标准名称。日期-时间处理非常混乱,而且最后没有读取/记住
z
的模糊性

SQL规范很少涉及日期时间处理的主题。因此,数据库实现之间的行为差异很大

博士后的工作方式非常简单

  • 对于带有时区的时间戳类型为
    的列,任何带有UTC或时区偏移量的输入都会自动调整为。调整后,原始值的偏移/分区信息将被丢弃。“带时区”实际上是指“关于传入数据的时区”,而不是“与时区一起存储”如果必须知道原始偏移量/区域,则必须将其存储在单独的列中。我建议使用ISO 8601标准偏移格式或。如果输入缺少区域/偏移的任何指示器,则应用会话的当前默认时区,然后对UTC进行调整——正如我模糊地记得的那样;您不应该传递缺少区域/偏移的输入
    
  • 对于不带时区的
    时间戳列
    ,将忽略任何带输入的区域/偏移信息(如果有)。同样,检索时,此值没有分区/偏移。这种类型没有分区/偏移的概念。当您打算在时间线上存储一个时刻、一个点时,请勿使用此类型。这种类型是为了模糊地了解26-27小时范围内的潜在时刻,例如“2018年12月25日午夜后开始圣诞节”。这样的句子没有真正的意义,除非您附加“在日本”、“在印度”或“在法国”(从而在另一种类型中创建一个值,
    带时区的时间戳
    )。这种类型也适用于未来几周以上的任命,届时政客可能会改变其地区的补偿(他们经常这样做,而且几乎没有预先警告)
注意:令人困惑的是,某些工具或驱动程序可能会将会话的当前默认时区应用于eit值
ZoneId zoneSaoPaulo = ZoneId.of( "America/Sao_Paulo" ) ;
ZoneId zoneLisbon = ZoneId.of( "Europe/Lisbon" ) ;
ZoneId zoneKolkata = ZoneId.of( "Asia/Kolkata" ) ;
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
public enum DistributionCenter {
    // List the constants to be constructed automatically when this class loads.
    SAOPAULO( ZoneId.of( "America/Sao_Paulo" ) ) ,
    LISBON( ZoneId.of( "Europe/Lisbon" ) ) ,
    KOLKATA( ZoneId.of( "Asia/Kolkata" ) ) 

    final public ZoneId zoneId ;  // Make public, or add a getter method to access private member.

    // Add constructor taking the passed `ZoneId` and storing in the variable.
}
DistributionCenter dc = … ;
ZonedDateTime zdt = ldt.atZone( dc.zoneId ) ;
Instant instant = zdt.toInstant() ;
myPreparedStatement.setObject( … , instant ) ;