mysql日期类型计算机_深度长文 | 循序渐进解读计算机中的时间—应用篇(下)...

关注【搜狐技术产品】公众号,第一时间获取技术干货

搜狐技术产品:深度长文 | 循序渐进解读计算机中的时间—应用篇(上)​zhuanlan.zhihu.com3f29610a9f0d2df30ff464570034243b.png

3 对时间的存储

讲完表示再来看日期时间的存储方法。以MySQL数据库为例,介绍数据存储的方式,以及与Java程序的交互。

3.1 MySQL的日期时间类型介绍

将MySQL提供的几种日期时间数据结构列表如下:

●YEAR 类型用于表示年份,默认是4位,可以直接插入4位数字或字符串。由于YEAR类型占用空间很小,如果只想表示年份,并在其表示范围内,不失是一种很好的选择。

●DATE 类型用于表示日期,以 YYYY-MM-DD 格式显示。指“日历页上的日期”,没有时区概念,类似于 Java8 中的 LocalDate。

●TIME 类型用于表示时间,以 HH:MM:SS 格式显示,精度为秒。指“挂钟显示的时间”,没有时区概念,类似于 Java8 中的 LocalTime。

●DATETIME 类型是 DATE 和 TIME 的结合,占8位,它把日期和时间封装到格式为 “YYYYMMDDHHMMSS” 的整数中,可以记录较 TIMESTAMP 更长的时间。没有时区概念,类似于 Java8 中的 LocalDateTime。

●TIMESTAMP 类型也是表示日期加时间,但是表示的时间较短,和32位 Unix 时间戳相同。TIMESTAMP 类型表示的时间与时区有关,MySQL服务器、操作系统、客户端连接等都有时区设置,插入日期时会先转换为本地时区后再存放,查询日期时会将日期转换为本地时区后再显示。如果插入时没有指定 TIMESTAMP 列的值,则系统默认设置为 '0000-00-00 00:00:00',也可以手动设置为添加当前时间。

3.2 MySQL的日期时间类型比较与选择

YEAR、DATE、TIME 三种类型都功能不同,YEAR 存年份,DATE 存日期,TIME 存时间,按业务需求进行挑选即可。主要比较 DATETIME 和 TIMESTAMP 类型:

●时区属性不同:DATETIME 无时区属性,TIMESTAMP支持时区变换;

●表示范围不同:DATETIME 表示范围更大,为1000-01-01 00:00:00——9999-12-31 23:59:59,TIMESTAMP 只能表示32位Unix时间戳的范围;

●空间占用不同:TIMESTAMP 只要 4 bytes,效率更高。

●综上:若有明确的需要时区转换或不需要时区转换的问题,则根据业务需求选择对应的,否则会出现逻辑错误;else if 32位Unix时间戳的范围够用则推荐选择 TIMESTAMP 类型,因为空间效率更高。

还有一种可选项:每次涉及日期时间时全部用Unix时间戳表示,Java中用long,MySQL中用INT类型。

详见[如何正确地处理时间-廖雪峰]①。好处是体现了“存储与显示分离”的原则,且易于比较。

但是肉眼无法快速识别时间戳确实带来了很大的麻烦,况且Java和MySQL开发出那么多类型就是为了方便使用(不然上文全都白讲了),也可以解决大多数问题,所以个人并不推荐这种做法(也可能是开发经验不够,没有理解到廖老师这个点的精髓)。

3.3 与Java的交互

笔者自己总结了Java 和 MySQL 日期时间数据类型的一种映射关系:

●在MySQL数据库创建表包含各种类型的字段用于测试:

DATETIME、TIMESTAMP类型默认精确到秒,如需毫秒或更高精度,需手动指定字段长度,如下:

1CREATE TABLE `test_time` (

2 `id` int(11) NOT NULL AUTO_INCREMENT,

3 `time1` date DEFAULT NULL,

4 `time2` time DEFAULT NULL,

5 `time3` year(4) DEFAULT NULL,

6 -- 长度为3精确到毫秒

7 `time4` datetime(3) DEFAULT NULL,

8 -- 长度为6精确到微秒

9 `time5` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

10 PRIMARY KEY (`id`)

11) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;

●使用spring mybatis generator 插件创建 model,自动创建的数据格式都是 java.util.Date。将数据读出时,无关联时区的数据格式都会加上当前系统默认时区,缺少的数据会用缺省值填充。这是一种非常浪费且繁琐且容易出错的方式。如下图:

●MySQL 版本在5.1.37以上的,驱动在4.2以上的,可以使用Java8中的新类型,几乎可以说完美匹配。

4 时区转换的操作

需要时区转换的时间一定不是“挂钟上的时间”,而是时间轴上确定的一个“绝对时间”。所以时区转换分为两个方面:由被展示的字符串添加某时区信息后转为Java对象,或由固定时区的Java对象转换时区后展示。

下面各种方式实现这两个转换:

4.1 无脑加减操作

根据目标时区和原时区的时差直接加减,“硬核转换”,极不推荐。

4.2 Date+SimpleDateFormat

如下图(注意,转为Date对象的时候自动变为了系统时区):

或者更简单的利用“z”这个域:

4.3 ZonedDateTime + DateTimeFormatter

4.4 用时间戳处理

用各种方法得到该时间点的时间戳,然后转化为Java对象,添加时区信息,输出。

4.5 与MySQL的交互转换

按照上述MySQL与Java交互中所述,将MySQL存储的时间转换为Java对象,然后按照2,3方法转换即可。

5 总结

本篇文章全面贴近实际开发,首先从日常代码遇到的问题出发,介绍了一些常识和会遇到的问题。

随后介绍了Java中日期时间的获取、数据格式表示及格式转换方法。其中深入源码详细介绍了Java7中的日期时间数据结构,拆解了可能会遇到的线程安全问题及解决办法,并在使用层面介绍了Java8中日期时间新API及其优点,源码中的复杂计算方法有待今后研究。

接着在存储方面介绍了MySQL的日期时间类型及如何选择的建议,并给出了与Java各种日期时间类型的转换示例。最后根据时区转换的需求给出各种数据结构的时区转换操作方法。

本篇为上篇-应用篇,下篇中会详细解释一些底层日期时间的处理,如为什么不同操作系统获取当前时间的速度有数量级差异;高并发场景用 System.currenTimeMillis() 会出现什么问题及怎么解决;Linux中有哪些时间相关系统调用及他们的区别;系统对于类似 Thread.sleep(long millis) 的“时间段”长度是如何控制的;以上这些底层问题如何影响我们的程序设计等。

参考资料:

[6]《高性能MySQL - 4.1.4日期和时间类型》搜狐新闻推荐算法 | 呈现给你的,都是你所关心的​mp.weixin.qq.com新闻推荐系统的CTR预估模型​mp.weixin.qq.com互联网架构演进之路​mp.weixin.qq.comEmbedding 模型在推荐系统的应用​mp.weixin.qq.com深入理解Flutter多线程​mp.weixin.qq.com

获取更多资讯请关注微信公众号【搜狐技术产品】,微信后台联系搜狐技术产品小助手。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值