SQLite 对时间的支持

大多数的关系型数据库都会有时间或者日期类型。但是 SQLite 里面是没有的。虽然SQLite 没有专门的时间类型,但是它提供了一些时间和日期相关的转换函数。利用这些函数,我们也可以很方便的处理时间问题。

首先我们来说说 SQLite 为什么不直接提供时间类型。因为时间类型是个非常复杂的,要考虑的因素非常多。时间是个物理量,对于物理量来说就有分辨率和范围这两个概念。对于一个会议室预约管理系统来说,精确到分钟就够了,可是对于一个精密的物理实验,有可能我们要处理纳秒甚至皮秒量级的数据。范围跨度也是巨大的,我们可能只要记录几年之内的事件,但是对于天文学来说,可能观察到的是几亿年前发生的事件。我们很难用一个简单的数据结构兼顾如此大的时间跨度和如此小的时间分辨率。而且我们还没有考虑时区问题的,对于有些国家,还有夏令时问题。由于地球公转和自传的周期并不是严格的倍数关系,还要每隔几年来个闰秒。这些问题如果都要考虑进去,这个时间系统会非常的复杂,而且低效。所以SQlite 干脆就取消了时间类型,由用户自己决定用什么样的数据形式表示时间。

常用的时间表示方法

可以用来表示时间日期的方法有很多,各种方法有不同的范围和分辨率。下面介绍几种 SQLite 中常用的。

儒略日(Julian Day)

以下内容引自百度百科:

儒略日数(Julian Day Number,JDN)的计算是从格林威治标准时间的中午开始,包含一个整天的时间,起点的时间(0日)回溯至儒略历的公元前4713年1月1日中午12点(在格里历是公元前4714年11月24日),这个日期是三种多年周期的共同起点,且是历史上最接近现代的一个起点。例如,2000年1月1日的UTC 12:00是儒略日2,451,545。
儒略日期(Julian date,JD)是以格林威治标准时中午12:00的儒略日加上那一天的瞬时时间的分数。儒略日期是儒略日添加小数部分所表示的儒略日数。例如,2013年1月1日00:30:00(UT)是儒略日期2,456,293.520833。

通过上面的介绍可以知道,儒略日采用一个整数表示日期,小数部分表示当天的时间。因此我们可以用一个浮点数来存储时间。如果用 double 型(64-bit)来存储时间,时间分辨率优于1微秒。

如何在 SQLite 中使用Julian Day 呢。SQLite 给了几个函数,下面有几个例子:

SELECT julianday('now');
SELECT julianday('2013-01-01 00:30:00');

在我电脑上运行了一下,结果是:2459875.08420683 和 2456293.52083333。将这个结果作为一个浮点数存起来就行了。需要注意的是这里的时间都是 UTC 时间。

如果要取得当前时区的时间,要这样写:

SELECT julianday('2013-01-01 00:30:00', 'utc');
SELECT julianday('2013-01-01 00:30:00', 'localtime');

输出结果是:2456293.1875, 2456293.85416667

我们将这三个值比较一下:
2456293.52083333
2456293.1875
2456293.85416667

第一个值介于后两个中间,后两个分别与第一个结果的差是:0.33333334 也就是 1/3 天,我们知道中国在东 8 区。所以和 UTC 时间差 8 个小时,也是 1/3 天。东 8 区比 UTC 时间是早 8 个小时的,所以我们应该用 ‘utc’。这时把时间字符串当作时东 8 区时间,减 8 个小时转换为 UTC 时间后在计算成 Julian Day 时间。‘localtime’ 是把计算出的时间再加了 8 个小时。

所以,再强调一下,正确的写法是这样的;

SELECT julianday('2013-01-01 00:30:00', 'utc');

注意一定不要用 ‘localtime’。

上面的例子还可以用 strftime 函数来实现:

SELECT strftime('%J','2013-01-01 00:30:00');
SELECT strftime('%J','2013-01-01 00:30:00', 'utc');

下面是反向操作,将 Julian Day 转换回时间字符串:

SELECT datetime(2456293.52083333);
SELECT date(2456293.52083333);
SELECT time(2456293.52083333);SELECT datetime(2456293.1875, 'localtime');
SELECT date(2456293.1875, 'localtime');
SELECT time(2456293.1875, 'localtime');

这里需要特别强调:

  • 在时间字符串向浮点数转换时要用 ‘utc’,表示我的字符串时当前时区的,需要先转换为 UTC 时间。
  • 浮点数向时间字符串转换时要用 ‘localtime’, 表示我们算出的时间字符串需要转换为当前时区的时间。

这两点对于下面的 Unix Timestamp 也适用。

Unix Timestamp

以下是百度百科的介绍:

