PostgreSQL插入文本时间戳时如何指定格式与对应时区?
说明:有一些类似的问题讨论过相关话题,但我认为它们的表述不够清晰。因此我提出本问题,附上明确的解释和示例,希望能帮助更多PostgreSQL新手,并获得最佳的解决方案。
我有一个CSV文件,其中包含一个文本字段,该字段代表特定时区内的时间戳,但未包含时区信息——仅需明确这些时间戳属于某一特定时区,且该时区与PostgreSQL所在系统的**系统时区(system TZ)**不同。
示例
假设我的系统时区为+02:00,CSV中的时间戳属于GMT(或+00:00)时区。
该时间戳文本的格式为:DD.MM.YYYY HH:mm:ss.uuu,其中uuu代表毫秒(即3位小数精度)。
需求
我需要将CSV中的所有行导入或INSERT到PostgreSQL表中,同时需要:
- 告知PostgreSQL将该文本解析为
DD.MM.YYYY HH:mm:ss.uuu格式; - 告知PostgreSQL这些时间戳属于GMT时区,但不要将其转换为系统时区。
即表中需存储从CSV文本读取的GMT时间戳原样。
结果对比
错误结果示例:
插入后时间被自动转换为系统时区,导致存储的时间比原GMT时间早2小时(与系统时区偏移一致)
正确结果示例:
插入后时间保持GMT时区的原始值,未被转换为系统时区,存储的时间与CSV文本中的时间完全一致(带GMT时区标识)
问题本质
PostgreSQL文档中有大量关于时间戳及时区的内容,但大多是关于查询时如何格式化显示时间戳。
我的问题本质不同:是如何告知PostgreSQL在INSERT时解析文本格式的时间戳,并将其转换为对应时区的正确时间戳,而非如何格式化显示已存储的时间戳。
具体问题
- 在INSERT语句中,如何告知PostgreSQL待插入文本的源时间戳格式?
- 时区需在行级(添加时区列或为时间戳文本追加时区信息)、表级(能否将时区设为表属性)还是库级设置?正确做法是什么?
补充:代码示例
我使用过以下可正常运行的语法:
INSERT INTO myTable (datetime,sys_id,cputil,memfree,sessnum) VALUES ('2019/05/03 09:41:14 +00:00',100,0.55,0.59,63) RETURNING *;
还有以下语法也可被识别并正常运行(甚至支持夏令时):
INSERT INTO myTable (datetime,sys_id,cputil,memfree,sessnum) VALUES ('23.12.2020 13:51:35 +00:00',100,0.76,0.22,71) RETURNING *;
但我主要担心日期格式的歧义性,不想依赖PostgreSQL自动解析正确。正如所有接触过日期处理的人所知,每月前12天的日期和月份可能被误读!我更希望强制指定正确的解析格式,避免因日期月份互换、未使用24小时制导致小时偏差等问题插入错误数据。
我需要确定性的时间戳解析。
内容的提问来源于stack exchange,提问作者skeetastax

