mysql 日期 1970,Mysql中处理1970年前的日期(unixtime为负数的情况)负数时间戳格式化...

客户扔过来一个bug,说是一个系统中对42岁以上的人的统计不正确,而41岁以下的人没有问题。眼睛瞟了一下托盘区里的日期,2012年3月26日,嗯,今年42岁的话,那么应该就是出生在1970年左右,马上就把问题锁定在了unixtime上,嗯,重点怀疑!

小贴士:UNIX时间,或称POSIX时间是UNIX或类UNIX系统使用的时间表示方式:从协调世界时1970年1月1日0时0分0秒起至现在的总秒数,不包括闰秒。——来自《维基百科》

看了一下数据库,生日是以int形式保存的,有正有负。这没啥问题嘛。

再看代码,SQL语句中有一个类似下面的条件语句:

WHERE FROM_UNIXTIME(birthday, '%Y') = XXX

其中的birthday是存放生日日期的unixtime值的字段,int类型的。XXX由PHP的date('Y', timestamp)来算出年份。在我的印象中,PHP的date函数处理负数的时间戳是没有问题的(注:PHP4在windows下不能处理负数时间戳,PHP5则没有这个问题。客户的服务器是Linux的,PHP4也没有问题)。好吧,那么我就开始怀疑FROM_UNIXTIME函数了,以前还真没怎么注意这玩意。随手写两个测试:

> SELECT FROM_UNIXTIME(1);> 1970-01-01 08:00:01

看来FROM_UNIXTIME还与时区有关系。继续来:

> SELECT FROM_UNIXTIME(-1);> NULL

哦耶,FROM_UNIXTIME果然不支持负数。测试版本为Mysql 5.1.x

这是一个条件语句,又不能拿出来由PHP处理。当然办法还是很多,比如把生日所在年换一个以unixtime表示的年龄段等等。但是我们只讨论如何用mysql计算负数的unixtime。

我们知道了unixtime表示的是从1970年1月1日0时0分0秒开始到现在的秒数,而为负的情况就是1970年第一天之前的秒数,那么可不可以通过时间计算来算出来呢?查手册,找到一个date_add函数,可以计算时间的加减。那我们就以1970年的第一天(unixtime=0的时候)作为基准来手动计算吧。由于Mysql的日期计算基本上都和时区有关系,我也懒得去搞了,就写一个大一点的秒数来看看结果:

> SELECT DATE_ADD(FROM_UNIXTIME(0), INTERVAL 1234567SECOND);> 1970-01-15 14:56:07

这是没有问题的,unixtime为负数的情况下:

> SELECT DATE_ADD(FROM_UNIXTIME(0), INTERVAL -1234567SECOND);> 1969-12-18 01:03:53

哦耶!成功了!那么剩下的问题就简单了,将本文开始的查询条件修改为:

WHERE DATE_FORMAT(DATE_ADD(FROM_UNIXTIME(0), INTERVAL birthday SECOND),'%Y') = XXX

就没问题了,BUG去除成功。

本例中用了到INTERVAL关键字,由于它不止可以用于date_add函数,那下面再总结一下DATE_ADD函数的单位(从官方手册里抄来的,为了方便理解,有一点小修改):

使用格式:INTERVAL expr type

举例:

DATE_ADD(date,INTERVAL

expr type)

DATE_SUB(date,INTERVAL expr type)

date +/-INTERVAL expr type等。

关键词INTERVA及

type分类符均不区分大小写。

type值

预期的expr格式

MICROSECOND

整数

SECOND

整数

MINUTE

整数

HOUR

整数

DAY

整数

WEEK

整数

MONTH

整数

QUARTER

整数(季节)

YEAR

整数

SECOND_MICROSECOND

'秒.毫秒'

MINUTE_MICROSECOND

'分钟数.毫秒'

MINUTE_SECOND

'分:秒'

HOUR_MICROSECOND

'小时数.毫秒'

HOUR_SECOND

'时:分:秒'

HOUR_MINUTE

'时:分'

DAY_MICROSECOND

'日期号数.毫秒'

DAY_SECOND

'日 时:分:秒'

DAY_MINUTE

'日 时:分'

DAY_HOUR

'日 小时'

YEAR_MONTH

'年-月'

转: https://blog.unlink.link/sql/mysql_before_1970_minus_unixtime.html

mysql的from_unixtime只能处理1970~2038年的时间戳,超过必须要上面的思路,并且int长度也只能表示到2038年,bigint可以表示的范围大些

bf9f90a8556e51200bd5bff9f80827c0.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值