Unix时间戳(Unix timestamp),或称Unix时间(Unix time)、POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。Unix时间戳不仅被使用在Unix系统、类Unix系统中,也在许多其他操作系统中被广泛采用。

Unix Timestamp 是以一个整数来存储时间的。时间分辨率是 1s。我们可以用 32 位的整数或者 64 位的整数来存储。Unix Timestamp 在 UXIX 系统中使用很方便,但是在 WINDOWS 下就不那么方便了。不过各种编程语言基本都提供了一些相应的转换函数来处理这种类型的时间。

下面的例子将时间字符串转换为 UNIX 时间戳:

SELECT strftime('%s','2004-08-19 18:51:06');
SELECT strftime('%s','2004-08-19 18:51:06', 'utc');

得到的结果是:1092941466 和 1092912666。 这两个时间的差是 28800。正好对应 8 个小时的秒数。

下面的例子将 UNIX 时间戳转换为时间字符串。

SELECT datetime(1092941466, 'unixepoch');
SELECT date(1092941466, 'unixepoch');
SELECT time(1092941466, 'unixepoch');SELECT datetime(1092912666, 'unixepoch', 'localtime');
SELECT date(1092912666, 'unixepoch', 'localtime');
SELECT time(1092912666, 'unixepoch', 'localtime');

字符串

用一个字符串来存储时间也是一种非常常见的方式。通常我们采用 ISO 8601 规定的格式。日期采用 “YYYY-MM-DD” 格式,时间采用 “HH:MM:SS”。如果既要日期也要时间就写成 “YYYY-MM-DD HH:MM:SS”。 这个格式不是必须的,经常我们会看到有人把日期写为 “YYYY/MM/DD”。写成什么样其实都可以,只要用到的地方保持一致就好。
字符串方式的优点显而易见,容易阅读,方便调试,如果采用 ISO 8601 的格式,时间的比较就是标准的字符串比较。
字符串方式的缺点也很明显:

  1. 占用空间大,“YYYY-MM-DD HH:MM:SS” 要占用 20 个字节。
  2. 时间运算比较麻烦,通常需要转换为儒略日或者其他数值类型,计算完再转换回来。
  3. 要保证所有人输入时间时采用完全一致的格式。SQLite 以字符串格式存储日期时间时不会做任何校验。格式不对不会有任何的报错或者提示。因此应用程序需要自己保证格式正确。

SQLite 给出了一些函数,用来格式化时间字符串。下面给几个例子,首先是返回当前的时间和日期。

SELECT date('now');
SELECT time('now');
SELECT datetime('now');

这三个时间都是 UTC 时间。如果要显示当前时区的时间应该用:

SELECT date('now', 'localtime');
SELECT time('now', 'localtime');
SELECT datetime('now', 'localtime');

还可以是用 strftime 函数。下面是几个简单的例子:

SELECT strftime('%Y/%m/%d %H/%M/%f' , '2013-01-01 00:30:00');
SELECT strftime('%Y/%m/%d %H/%M/%f' , 2456293.52083333);

输出的结果是:2013/01/01 00/30/00.000。SQLite 默认这个时间都是 UTC 时间的。
如果要转换为当前时区时间,则需要写为:

SELECT strftime('%Y/%m/%d %H/%M/%f' , '2013-01-01 00:30:00', 'localtime');
SELECT strftime('%Y/%m/%d %H/%M/%f' , 2456293.52083333, 'localtime');

UNIX时间戳向时间字符串的转换也可以用 strftime。 下面是个例子:

SELECT strftime('%Y/%m/%d %H/%M/%f' , 1092941466, 'unixepoch', 'localtime');

基本上,这里讲的内容对于常规应该应该是够用了。如果需要更多的功能,还是需要去读 SQLite 的官方文档。

这里需要特别强调,SQLite 认为整数或者浮点数存储的时间都是 UTC 时间,字符串时间默认是 UTC 时间,如果字符串时间不是 UTC 时间,而是当前时区的时间,那么我们需要:

  • 在时间字符串向数字(整数或者浮点数)转换时要用 ‘utc’,表示我的字符串时当前时区的,需要先转换为 UTC 时间。
  • 数字(整数或者浮点数)向时间字符串转换时要用 ‘localtime’, 表示我们算出的时间字符串需要转换为当前时区的时间。

