博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一起Polyfill系列:让Date识别ISO 8601日期时间格式
阅读量:5897 次
发布时间:2019-06-19

本文共 9546 字,大约阅读时间需要 31 分钟。

一、什么是ISO 8601日期时间格式

  ISO 8601是国际标准化组织制定的日期时间表示规范,全称是《数据存储和交换形式·信息交换·日期和时间的表示方法》。

  示例:

  1. 2014-12-12T00:00:00.000Z

  2. 2014-12-12T00:00:00.000+08

  3. 2014-12-12T00:00:00.000+0800

  4. 2014-12-12T00:00:00.000+08:00

  5. 2004-W17-3

  6. 0001-165

详细说明请参考度娘:http://baike.baidu.com/link?url=Qr7NLClAyUHihOCl1DK6DQL_gMw5rk3euXdiz3zt6M9ORGFS2XBy7LHmcO2ID-iz

 

二、Javascript中实现的ISO 8601日期时间格式

  度娘后大家应该对ISO 8061有一定的了解了吧。ISO 8601的内容十分丰富,可惜Javascript仅仅实现一小部分而已,不过这一部分就够我们用了。

  javascript支持的ISO 8061格式如下:

   1. 2014-12-12T00:00:00.000Z

 2. 2014-12-12T00:00:00.000+0800

   3. 2014-12-12T00:00:00.000+08:00

 

二、ES5中涉及ISO 8061日期时间格式的方法

 1.  Date.parse({String} datetime) :接收ISO 8061和GMT的日期时间格式字符串(根据格式内容被识别为0时区或其他时区的日期时间),返回入参所表示的0时区日期时间距离1970年1月1日的毫秒数。

   2.  Date.prototype.toISOString() :返回当前Date类型对象0时区的ISO 8061日期时间格式字符串。形如:2014-12-12T00:00:00.000Z

   3.  new Date({String} datetime) :构造函数的入参在ES5中新增接收ISO 8061格式字符串,其实内部就是调用 Date.parse({String} datetime) 进行转换。

   4.  Date.prototype.toJSON() :返回当前Date类型对象0时区的ISO 8061日期时间格式字符串。形如:2014-12-12T00:00:00.000Z。

 

三、认识ES3下的Date类型

   1. 作为构造函数使用

/**  * 第一种入参模式:无入参,实例化当前日期时间的Date对象  */var date1 = new Date(); /**  * 第二种入参模式:短日期格式字符串入参,实例化当前时区日期时间的Date对象  */var date2 = new Date('2014/12/3'); /**  * 第三种入参模式:长日期格式字符串入参,实例化当前时区日期时间的Date对象  */var date3 = new Date('Aug 3, 2014');/**  * 第四种入参模式:GMT日期格式字符串入参,实例化指定时区日期时间的Date对象  */var date4 = new Date('Tue May 25 2014 00:00:00 GMT +0800');/**  * 第五种入参模式:GMT日期格式字符串入参,实例化0时区日期时间的Date对象  */var date5 = new Date('Tue May 25 2014 00:00:00 GMT');/**  * 第六种入参模式:入参依次为年、月、日、时、分、秒和毫秒的数值(其中仅年和月为必填项,日默认值为1,其他默认值为0),实例化当前时区日期时间的Date对象  */var date6 = new Date(2014,12,2,1,1,1,1);

   2. 作为函数使用

// 无论入参是什么,总返回当前时区的GMT日期时间格式的字符串var dateStr = Date();

   3. 类成员

     3.1.  Date.parse({String} datetime) :接收GMT的日期时间格式字符串(根据GMT格式内容被识别为0时区或其他时区的日期时间),返回入参所表示的0时区日期时间距离1970年1月1日的毫秒数

     3.2.  Date.UTC(Y,M,d,H,m,s,ms) :设置0时区的日期时间,返回入参所表示的0时区日期时间距离1970年1月1日的毫秒数

   4. 部分实例成员

  4.1.  Date.prototype.toGMTString() :返回当前Date对象的GMT日期时间格式字符串(仅为了向后兼容而已)

  4.2.  Date.prototype.toUTCString() :返回当前Date对象的GMT日期时间格式字符串(建议使用该方法)

 

