DolphinDB 中的时区处理
本教程介绍了在DolphinDB中存储与导入时间数据时需要注意的时区问题。
DolphinDB 中的时区处理
1. 时间的存储方式
1.1 场景一
1.2 场景二
2. Java API 的时间处理
2.1 最佳实践
2.2 慎用 Date 类
3. MySQL 的时间处理
3.1 MySQL常用时间类型和时区的关系
3.2 MySQL 时间类型导入 DolphinDB
4. CSV 文件的时间处理
5. 总结
附录
DolphinDB 支持以下九种表示时间的数据类型:
Data Type Example
MONTH 2012.06M
DATE 2012.06.13
MINUTE 13:30m
SECOND 13:30:10
TIME 13:30:10.008
NANOTIME 13:30:10.008000001
DATETIME 2012.06.13 13:30:10 or 2012.06.13T13:30:10
TIMESTAMP 2012.06.13 13:30:10.008 or 2012.06.13T13:30:10.008
NANOTIMESTAMP 2012.06.13 13:30:10.008000001 or 2012.06.13T13:30:10.008000001
1. 时间的存储方式
有的数据库在存储时间数据时,会将其转换为全球统一的 Unix 时间戳,并单独存储时区信息(即 UTC 偏移量)。 而 DolphinDB 将时间转换为本地时间戳直接存储,不会单独存储时区信息。Unix时间戳和本地时间戳的转换关系为:Unix 时间戳 + UTC 偏移量 (秒) = 本地时间戳
对于不需要存储时区信息的业务场景(见2.1 章节),用户将时间数据直接存入 DolphinDB,查询时 DolphinDB 按存入时间输出,不会增加时区转换;对于需要存储时区信息的业务场景(见2.2章节),用户在写入数据库时可以通过内置时区转换函数 gmtime 将本地时间转换成 UTC 时间进行存储,之后查询时通过内置函数 localtime(或 convertTZ)将数据转换回本地时间(或指定的时区)。
下面展示两种业务场景,通过比较是否存储时区信息两种方案,详细展示各场景下的最佳实践。
1.1 场景一
场景信息概述
存储纽约某一交易所地交易数据,其中一列是交易时间,例如2022.02.20 09:35:03。
数据库服务部署在北京(东八区)。
业务相关的端上服务(web、APP 等)一部分部署在北京(东八区),另一部分部署在旧金山(西八区)。
业务需求概述
要求无论是在北京(东八区)还是旧金山(西八区)的用户,访问端上服务时,查询时显示的数据时间显示和纽约交易所本地交易时间(西五区)一致,本例中以即显示2022.02.20 09:35:03为例进行说明。
1.1.1 方案一:存储时间信息
对于存储时区信息的数据库来说,此业务场景中将执行下列步骤:
将交易时间转化为本地时间戳。在本例中,2022.02.20 09:35:03对应的本地时间戳(西五区)是1645349703。
将本地时间戳减去时区偏移量得到unix时间戳 (1645367703),存入数据库。
用户通过部署在北京(东八区)或旧金山(西八区)的业务端访问数据库时,数据库将按照业务端服务器所在时区进行解析。因此,必须另行指定客户端按西五区时间显示时间数据,才能正确显示2022.02.20 09:35:03。
从上述存储的时间转换过程来看,数据库存储时间时,如果带有时区的概念,需要在查询时指定显示的时区信息,引入一些时区转换的操作,给业务上带来一些不便。
1.1.2 方案二:存储本地时间(即直接存储最终想要显示的时间)
存储转换过程:
step 1 : 直接存储交易时间2022.02.20 09:35:03对应的时间戳 1645349703 入库即可。
step 2 : 用户在端上请求查询接口时,直接显示时间戳 1645349703 对应的时间2022.02.20 09:35:03。
分析可知,场景一优先选择方案二:存储本地时间。在存储数据时,将交易时间2022.02.20 09:35:03 的纽约本地时间直接存储入库,不用考虑时区的问题。在读取数据时,省去了计算 Unix 时间戳以及各种服务跨时区设置不同偏移量的问题,可以简单明了地描述时间信息。
1.2 场景二
在需要存储时区信息的场景下,DolphinDB 也可以通过一些内置函数实现存储时区信息。
场景信息概述
某中国买家通过电商平台,与日本卖家达成了一笔线上交易。交易时间为北京时间2022.05.20 11:30:05(东八区),东京时间2022.05.20 12:30:05(东九区)。
该电商公司在中国和日本都部署了数据中心,分别用于存储当前国家的交易数据。
业务需求概述
用户浏览订单时,平台显示的交易时间必须与用户所在时区一致,即中国买家看到北京时间,日本卖家看到东京时间。
1.2.1 方案一:存储时区信息
step 1 : 北京买家的交易时间为2022.05.20 11:30:05,可以使用 DolphinDB 的内置函数 gmtime,将本地时间转换成零时区时间,并配合 long 函数得到Unix 时间戳,同理可得卖方东京时间的 Unix 时间戳。以数据库服务部署在东八区的中国为例,具体代码如下:
$ gmtime(2022.05.20 11:30:05)
2022.05.20 03:30:05
$ long(gmtime(2022.05.20 11:30:05))
1653017405
由于该笔交易数据被转换成了 UTC 时间,其对应的 Unix 时间戳1653017405对中国和日本用户来说是相同的。
step 2:用户查看订单时,客户端从数据库中取出 Unix 时间戳,并根据服务器所在时区进行转换显示。此例中 Unix 时间戳为1653017405,中国用户看到的显示时间应为2022.05.20 11:30:05,日本用户为2022.05.20 12:30:05。
在 DolphinDB 中,可通过内置函数 localtime 将零时区时间转换为本地时间。以东八区为例,示例代码如下:
$ localtime(2022.05.20 03:30:05)
2022.05.20 11:30:05
1.2.2 方案二:存储本地时间
在上述场景中采用存储本地时间的方案,会存在以下几个问题:
以哪个时区的本地时间为准?
即便规定好之后,我们需要明确既定的本地时间和其他时区的偏移关系。 计算“本地时间”与其他时区的偏移关系。
通过以上两个问题的思考,不难发现,在场景二中应该采用直接存储数据的 Unix 时间戳,并配合服务器的默认时区进行解析的方案。在该场景中,如果采用存储本地时间的方案,还要处理复杂的时差关系和夏令时等潜在问题。
参考
https://gitee.com/dolphindb/Tutorials_CN/blob/master/timezone.md#2-java-api-%E7%9A%84%E6%97%B6%E9%97%B4%E5%A4%84%E7%90%86