令人困惑的strtotime - 风雪之隅


本站和网页 http://www.laruence.com/2018/07/31/3207.html 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

令人困惑的strtotime - 风雪之隅
Press "Enter" to skip to content
风雪之隅 左手代码右手诗 open menu
mobile menu toggle button
主页
PHP源码分析
PHP应用
JS/CSS
随笔
留言
博客地图
令人困惑的strtotime
Published on
31 July 2018
by
laruence
作者:
Laruence
-->
本文地址:
https://www.laruence.com/2018/07/31/3207.html
转载请注明出处
经常会有人被strtotime结合-1 month, +1 month, next month的时候搞得很困惑, 然后就会觉得这个函数有点不那么靠谱, 动不动就出问题. 用的时候就会很慌...
这不, 刚刚就有人在微博上又问我:
鸟哥,今天是2018-07-31 执行代码:
date("Y-m-d",strtotime("-1 month"))
怎么输出是2018-07-01?
好的吧, 虽然这个问题看起来很迷惑, 但从内部逻辑上来说呢, 其实是"对"的:
我们来模拟下date内部的对于这种事情的处理逻辑:
1. 先做-1 month, 那么当前是07-31, 减去一以后就是06-31.
2. 再做日期规范化, 因为6月没有31号,
所以就好像2点60等于3点一样, 6月31就等于了7月1
是不是逻辑很"清晰"呢?
我们也可以手动验证第二个步骤, 比如:
var_dump(date("Y-m-d", strtotime("2017-06-31")));
//输出2017-07-01
也就是说, 只要涉及到大小月的最后一天, 都可能会有这个迷惑, 我们也可以很轻松的验证类似的其他月份, 印证这个结论:
var_dump(date("Y-m-d", strtotime("-1 month", strtotime("2017-03-31"))));
//输出2017-03-03
var_dump(date("Y-m-d", strtotime("+1 month", strtotime("2017-08-31"))));
//输出2017-10-01
var_dump(date("Y-m-d", strtotime("next month", strtotime("2017-01-31"))));
var_dump(date("Y-m-d", strtotime("last month", strtotime("2017-03-31"))));
那怎么办呢?
从PHP5.3开始呢,
date新增了一系列修正短语,
来明确这个问题, 那就是"first day of" 和 "last day of",
也就是你可以限定好不要让date自动"规范化":
var_dump(date("Y-m-d", strtotime("last day of -1 month", strtotime("2017-03-31"))));
//输出2017-02-28
var_dump(date("Y-m-d", strtotime("first day of +1 month", strtotime("2017-08-31"))));
////输出2017-09-01
var_dump(date("Y-m-d", strtotime("first day of next month", strtotime("2017-01-31"))));
////输出2017-02-01
var_dump(date("Y-m-d", strtotime("last day of last month", strtotime("2017-03-31"))));
////输出2017-02-28
那如果是5.3之前的版本(还有人用么?),
你可以使用mktime之类的, 把所有的日子忽略掉, 比如都限定为每月1号就可以了, 只不过就不如直接用first day来的更加优雅.
现在, 搞清楚了内部原理, 是不是就不慌了?
Filed in
-1 month
first day of
last day of
last month
next month
PHP
strtotime
Previous Post
深入理解PHP7内核之Reference
Next Post
print不是函数
175 Comments
Prestige park grove
July 7, 2023
Brother Bird actually updated it…
hartono
April 25, 2023
Very good post, thanks for the info
bromo adventureland
July 14, 2022
Thanks
deng
October 11, 2021
echo date(‘Y-m-d H:i:s’,671565600);// 1991-04-14 03:00:00
echo strtotime(“1991-04-14 02:00:00”);//03
请问鸟哥,1991-04-14 02:00:00这个时间在某些php版本为什么会出现转换错误的情况
小李世界
August 28, 2021
这么说也是哦,-1 month,每个月不一样的天数,所以正规是单纯地在月份上减去 1,很符合自然逻辑,哈哈。-1 月,实际上是减去上个月的天数,+1 月,实际上是加这个月的天数,这种逻辑很少人用吧。
令人困惑的strtotime – 彭立涛的博客
January 7, 2021
[…] 本文转载自
[…]
v24
July 1, 2020
这有点坑啊,以前都没发现,赶紧翻一翻代码
污泥螺杆泵
March 24, 2020
个人整理, 阅读过的好文章 (每天随时更新) _ 脚本宝典
February 4, 2020
[…] 令人困惑的strtotime […]
PHP中时间函数strtotime记录容易出现bug的情况 – FreeLoop
February 1, 2020
[…] 参考:
http://www.laruence.com/2018/07/31/3207.html
smith smith
December 31, 2019
用carbon库就没这个问题了
w-viviv-vip
January 8, 2020
`Carbon::parse(‘2019-12-31’)->subMonth();` 还是`2019-12-01`
whitek
March 19, 2020
可以使用 subMonthNoOverflow()
凉风有信
新手踩坑,前来膜拜
令人困惑的strtotime – 芒果日志
December 20, 2019
[…] 本文转载自: http://www.laruence.com/2018/07/31/3207.html […]
Alan
November 19, 2019
前几天,我走进大自然,没有来自城市的喧闹声,没有头痛,只有我和大自然的声音。
气动隔膜泵
November 4, 2019
seying
October 27, 2019
正好用到这个,学习了。
xiong
October 17, 2019
确实很容易出现坑
PHP精通教程-开始
September 17, 2019
不错支持一下
zjc348
September 3, 2019
学习了
PHP 高级教程-面向对象编程(OOP)[第三章]
August 31, 2019
分享的不错
好了睡
August 29, 2019
请教一下,如果想获取上周的周一,这种时间,strtotime 有没有类似的修正短语呢
rain
August 5, 2019
已采坑
php strtotime引起的错误 – 流浪者
July 31, 2019
[…] 后面再网上找到了一篇文章, 讲解这个问题的
[…] 后面再网上找到了一篇文章讲解,这个问题的
Thinklong
July 29, 2019
这个问题是我经常问初中级的面试题
abc
October 31, 2019
zi yi wei shi de sha bi mian shi guan
zzn
November 18, 2020
niu bi
cck
频敏变阻器
July 26, 2019
学习了,好文章,就喜欢这种干货!
xiaoming
这个 +1 month ,可以理解成 +30 day,这样就可以理解了为啥2017-08-31 变成了 2017-10-01
错了是 +31 day
LC
November 26, 2019
就是月份加1不是加30天,再校验日期,请再熟读一边
2017-08-31加1月是 2017-09-31
进位了成2017-10-01
没有错,
相当于月位相加减,再格式化为合法的日期
搬瓦工
July 22, 2019
学习了 期待更多好文
mx
July 20, 2019
good
Dovino
July 16, 2019
very helpful
zhangbin
July 11, 2019
$now = strtotime(“2018-03”);
echo date(‘Y-m-d’,strtotime(‘-1 month’, $now));
echo “\n”;
var_dump(date(‘Y-m-d’,strtotime(“first day of -1 month”,strtotime(“2018-03-31”))));
zaky
学到了
Rohman Suparno
Nice
张鹏
July 6, 2019
为什么要加first day , last day这种方式来手动规范结果而不是PHP语言自动将正确结果显示出来?我用PHP7的版本还是会有这种问题。
lao lu
July 3, 2019
卧槽。。不敢用了。。这太坑了。。
vegisau
June 27, 2019
emmm, 我一直都是01号开始+1 month,这种逻辑出现在金融上不堪设想
令人困惑的strtotime | 杨龙
May 12, 2019
令人困惑的strtotime strtotime的一些问题
本条目发布于2019年5月12日。属于PHP分类,被贴了 php […]
令人困惑的strtotime – 技术笔记
March 14, 2019
[…] 本文地址:
陈龙强
March 12, 2019
鸟哥,个人认为这个问题,不应该说是修正程序的问题吗?
如果 -1 month 溢出了,应该要取上个月真实的最后一天吧?
而不是没有这天,就直接把差值累加上去了。
您在这里说清楚了,但这个坑相信会被踩无数次,哈哈~
Vito
March 8, 2019
鸟哥,这个last day of -1 month,只能解决想获得的是所求日期的上个月月末最后一天,而并不能得到所求日期的一个月前的时间,说白了,一个月多久不定,php无法定义,
感觉如果真的想严谨的定义 -1 month 或者 +1month, 应该提供一个求上个月或者下个月天数n 的的函数,然后利用 -n days 或者 +n days 比较科学,因为一天24个小时,是固定不变的。。。
也就是这个 -1 month 不如自己写个方法,自己定义好12个月对应的天数n,然后利用 -n days 或者 +n days
RCS Capital Partners
March 5, 2019
dheaf
http://wireless.fcc.gov/cgi-bin/wtbbye.pl?ftp://tidepool.nos.noaa.gov/pub/users/servary/pdt/rcs-capital-partners-help.pdf
ta_shuo
March 4, 2019
以前竟然都没考虑过这种极端问题,隐藏的好深的bug
1ad
February 25, 2019
eee
云天
February 17, 2019
我觉得这个问题应该这样理解,内部在实现的时候减去的为上个月所含有的天数。比如2月有29天 3月有31天
var_dump(date(“Y-m-d”, strtotime(“-1 month”, strtotime(“2017-03-31”))));得到的结果为2019-03-31减去的29天之后的日期。这样算是科学的,因为应该是从上月1号对应本月1号开始往后一一对应正推,而不是从本月底对应上月底来倒推。所以应该减去上月的天数。
笔误应该是var_dump(date(“Y-m-d”, strtotime(“-1 month”, strtotime(“2019-03-31”))));
黄江宇
March 16, 2019
test1
Malu
May 23, 2019
我测试过了好像的确是这样的,3月的30号减一个月就是03-02,29号就是03-01。
安德森
February 13, 2019
好,学到了
学好了
再学一次
111
11
曹东超
了解了。
令人困惑的strtotime – 庸人
January 30, 2019
[…] 本文转载自: 
Jason
February 2, 2019
写的不错!
January 29, 2019
妙啊
CVV shop
很清楚 – what does it mean pls?
guang
January 22, 2019
可是原本的需求还是没解决啊
曹金龙
January 20, 2019
好文 能学习
Free cloud hosting
January 11, 2019
哥更文了!
令人困惑的strtotime – 拾零
January 9, 2019
[…] 本文地址: http://www.laruence.com/2018/07/31/3207.html […]
VPS234
感觉这是WordPress的代码呢
Hoe
January 8, 2019
恍然大悟啊
shirne
January 3, 2019
稳的一批
boyer
December 31, 2018
tlanyan
December 29, 2018
总结就是程序不会错,结果错说明用法不对
php二次开发
December 25, 2018
经常这样用,一直不理解,偶尔还出错,总算弄明白了,感谢博主。
ARM
December 19, 2018
暂时还没用到,先Mark一下
个人整理, 阅读过的干货文章 (每天随时更新) – 乌托邦
November 30, 2018
strtotime的一个使用问题 – 1
November 29, 2018
[…] 参考资料:http://www.laruence.com/2018/… […]
个人整理, 阅读过的好文章 (每天随时更新) – 1
chenweijie
November 26, 2018
稳!
安满
November 24, 2018
鸟哥分析的很清晰易懂
fatming
November 21, 2018
还是很慌怎么办….
既然正常人都觉得 10-31 的 *上一个月*不应该还是10月份,
那为什么不把默认值就设置为9月30号呢. 就算有短语可以修正,真的一点都不优雅, 而且很拗口=.=
noone
November 20, 2018
漂亮
AlicFeng
November 17, 2018
nice??
avrilko
November 16, 2018
三顿饭
November 14, 2018
鸟哥。正文的字体太细了,能否改粗点
天猫超市优惠券
November 12, 2018
学习学习,涨知识
showbox
November 6, 2018
经常会有人被strtotime结合
van23qf
November 5, 2018
还有这种操作,平时都没注意到。。。
yun
October 29, 2018
个人整理, 阅读过的干货文章 (每天随时更新) – 不方
October 27, 2018
qwqw
October 22, 2018
这个问题不应该用鸟哥最后讲的方法解决,还是应该在函数内部解决
straiway
October 20, 2018
之前遇到过这样的情况,也觉得strtotime不靠谱,但是没深究。感谢鸟哥,看来遇到问题最彻底的办法就是看源码?
DusNoob
October 18, 2018
涨姿势了,做项目一直都没注意到
annon
October 15, 2018
鸟哥好棒
Günaydın
October 8, 2018
鸟哥好棒!
yang
November 15, 2018
nice
00
000
Venus Zhu
September 30, 2018
只有我觉得右侧新浪添加关注的插件会挡住昵称而别扭嘛?!逼死强迫症。谷歌浏览器 版本 69.0.3497.100(正式版本) (64 位)
陈小东
October 17, 2018
我这里也挡住了
2s
September 28, 2018
不慌不慌
Sakura
jian.liu
September 27, 2018
简单的问题复杂化,复杂的问题简单化!
zhebie
September 26, 2018
通俗易懂,厉害厉害,我是转行过来做的php,现在会点python和golang,一入编程深似海,感觉学不完,随便哪个语言。。。
Liu zhi peng
我刚刚百度完鸟哥的个人信息,好厉害,以后我们就叫你做大哥,你就叫我们练功夫
bunsen zhou
September 25, 2018
还是挺好理解的,官网文档看仔细点就不会乱了
杨小杰博客
September 22, 2018
小沐博客
好巧啊
Donne
September 14, 2018
一般获得「上个月的今天,当这天不存在就取上月的最后一天」,是更「亲人」的描述方式吧,这种逻辑就没办法很简单的一个 strtotime 去处理了。
haibao
September 13, 2018
讲的很清楚了~ 666
JackMa
September 12, 2018
涨姿势了
5G云资源分享网
September 9, 2018
还真不知道有这样操作,学习了。
Lanffy
September 5, 2018
向大佬学习,这以前还真不知道。哈哈
king
August 31, 2018
这是大佬时间长没写过业务了么? 为什么我搞清楚了反倒是感到这个函数好不靠谱? strtotime一点都不php风格,我现在有需求要求查询用户上个月的今天到今天一共做了某某个事件,请问怎么用一句strtotime解决???
za
取数据的时候,取这俩个时间的unix时间戳之间的对应的数据,count一下,不行嘛?
pp
October 2, 2018
********
echo date(“Y-m-d H:i:s”, strtotime(date(‘Y-m’)));
看下这个日期是不是你要的结果
charlie
慌而不乱
August 30, 2018
看完深覺 strtotime 的月份加減是雞肋了
沒辦法精準加減到上、下個月對應的日子
即使 first day of、last day of 也只能取得月初、月底
任意日期,也得另外判斷每個月有幾天
(正努力回想寫過的程式有沒用到功能過)
yan
August 27, 2018
鸟哥终于换主题了! 特别像sublime的风格!
LEWISS
比如说我们是当前日期的上个月对应时间, 是个动态情况条件,那这个还是没有解决实际问题吧
niming
自己转换一下呗,比如每个月都有10号,你就只用10号做’-1 month’操作,得到月份后再拼接一下日期。
cvv shop
August 26, 2018
你是一位出色的作家。 今天很难找到一个能清楚理解的人。谢谢! 我是你的常客。
膜拜各路大神
August 21, 2018
轮子
August 20, 2018
我司还在用5.2 #fml
Renling
August 23, 2018
都是7的时代了,你竟然还在用5.2?
Bill Gates
August 19, 2018
作为PHP开发组为数不多的华人成员,私觉得鸟哥适合稍微提高一下发文频次,让我们这些“二把刀”能够对PHP有更深的了解。比如,PHP未来的发展方向、最新主版本(比如现在的PHP 7.3 Beta)在性能上的表现以及为什么。
breeze
August 18, 2018
模板比以前好看
Bruce
August 16, 2018
解释得清晰明了!
笨小孩
August 15, 2018
第一个参数为时间戳时,在windows环境下,返回值一直正常。但是在linux环境下,有些时间戳返回正常,有些时间戳返回与预期不一样。(正常应该返回false),例如strtotime(1500516291)
奋斗
感觉这个博客模板很low啊
cloedy
August 13, 2018
鸟儿哥, 你终于终于换了个blog模板了
aaa
August 9, 2018
鸟哥
qianfeng
鸟哥大神,久仰您很久
masker
仰望鸟哥,我这种PHP小菜鸟快完蛋了
魔王卷子
鸟哥的博客主题终于换了。
裸奔の蜗牛
更加慌了
mengkang
August 7, 2018
恭喜鸟哥博客前端改版,看微博得知还是鸟哥亲自操刀。
落舞者
哈哈哈,还是还以为谁博客呢。换主题了。差点没认出来。鸟哥加油永远支持php。
推广网
为什么不直接在php服务器里做判断 ,而是要用first day of 这个判断 ,每个月多少天是固定的
Pianyiwan.com
网站新的模版,好看多了!!
Fast Light
August 6, 2018
我在写js的时候也遇到过类似的问题,都是因为各个月份天数不同造成的。
懒人儿咖啡
怎能一个漂亮了得, 666
wuxiaworld
但我很害怕
lcp0578
我也有点慌了,鸟哥
谢谢鸟哥
哇,更新了,谢谢鸟哥
AIinjection
August 5, 2018
PHP 的时间函数和时区结合起来,感觉有点乱。特别是当语言自身,框架,ini 都可以配置时区的时候,就更加措手不及了。
Willove
还是很慌。。。为啥 first day of next month 取的不是0点的时间戳,而还是对应了当前时间的时分秒,大多数能够用到这个参数的需求是想取0点的时间戳。
dilex
August 4, 2018
谢谢
aarongoo
呃………这样啊
龙笑天
time()、date()、strtotime() 这三个函数的时区问题很烦~~
西枫里
哇哦,博客换主题了,点个卯~
樊浩柏
August 3, 2018
现在不慌了。
沦陷今生
August 2, 2018
我也遇到过,幸好可以用mysql填这个坑
SELECT DATE_ADD( ‘2017-01-31’, INTERVAL 1 MONTH ),DATE_ADD( ‘2017-01-31’, INTERVAL 2 MONTH ),DATE_ADD( ‘2017-01-31’, INTERVAL 3 MONTH );
就可以得到和预期一样的结果
2017-02-28
2017-03-31
2017-04-30
http://lxjsmdc.com/php/get-next-month.html
tanteng
August 1, 2018
终于更新了!
jack
额 其实还是很方啊,我一直以为是这样的,2.28 +1 month = 3.31 结果是3.28
统计的时候,要判断是大小月 还要判断上个月是大小月,然后还得今天是月末,还是月初。。。。
之前在php手册上看到 这个
[kumar AT swatantra.info Swatantra Kumar ]
这位同学在5 years ago的说的
var_dump(date(“Y-m-d”, strtotime(“-1 month”, strtotime(“2017-03-31”))));
只是感觉不对劲
这能归结为一个bug么。鸟大大 。
余志斌
July 31, 2018
写错日期了,修改写:实际我是想获取到前者(2018-09-12)
Tonight
鸟哥,请问下first day of/last day of后面的关键词,在底层是如何解析的?
使用first day of +1 month或者last day of +1 month,是可以获取到当前日期下个月的第一天或最后一天。
当如果我当前日期是2018-08-12,使用+1 month,会获取到2018-09-12,使用first day of +1 month,会得到2018-09-01。实际我是想获取到前者(2018-08-12),所以这个first day of还是有些情况不能兼容到
dream-fei
不慌了,原来如此
我现在更慌的…:(
白菜
感觉还是mktime好用,这种情况还是比较特殊的。不够灵活。
老郭博客
的确不慌了、
侉帮子
鸟哥终于更新博客了。
loadinger
鸟哥竟然更新了…
最近是玩农药玩得少了呀,这可不行.再说dota2,马上ti了,训练不能少~!
Charles
谢谢鸟哥回复
匹配这么多种情况,还有这么长的字符串,我还是用mktime吧,啥时候给博客加上微博表情包就好了。
莫非
不慌,了
沈唁志
鸟哥更文了!
Comments are closed.
Sidebar
开发组核心成员,
Zend
顾问, PHP7及PHP8 JIT核心作者. Yaf等开源项目作者.
Search
开源项目
Yaf
:  PHP Framework in PHP extension
Yar
:  Light, concurrent RPC framework
Yac
:  PHP Contents cache
Yaconf
:  PHP Configurations Container
Taint
:  XSS code sniffer
Lua
:  Embedded lua interpreter
MsgPack
:  MessagePack in PHP extension
Couchbase
:  Libcouchbase wrapper
See also:  
laruence@github
最新评论
Hengist Wang
on
关于调用约定(cdecl、fastcall、stcall、thiscall) 的一点知识
拍黄瓜
PHP 8新特性之Attributes(注解)
陶路
博客迁移到腾讯云
tattvamretreat
深入理解Zend SAPIs(Zend SAPI Internals)
Sobha Town Park
PHP 8新特性之JIT简介
个人公众号
标签
Apache
apc
bug
C++
core
curl
Extension
IE
javascript
js
json
mysql
nginx
opcache
Performance
PHP5.4
PHP5.4新特性
PHP7
PHP8
PHP 8
PHP extension
php原理
PHP扩展
php源码
php源码分析
SAPI
session
valgrind
vim
yac
Yaf_Loader
zval
优化
低概率core
内核
原理
开发php扩展
性能
性能优化
扩展开发
正则
分类
Select Category
GNU C/C++  (11)
Js/CSS  (24)
Linux/Unix  (15)
MySQL/PostgreSQL  (7)
PHP Extension  (19)
PHP7  (9)
PHP8  (5)
PHP应用  (188)
PHP源码分析  (86)
转载  (34)
随笔  (111)
Links
Licence
Sitemaps
Site Feed
Yaf Manual
SSE Intrinsics Guide
X86 Instruction Reference
Realsee
访客地图
©
博客声明
京ICP备15032766号
PHP 8.1.0-NTS(JIT)
/ Theme By
Compete Themes