四、一起Polyfill

if (!Date.prototype.toISOString){        var isLeapYear = function(year){            return (year % 400 === 0) || (year % 4 === 0 && year % 100 !== 0);        };        var operHoursAndMinutes = {};         operHoursAndMinutes['+'] = function(minusHours, minusMinutes, year, month, date, hours, minutes, seconds, milliseconds){            var ret = {};            minutes -= minusMinutes;            hours -= minusHours;            if (minutes < 0){                hours -= 1;                minutes += 60;            }            if (hours < 0 ){                --date;                hours += 24;                if (date < 0){                    --month;                    if (month < 0){                        --year;                        month = 11;                    }                    if (month % 2 === 0){                        date += 31;                        }                    else if (month === 1)                    {                        date += isLeapYear(year) ? 29 : 28;                    }                    else{                        date += 30;                    }                    if (month < 0){                        --year;                        month += 12;                    }                }            }            ret.year = year;            ret.month = month;            ret.date = date;            ret.hours = hours;            ret.minutes = minutes;            ret.seconds = seconds;            ret.milliseconds = milliseconds;            return ret;        };        operHoursAndMinutes['-'] = function(addHours, addMinutes, year, month, date, hours, minutes, seconds, milliseconds){            var ret = {};            minutes += addMinutes;            hours += addHours;            if (minutes >= 60){                hours += 1;                minutes -= 60;            }            if (hours >=24){                ++date;                hours -= 24;                var dateOfCurrMonth = month % 2 === 0 ? 31 : (month === 1 ? (isLeapYear(year) ? 29 : 28) : 30);                if (date >= dateOfCurrMonth){                    ++month;                    date -= dateOfCurrMonth;                    if (month >= 12){                        ++year;                        month -= 12;                    }                }            }            ret.year = year;            ret.month = month;            ret.date = date;            ret.hours = hours;            ret.minutes = minutes;            ret.seconds = seconds;            ret.milliseconds = milliseconds;            return ret;        };        var regExp = new RegExp('^(\\d{4,4})'                + '-((?:0[123456789]|1[012]))'                + '-((?:0[123456789]|[12]\\d|3[01]))'                + 'T'                + '((?:[01]\\d|2[0123]))'                + ':([012345]\\d)'                + ':([012345]\\d)'                + '(?:.(\\d{3}))?'                + '(Z|[+-](?:[01]\\d|2[0123]):?[012345]\\d)$');        var parseISOString2UTC = function(ISOString){            var ret = {};            var year = Number(RegExp.$1)                , month = Number(RegExp.$2) - 1                , date = Number(RegExp.$3)                , hours = Number(RegExp.$4)                , minutes = Number(RegExp.$5)                , seconds = Number(RegExp.$6)                , offset = RegExp.$8                , milliseconds;            milliseconds = (milliseconds = Number(RegExp.$7), !isNaN(milliseconds) && milliseconds || 0);            if (offset === 'Z'){                     ret.year = year;                ret.month = month;                ret.date = date;                ret.hours = hours;                ret.minutes = minutes;                ret.seconds = seconds;                ret.milliseconds = milliseconds;            }             else if (typeof offset !== 'undefined'){                     var symbol = offset.charAt(0);                var offsetHours = Number(offset.substring(1,3));                     var offsetMinutes = Number(offset.substring(offset.length > 5 ? 4 : 3));                ret = operHoursAndMinutes[symbol](offsetHours, offsetMinutes, year, month, date, hours, minutes, seconds, milliseconds);            }            return ret;        };                var _nativeDate = Date;        Date = function(Y,M,D,H,m,s,ms){            var ret, len = arguments.length;            if (!(this instanceof Date)){                ret = _nativeDate.apply(null, arguments);            }            else if (len === 1 && typeof arguments[0] === 'string' && regExp.test(arguments[0])){                var tmpRet;                try{                    tmpRet = parseISOString2UTC();                }                catch(e){                    console && console.log('Invalid Date');                    return void 0;                }                ret = new _nativeDate(_nativeDate.UTC(tmpRet.year, tmpRet.month, tmpRet.date, tmpRet.hours, tmpRet.minutes, tmpRet.seconds, tmpRet.milliseconds));            }            else if (typeof arguments[0] === 'string'){                ret = new _nativeDate(arguments[0]);            }            else{                ret = len >= 7 ? new _nativeDate(Y, M, D, H, m, s, ms)                    : len >= 6 ? new _nativeDate(Y, M, D, H, m, s)                    : len >= 5 ? new _nativeDate(Y, M, D, H, m)                    : len >= 4 ? new _nativeDate(Y, M, D, H)                    : len >= 3 ? new _nativeDate(Y, M, D)                    : len >= 2 ? new _nativeDate(Y, M)                    : len >= 1 ? new _nativeDate(Y)                    : new _nativeDate();            }            return ret;        };        Date.prototype = _nativeDate.prototype;        Date.prototype.constructor = Date;        var _pad = function(num){            if (num < 10){                return '0' + num;            }            return num;        };        var _padMillisecond = function(num){            if (num < 10){                return '00' + num;            }            else if (num < 100){                return '0' + num;            }            return num;        };        Date.prototype.toISOString = function(){                return [this.getUTCFullYear(), '-', _pad(this.getUTCMonth() + 1), '-', _pad(this.getUTCDate()), 'T'                    , _pad(this.getUTCHours()), ':', _pad(this.getUTCMinutes()), ':', _pad(this.getUTCSeconds()), '.', _padMillisecond(this.getUTCMilliseconds()), 'Z'].join('');                };        // 复制可枚举的类成员        for (var clsProp in _nativeDate){            if (_nativeDate.hasOwnProperty(clsProp)){                Date[clsProp] = _nativeDate[clsProp];            }        }        // 复制不可枚举的类成员        var innumerableMems = ['UTC'];        for (var i = 0, clsProp; clsProp = innumerableMems[i++];){            Date[clsProp] = _nativeDate[clsProp];        }        Date.parse = function(str){            if (['string', 'number'].indexOf(typeof str) === -1) return NaN;                        var isMatch = regExp.test(str), milliseconds = 0;            if (!isMatch) return _nativeDate.parse(str);            var tmpRet = parseISOString2UTC();            return _nativeDate.UTC(tmpRet.year, tmpRet.month, tmpRet.date, tmpRet.hours, tmpRet.minutes, tmpRet.seconds, tmpRet.milliseconds);        };        Date.now = Date.now             || function(){                return +new this();            };    }

 

五、总结

  上述实现相对es5-shim来讲考虑的地方仍有欠缺,这源于我对日期时间格式的理解不够完整,因此请大家多多见谅。

 

原创文章,转载请注明来自^_^肥仔John[]

本文地址: (本篇完)

如果您觉得本文的内容有趣就扫一下吧!捐赠互勉!

本文转自^_^肥仔John博客园博客,原文链接:http://www.cnblogs.com/fsjohnhuang/p/3731251.html,如需转载请自行联系原作者

你可能感兴趣的文章
react性能优化
查看>>
关于如何在部署环境修改process.env & 本地测试
查看>>
使用 js 修饰器封装 axios
查看>>
使用JPA + Eclipselink操作PostgreSQL数据库
查看>>
QuickBI助你成为分析师——数据源FAQ小结
查看>>
Git的基本使用
查看>>
[机器学习][异常检测算法]
查看>>
https是如何加密的 (知道了原理之后,希望自己能用代码实现一下,还有用于对个人信息和公钥进行加密的哈希算法,有时间也去查一下)...
查看>>
晋大科技完成2亿元B轮融资,持续投入研发及量产
查看>>
DRF-权限源码流程和基本使用
查看>>
深入浅出浏览器渲染原理
查看>>
科学家发现4起黑洞相撞事件,其中最大的一起或为“双重”碰撞
查看>>
WPF程序中的弱事件模式
查看>>
Android开发 - 掌握ConstraintLayout(六)链条(Chains)
查看>>
java基本数据类型
查看>>
BAT自动驾驶:大致相同的生态链,截然不同的生意经
查看>>
WPF Touch操作滚动条,Window弹跳
查看>>
java源码-vector
查看>>
Android 获取系统信息
查看>>
如何持续写文章?
查看>>