1 原因
safari浏览器的new Date(dateStr: string) 格式要求如下:
/*** dateStr里 必须要有 d(日);月、日和时分秒 都不用满足补0规则;但有 时钟 必须有 分钟 ***/
new Date('yyyy/MM/dd HH:mm:ss');
new Date('yyyy/MM/dd HH:mm');
new Date('yyyy/M/d');
new Date('yyyy/M/dd');
new Date('yyyy/MM/d');
new Date('yyyy/M'); // Invalid Date
new Date('yyyy/MM'); // Invalid Date
new Date('yyyy/MM HH'); // Invalid Date
new Date('yyyy/MM HH:mm:ss'); // Invalid Date
/*** dateStr里 不必一定要有 d(日);但 M(月) 、d(日)和时分秒 都必须满足 小于10前面补0;而且如存在时分秒,必须用T连接; 而且有 时钟 必须有 分钟 ***/
new Date('yyyy-MM-ddTHH:mm:ss');
new Date('yyyy-MM-ddTHH:mm');
new Date('yyyy-MM-dd');
new Date('yyyy-MM');
new Date('yyyy-M'); // Invalid Date
new Date('yyyy-M-d'); // Invalid Date
new Date('yyyy/MM HH'); // Invalid Date
new Date('yyyy-MM-dd H:MM'); // Invalid Date
2 解决
2.1 自定义一个构造函数
class MyDate extends Date {
constructor()
constructor(value: number | string)
constructor(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number)
constructor(...args: any) {
super(...args);
if (this.toString() === 'Invalid Date' && args.length === 1 && typeof args[0] === 'string') {
const dateStr = args[0];
const dateReg: any = {
year: '0*(\\d+)',
// 日期的分隔符
splitChar: '(?:([ \\/\\-]))?',
month: '(?:0*([1-9]|(?:1[0-2])))?',
date: '(?:0*([1-9]|(?:[1-2]\\d)|(?:3[0-1])))?',
hour: '(?:0*((?:1?\\d)|(?:2[0-3]))?)',
minute: '(?::0*([1-5]?\\d)?:*)',
second: '(?::0*([1-5]?\\d))?',
millisecond: '(?::0*(\\d{0,3}))?',
// 零点整
zeroOClock: '(?:(24)(?::0*:*)(?::0*){0,2})',
};
// 前面一种情况匹配24点前,后一种是匹配24点整
dateReg.time = `(?:(?:${dateReg.hour}${dateReg.minute}${dateReg.second}${dateReg.millisecond})|${dateReg.zeroOClock})`;
const regStr = new RegExp(`^${dateReg.year}${dateReg.splitChar}${dateReg.month}(?:\\2${dateReg.date})?(?:[ T]+${dateReg.time}:?)?$`);
const dateMathArr = dateStr.match(regStr);
if (dateMathArr) {
return new Date(...(dateMathArr
.slice(1, 2) as Array<string | number>)
.concat(
// d(日): 数字代表的月份比实际月份(字符串传入的)大1,所以需要减去1
(Number(dateMathArr[3]) || 1) - 1,
(dateMathArr[4] || 1),
// H(时),因为匹配time时有两种情况,所以需要兼容第二种情况
dateMathArr.pop() || dateMathArr[5] || 0,
// MM:SS:MS
dateMathArr
.slice(6, 9)
.map(item => item || 0),
));
}
}
}
}
// 使用
const myDate = new MyDate('2022-1-1');
2.2 重写Date函数
Date = function(Date) {
MyDate.prototype = Date.prototype;
// 将Date构造器的属性方法,复制到MyDate构造器上
var propertys = Object.getOwnPropertyNames(Date.prototype.constructor);
if(propertys && propertys.length > 0){
for(var i = 0; i < propertys.length; i++){
var name = propertys[i];
MyDate[name] = Date.prototype.constructor[name];
}
}
return MyDate;
function MyDate() {
// 只对不支持的日期格式做处理
const thisDate = new Date(...arguments);
if (thisDate.toString() === 'Invalid Date' && arguments.length === 1 && typeof arguments[0] === 'string') {
const dateStr = arguments[0];
const dateReg = {
year: '0*(\\d+)',
// 日期的分隔符
splitChar: '(?:([ \\/\\-]))?',
month: '(?:0*([1-9]|(?:1[0-2])))?',
date: '(?:0*([1-9]|(?:[1-2]\\d)|(?:3[0-1])))?',
hour: '(?:0*((?:1?\\d)|(?:2[0-3]))?)',
minute: '(?::0*([1-5]?\\d)?:*)',
second: '(?::0*([1-5]?\\d))?',
millisecond: '(?::0*(\\d{0,3}))?',
// 零点整
zeroOClock: '(?:(24)(?::0*:*)(?::0*){0,2})',
};
// 前面一种情况匹配24点前,后一种是匹配24点整
dateReg.time = `(?:(?:${dateReg.hour}${dateReg.minute}${dateReg.second}${dateReg.millisecond})|${dateReg.zeroOClock})`;
const regStr = new RegExp(`^${dateReg.year}${dateReg.splitChar}${dateReg.month}(?:\\2${dateReg.date})?(?:[ T]+${dateReg.time}:?)?$`);
const dateMathArr = dateStr.match(regStr);
if (dateMathArr) {
const date = new Date(...dateMathArr
.slice(1, 2)
.concat(
// d(日): 数字代表的月份比实际月份(字符串传入的)大1,所以需要减去1
(dateMathArr[3] || 1) - 1,
(dateMathArr[4] || 1),
// H(时),因为匹配time时有两种情况,所以需要兼容第二种情况
dateMathArr.pop() || dateMathArr[5] || 0,
// MM:SS:MS
dateMathArr
.slice(6, 9)
.map(item => item || 0))
);
if (date && date.toString() !== 'Invalid Date') return date;
}
}
return thisDate;
}
}(Date);
// 使用
const myDate = new Date('2022-1-1');
2.2.1 简配版
没有对日期字符串里的数字做更深入的检验,只支持正常的日期字符串;
Date = function(Date) {
MyDate.prototype = Date.prototype;
// 将Date构造器的属性方法,复制到MyDate构造器上
var propertys = Object.getOwnPropertyNames(Date.prototype.constructor);
if(propertys && propertys.length > 0){
for(var i = 0; i < propertys.length; i++){
var name = propertys[i];
MyDate[name] = Date.prototype.constructor[name];
}
}
return MyDate;
function MyDate() {
// 只对不支持的日期格式做处理
const thisDate = new Date(...arguments);
if (thisDate.toString() === 'Invalid Date' && arguments.length === 1 && typeof arguments[0] === 'string') {
const dateStr = arguments[0];
const dateMathArr = dateStr.match(/^(\d+)(?:([ \/\-])(\d+))?(?:\2(\d+))?(?:[ T]+(?:(\d+))(?::(\d+))(?::(\d+))?(?::(\d+))?)?$/);
if (dateMathArr) {
const date = new Date(...dateMathArr
.slice(1, 2)
.concat((dateMathArr[3] || 1) - 1, dateMathArr.slice(4).map((item, index) => item || (index > 0 ? 0 : 1))));
if (date && date.toString() !== 'Invalid Date') return date;
}
}
return thisDate;
}
}(Date);
3 没有解决的问题
比如日期字符串的第一个数字不是年份,在chrome和safari上解析出的日期不同:
new Date('10') // chrome: Mon Oct 01 2001 00:00:00 GMT+0800 (中国标准时间) // safari: Fri Jan 01 0010 08:05:43 GMT+0805 (CST)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。