SQLite 对时间的支持相关推荐

  1. SQLite日期时间函数

    SQLite日期时间函数 SQLite支持以下五个日期时间函数: date(timestring, modifier, modifier, -) time(timestring, modifier, ...

  2. Delphi纯代码连SQLite数据库,同时支持数据库的加密解密

    //摘自:http://bbs.witbase.com/thread-1141-1-1.html Delphi纯代码连SQLite数据库,同时支持数据库的加密解密 Delphi纯代码连SQLite数据 ...

  3. 【题目】一个信道的比特速率为4Mbps,信号的传播延迟为20ms,数据帧的大小为10^4比特,采用滑动串口协议,不考虑帧的生成时间,支持捎带应答,那么帧序号应为多少bit?

    [题目]一个信道的比特速率为4Mbps,信号的传播延迟为20ms,数据帧的大小为10^4比特,采用滑动串口协议,不考虑帧的生成时间,支持捎带应答,那么帧序号应为多少bit? [答案] 以上答案为本人考 ...

  4. 华为手机什么时候更新鸿蒙系统_华为什么时候用鸿蒙系统 鸿蒙OS上市时间与支持机型...

    华为鸿蒙系统什么时候出? 华为消费者业务首届开发者大会今日举行(8月9日).华为首次公布了自研操作系统"鸿蒙".余承东表示,手机会优先安卓系统,但如果不能用,随时可以启用鸿蒙,从安 ...

  5. SQLite 日期 时间

    SQLite 支持以下五个日期和时间函数: 序号 函数 实例 1 date(timestring, modifier, modifier, ...) 以 YYYY-MM-DD 格式返回日期. 2 ti ...

  6. sqlite 日期时间类型学习1

    根据教程, SQLite 没有一个单独的用于存储日期和/或时间的存储类,但 SQLite 能够把日期和时间存储为 TEXT.REAL 或 INTEGER 值. 存储类    日期格式 TEXT     ...

  7. sqlite关于时间的处理

    今天遇到个问题. 首先插入一个DataTime格式的数据: string sql="insert into [table] (date_time) values('" + date ...

  8. RTI1.3时间管理支持的两种模式

    RTI 1.3目前支持两种模式,一种是轮询模式,一种是异步模式,无论在那种模式下LRC都要做大量工作,比如和其他的联邦成员的LRC交换信息,完成这些工作需要一定时间,tick()函数就是为了给RTI提 ...

  9. 【CSDN博客之星】您的支持就是我最大的动力!喜欢本博客的读者,请拿出您宝贵的几秒钟时间来支持一下吧,非常感谢~

    各位亲爱的读者好, 本人博客自从2010年11月开通以来累计发表文章140篇(原创).本人一直将自己工作和学习经验写成博文分享给大家.今年本人有幸被选为2012年88位候选博客之星,如果各位IT'er ...

最新文章

  1. python绘制雷达图代码实例-PYTHON绘制雷达图代码实例
  2. c语言指针数组 难点总结,C语言之指针与数组总结
  3. JQuery获取元素本身HTML
  4. sysfs API总结
  5. mysql导入数据库某张表_MSSQLServer2005 导出导入数据库中某张表的数据
  6. 优秀员工和普通员工的十大区别,老板和员工都应该知道
  7. break and continue;
  8. 【渝粤教育】国家开放大学2018年春季 8038-22T实用管理基础 参考试题
  9. CG之菲涅尔效果简单实现
  10. java怎么让二维数组不重复_java - 如何创建具有随机产生的,非重复数二维数组? [重复] - SO中文参考 - www.soinside.com...
  11. 计算机二级考试先后顺序,(常文档排按照计算机二级考试试题顺序编写.doc
  12. #今日说码栏目#第十五集 iconfont-阿里巴巴矢量图的使用方法(保姆级教学,挑战全网最细致的使用矢量图)
  13. 在线Java/C++/C语言/Python/web网页编辑器(IDE)整理
  14. antD布局不能占满屏幕问题
  15. 【每周一个小技能】WSA 安装
  16. vue + scss,文本超过多行需要省略号,不起作用
  17. 中产学院全国首创7大黄金技术桂林游学发布会
  18. DFPlayer Mini资料 随手记
  19. D3基本图表绘制——折线图
  20. c语言累乘法,C语言基本算法

热门文章

  1. poi 操作 导出excel 合并列
  2. 【ppt入门教程】PowerPoint课件发布全攻略
  3. WIN10极限清理 C盘空间
  4. 如何爬取微信公众号的所有文章
  5. DellR240服务器U盘引导,【dell uefi u盘引导】dellr730配置uefi引导_dell uefi启动
  6. pe下找不到ssd硬盘_进入pe后找不到固态硬盘怎么解决
  7. android平板电脑怎么才能连接电脑,平板连接电脑没反应怎么办 平板怎样连接电脑...
  8. 【再也不怕pdf转换了】使用Python实现PDF扫描件生成DOCX或EXCEL
  9. Linux帐号和登录安全
  10. pysot-toolkit--eval.py笔记(读取算法结果,根据评价指标计算结果并可视化)