数据类型“带时区的时间戳”中的时区存储
Posted
技术标签:
【中文标题】数据类型“带时区的时间戳”中的时区存储【英文标题】:Time zone storage in data type "timestamp with time zone" 【发布时间】:2015-05-06 12:31:29 【问题描述】:在 PostgreSQL 中,数据类型 timestamp
和 timestamp with timezone
都使用 8 个字节。
我的问题是:
-
时间戳中使用什么格式存储日期和时间?
timestamp with timezone
中的时区信息是如何存储的
类型,后面读取类型时如何解析?
【问题讨论】:
timestamp.c 【参考方案1】:这只是源于有点误导的类型名称的误解。时区本身根本不存储。它只是用作计算实际存储的 UTC 时间戳(输入)的偏移量。或者作为根据current 或given 时区显示时间戳的装饰器(输出)。这一切都符合 SQL 标准。
只存储时间点,没有区域信息。这就是为什么 64 位信息就足够了。时间戳根据会话当前的时区设置显示给客户端。
详情:
Ignoring time zones altogether in Rails and PostgreSQL另外,既然 Jon 提到了,time with time zone
是在 SQL 标准中定义的,因此在 Postgres 中实现,but its use is discouraged:
time with time zone
是SQL标准定义的,但是定义 表现出导致有用性受到质疑的特性。
这是一种固有的模棱两可的类型,无法正确处理DST。
【讨论】:
哎呀,这是可怕的误导。感谢您纠正我的误解。 @ErwinBrandstetter 新问题在这里:***.com/questions/28877366/…【参考方案2】:看着documentation:
时间戳存储为整数或(不推荐使用的)浮点数 我不相信timestamp with timezone
可以在 8 个字节内正确编码,如果它实际上存储了一个时区。只是时间戳需要 64 位,因为 log2(298989 * 365 * 24 * 60 * 60 * 1000000) 大于 63。注意 time with time zone
需要 12 个字节,具有相同的精度,但范围为一天。
请参阅 Erwin 的回答以解释它实际上是如何设法存储在 8 个字节中的——它应该被称为“没有时区的时间戳,但存储在 UTC 中并转换为本地时区以进行显示”。艾克。
【讨论】:
嗨,pg 9.3 doc chp 8.5有一个表,它显示timestamp with timezone
只使用8字节,因为它的范围从4713 BC
到294276 AD
,所以它不需要8个字节来存储日期和时间,因此有剩余的时区信息位,但仍然想知道时区是如何存储和解析的。
@Eric:我知道它声称它只需要 8 个字节,但是您如何期望它在不超过 8 个字节的情况下覆盖到微秒精度的年份范围,而忽略时区?这就是我回答中计算的重点 - 表明该范围/精度组合需要 8 个字节。
我认为诀窍在于值的范围,有限的范围减少了存储值所需的位,同时仍保持精度,我猜这是一种数学问题,如您所见time with timezone
需要 12 个字节,因为它的范围更广。但这不是我关心的 :) 我希望了解时区存储和解析部分。
@EricWang:“有限范围”是什么意思? 4713BC 到 294276AD 是 298989 年。这可能比time
的范围更广,time
是一天 内的时间,但精度如何?在我的世界里,298989 年的范围比 1 天要宽 :) 如果您能解释 为什么 您需要知道精确的存储格式,这也会有所帮助。这只是好奇吗?您永远不需要自己处理原始存储格式。
这里房间里的大象是:时区根本没有存储。以上是关于数据类型“带时区的时间戳”中的时区存储的主要内容,如果未能解决你的问题,请参考以下文章