JavaScript多格式日期字符串转Date对象及时间戳问题
解决多种日期字符串格式转Date对象的问题
这个坑我踩过好多次!JavaScript原生的Date构造函数对非ISO标准的日期字符串真的很不友好,就像你遇到的情况:15/01/2012这种日在前的格式,它会误以为是月日,15超过了月份的范围,直接返回Invalid Date;连-分隔的15-01-2012也识别不了。下面给你几个实用的解决方案:
方案一:自定义解析函数(原生实现,无需依赖)
针对你提到的三种格式,我们可以写一个函数手动拆分日期部分,根据分隔符和数字范围判断格式:
function parseCustomDate(dateStr) { let dateParts, timeParts; // 拆分日期和时间部分 const [datePart, timePart] = dateStr.split(' '); timeParts = timePart ? timePart.split(':') : [0, 0, 0]; const [hours, minutes, seconds] = timeParts.map(Number); if (datePart.includes('/')) { dateParts = datePart.split('/').map(Number); const [first, second, year] = dateParts; // 判断是dd/MM还是MM/dd:第一个数字>12则为dd/MM if (first > 12) { // dd/MM/yyyy 格式 return new Date(year, second - 1, first, hours, minutes, seconds); } else { // MM/dd/yyyy 格式 return new Date(year, first - 1, second, hours, minutes, seconds); } } else if (datePart.includes('-')) { dateParts = datePart.split('-').map(Number); const [first, second, year] = dateParts; // 判断是dd-MM还是MM-dd:第一个数字>12则为dd-MM if (first > 12) { // dd-MM-yyyy 格式 return new Date(year, second - 1, first, hours, minutes, seconds); } else { // MM-dd-yyyy 格式 return new Date(year, first - 1, second, hours, minutes, seconds); } } // fallback到原生解析(处理ISO格式等) return new Date(dateStr); } // 测试示例 console.log(parseCustomDate("05/01/2012 21:10:17")); // Tue May 01 2012 21:10:17... console.log(parseCustomDate("15/01/2012 21:10:17")); // Sat Jan 15 2012 21:10:17... console.log(parseCustomDate("15-01-2012 21:10:17")); // Sat Jan 15 2012 21:10:17... console.log(parseCustomDate("01-15-2012 21:10:17")); // Sun Jan 15 2012 21:10:17...
逻辑说明:
- 先拆分日期和时间部分,分别处理时分秒
- 根据日期部分的分隔符(
/或-)拆分日、月、年 - 通过判断第一个数字是否大于12,区分是“日在前”还是“月在前”的格式
- 用
new Date(year, monthIndex, day, ...)构造日期(注意月份是0-based,必须减1)
方案二:正则匹配精准解析(更可靠,适合明确格式场景)
如果你的业务中只有固定的几种日期格式,用正则表达式精准匹配是最不容易出错的方式:
function parseDateWithRegex(dateStr) { // 定义三种格式的正则 const patterns = [ { regex: /^(\d{2})\/(\d{2})\/(\d{4}) (\d{2}):(\d{2}):(\d{2})$/, format: 'dd/MM/yyyy' }, { regex: /^(\d{2})-(\d{2})-(\d{4}) (\d{2}):(\d{2}):(\d{2})$/, format: 'dd-MM-yyyy' }, { regex: /^(\d{2})-(\d{2})-(\d{4}) (\d{2}):(\d{2}):(\d{2})$/, format: 'MM-dd-yyyy' } ]; for (const { regex, format } of patterns) { const match = dateStr.match(regex); if (match) { let day, month, year; const [, p1, p2, p3, hours, minutes, seconds] = match.map(Number); if (format === 'dd/MM/yyyy' || format === 'dd-MM-yyyy') { day = p1; month = p2; year = p3; } else if (format === 'MM-dd-yyyy') { day = p2; month = p1; year = p3; } return new Date(year, month - 1, day, hours, minutes, seconds); } } return new Date(dateStr); } // 测试示例 console.log(parseDateWithRegex("15/01/2012 21:10:17")); // Sat Jan 15 2012... console.log(parseDateWithRegex("15-01-2012 21:10:17")); // Sat Jan 15 2012... console.log(parseDateWithRegex("01-15-2012 21:10:17")); // Sun Jan 15 2012...
逻辑说明:
- 为每种格式编写精准的正则表达式,确保只匹配对应格式的字符串
- 匹配成功后,根据格式提取对应的日、月、年部分
- 构造Date对象,同样注意月份的0-based转换
方案三:使用第三方日期库(适合复杂场景)
如果你的项目允许引入第三方库,date-fns(轻量、现代)或者luxon(替代moment.js)都能轻松处理多种日期格式,无需自己写复杂逻辑:
以date-fns为例:
import { parse } from 'date-fns'; // 解析不同格式的日期字符串 const date1 = parse("15/01/2012 21:10:17", "dd/MM/yyyy HH:mm:ss", new Date()); const date2 = parse("15-01-2012 21:10:17", "dd-MM-yyyy HH:mm:ss", new Date()); const date3 = parse("01-15-2012 21:10:17", "MM-dd-yyyy HH:mm:ss", new Date()); // 转时间戳 const timestamp1 = date1.getTime(); // UI展示示例(根据需求格式化) const displayStr = date1.toLocaleString('en-IN', { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' });
优势:
- 库已经封装了各种边缘情况的处理,比如闰年、不同时区等
- 支持更多格式和本地化需求,减少自己造轮子的bug
后续处理
不管用哪种方法得到Date对象后:
- 转时间戳:直接调用
date.getTime()或者用+date获取毫秒级时间戳 - UI展示:可以用
date.toLocaleString()或者Intl.DateTimeFormat自定义展示格式,适配不同地区的用户习惯
内容的提问来源于stack exchange,提问作者Nagarjuna Reddy
相关产品推荐
相关产品推荐

