我们有一个服务于许多分发中心的系统。配送中心是该国任何地方的物理空间。一个客户可能有多个配送中心。现在我们正在扩展到更多的地方,我们将不得不面对不同时区的问题。同一个客户也可能拥有不同时区的中心。
可以使用我们在客户中心的系统创建和保存许多事件(包括日期和小时)。同一客户端中不同时区的理想行为如下:
考虑在时区A,中午发生的事件。如果时区B中另一个配送中心的主管检查此事件,他应该看到该事件的日期和时间与最初创建事件的时区有关(包括DST更改,如果存在)。 这是因为重要的是,事件是在事件时区中午创建的。对于主管而言,无论事件何时创建,都是在他的时区中的下午2点。
我们使用PostgreSQL作为我们的数据库,我发现存在两种不同的类型来保存时间戳。 TIMESTAMP
和TIMESTAMPTZ
。我们所有的数据库都只使用TIMESTAMP
类型。
可能(或不会)发生的另一种情况是配送中心在地理位置上发生变化的情况。这可能会影响其时区的变化。
我做了一些研究,发现更“正确”的方法(至少看起来似乎)是保存DISTRIBUTION_CENTER
表中每个中心的时区。在我们的数据库中将所有类型从TIMESTAMP
更改为TIMESTAMPTZ,并在保存时间戳的事件的每个插入中,我们应该使用创建事件的中心的时区来保存事件时区的偏移量( TIMESTAMPTZ
只保存时区的偏移量,而不是时区本身的偏移量。
我并不完全相信这是处理不同时区的正确(或最佳)方法。因为我从来没有这样做过,所以我不能说。
如果我必须遵循这种方法,我将不得不在数据库中将所有列类型从TIMESTAMP
更改为TIMESTAMPTZ
。还必须重新创建以某种方式依赖于该列的所有视图,因为我们将更改列类型。我还必须更改处理该列的所有查询,以便使用AT TIMEZONE
应用中心时区。
数据库现在已经设置了America/Sao_Paulo
时区,并且在更改TIMESTAMPTZ
的列类型时,我的担心最终导致出错。此更改是否可能会破坏数据一致性?我应该首先更改列类型还是更改UTC
的数据库时区?
我描述的解决方案是最好的方法吗?
这种方法是否也能正确处理DST更改?
额外信息:我们的服务器使用java(jersey)。
答案 0 :(得分:0)
阅读Basil的理解这些概念的令人印象深刻的答案。
你一定要切换到timestamp with time zone
,这实际上是绝对时间戳(略微违反了SQL标准的意图)。
您想要改变的一件事是,如果记录它的中心的时区发生变化,事件的时区应该改变。如果没有,您将需要保留中心的时区历史记录,或者(更好地)在创建每个事件时存储时区。