做接口、写脚本、接表单,只要涉及时间输入,就绕不开日期参数校验。用户随手输个 2023-02-30 或 2025/13/01,后端不拦住,轻则数据错乱,重则程序报错崩掉。
别只信格式,得验真实存在
很多人用正则判断 \d{4}-\d{2}-\d{2} 就算完事,结果 2024-02-30 过了,2023-00-01 也过了——格式对,日子根本不存在。
真正靠谱的校验,得走解析 + 验证两步:先按格式拆解年月日,再丢给语言内置的日期对象或库去“试造”一次。
JavaScript 示例(浏览器/Node.js)
function isValidDate(str) {
if (!/^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/.test(str)) return false;
const [y, m, d] = str.split('-').map(Number);
const date = new Date(y, m - 1, d);
return date.getFullYear() === y
&& date.getMonth() === m - 1
&& date.getDate() === d;
}
console.log(isValidDate('2024-02-29')); // true(闰年)
console.log(isValidDate('2023-02-29')); // false
console.log(isValidDate('2024-02-30')); // false
Python 示例(推荐用 datetime)
from datetime import datetime
def is_valid_date(date_str):
try:
dt = datetime.strptime(date_str, '%Y-%m-%d')
# 再反向格式化验证是否“原样可还原”
return dt.strftime('%Y-%m-%d') == date_str
except ValueError:
return False
print(is_valid_date('2024-02-29')) # True
print(is_valid_date('2024-02-30')) # False
print(is_valid_date('2024/02/29')) # False(格式不符)
常见坑点提醒
• 月份从 0 开始:JS 的 new Date(2024, 1, 29) 是 2 月,不是 1 月;new Date(2024, 13, 1) 会自动进位成 2025 年 2 月——所以必须手动比对原始值。
• 时区干扰:在 JS 中,new Date('2024-02-29') 默认按本地时区解析,跨时区可能出偏移。建议统一用 new Date('2024-02-29T00:00:00Z') 或直接走 toISOString() 处理。
• 字符串截断风险:比如用户输 '2024-02-29abc',正则若没加 ^$ 锚定,也可能通过。务必全匹配。
小技巧:带范围校验更实用
业务中常要限制“不能早于今天”或“不能超过一年后”。加两行就行:
function isValidFutureDate(str, maxDays = 365) {
if (!isValidDate(str)) return false;
const input = new Date(str);
const now = new Date();
const max = new Date();
max.setDate(max.getDate() + maxDays);
return input >= now && input <= max;
}
校验不是炫技,是堵住用户随手一填带来的意外。几行稳当代码,换来的可能是少一次半夜爬起来修 bug。