strtotime为何对特殊字符串返回日期?如何校验合法日期格式?
strtotime() 返回非日期类字符串时间戳的底层原理
strtotime() 的核心设计逻辑是贪心宽松匹配,不会要求输入字符串全量符合日期格式,只要能从中提取到可识别的日期、时间、时区相关标识,剩余无法识别的内容会被直接忽略,缺失的日期字段会自动补全为当前系统时间的对应值,这是相关现象的根本原因,具体对应测试案例:
'Poland'、'GB'属于被PHP时区映射库收录的地区/国家代称,解析器会匹配到对应的时区标识,补全当前日期生成对应时区的时间戳;'Soland'没有对应的时区/地区映射关系,无合法标识可匹配因此返回false。- 单个字母
'G'、'P'是PHP预设的时间/时区格式标识:G代表24小时制无前置零的小时数,P代表时区偏移量,解析器识别后会补全当前日期的其他字段生成时间戳。 - 普通字符串
'a string'中的开头字符a会被识别为上午(am)标识,剩余的string内容被直接忽略,补全当前日期的0点生成对应时间戳。
无预设日期格式前提下的校验方案
首先明确:strtotime() 本身的设计目标是兼容人性化的日期表述,不适合用来做严格的日期合法性校验,要排除这类特殊字符串可以用以下方案:
- 优先用
date_parse()函数解析输入字符串,查看返回结果中的error_count、warning_count字段,只要数值大于0就判定为不合法;同时检查unparsed字段,如果存在未被解析的内容,说明字符串包含非日期相关字符,直接排除。 - 若使用
DateTime类解析,可配合DateTime::getLastErrors()方法获取解析错误信息,校验逻辑和date_parse()一致。 - 额外增加双向校验:把解析得到的日期对象按照识别到的格式回转为字符串,和原始输入字符串做完全匹配验证,只有完全一致才判定为合法。
注意:完全没有预设格式的场景下不存在100%准确的校验方案,很多日期表述存在天然歧义(比如
03/04/2024可被解读为3月4日或4月3日),如果业务允许建议提前限定预期的日期格式范围,用DateTime::createFromFormat()逐个尝试匹配预设格式,是准确率最高的方案。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

