背景:

JS 有自己的 时间类型 Date  —— 但是,在某些情况下 这个对象似乎 不太好用。

本文 基于 JQuery 扩展了一些  JS日期函数,包括:

> 字符串 转 Date 对象 万能函数(性能仅 10W次/s,函数有路径优化,字符串越诡异 耗时越长)

> Date 转 字符串 格式化

> 两个 Date 的差值 (返回的结果类似 C# TimeSpan 对象)

一言不合,直接上代码:

 /*感谢 InkFx (C) http://www.ink-fx.com 为 以下日期函数 作出的努力 */
jQuery = window.jQuery || { }; (function($) { /*--数据类型转换函数 Start----------------------------------*/ $.isArray = function(obj) {var result = false;try {result = Object.prototype.toString.apply(obj) === '[object Array]';if (result) return true;} catch(e) {}try {result = obj.constructor === Array;if (result) return true;} catch(e) {}return false;};
$.toInt = function(obj, dft) {try {dft = (typeof dft === 'number') ? dft : 0;} catch(e) {dft = 0;}try {if (obj == null) return dft;if (typeof obj === 'number') return parseInt(obj);var match = obj.toString().toLowerCase().match(/-*[0123456789abcdefx.]+/);var str = match == null || match.length <= 0 ? null : match[0];var result = null;if (str != null && str.length >= 2 && str.substr(0, 2) == "0x") {str = str.substr(2);result = parseInt(str, 16);} else {result = parseInt(str);}if (result == null || !isFinite(result)) return dft;return result;} catch(e) {return dft;}};
$.toFloat = function(obj, dft) {try {dft = (typeof dft === 'number') ? dft : 0;} catch(e) {dft = 0;}try {if (obj == null) return dft;if (typeof obj === 'number') return parseFloat(obj);var match = obj.toString().toLowerCase().match(/-*[0123456789abcdefx.]+/);var str = match == null || match.length <= 0 ? null : match[0];var result = null;if (str != null && str.length >= 2 && str.substr(0, 2) == "0x") {str = str.substr(2);result = parseFloat(parseInt(str, 16));} else {result = parseFloat(str);}if (result == null || !isFinite(result)) return dft;return result;} catch(e) {return dft;}};
$.toString = function(obj, dft) {try {dft = (typeof dft === 'string') ? dft : '';} catch(e) {dft = '';}try {if (obj == null) return dft;if (typeof obj === 'string') return obj;return obj.toString();} catch(e) {return dft;}};
$.toDateTime = function(obj, dft) {try {dft = (dft instanceof Date) ? dft : new Date(1900, 00, 01);} catch(e) {dft = new Date(1900, 00, 01);}try {if (obj == null) return dft;if (obj instanceof Date) return obj;var result = parseDate(obj);if (result == null) return dft;return result;} catch(e) {return dft;}};
$.toBoolean = function(obj, dft) {try {dft = (typeof dft === 'boolean') ? dft : false;} catch(e) {dft = false;}try {if (obj == null) return dft;if (obj == true) return true;if (obj == false) return false;if ($.isArray(obj)) return obj.length >= 1;if (typeof obj === 'boolean') return obj.toString().toLowerCase() == "true";if (typeof obj === 'number') return parseFloat(obj) > 0;/*if (typeof obj === 'string') return parseFloat(obj) > 0;*/if (obj.toString().toLowerCase() == "t") return true;if (obj.toString().toLowerCase() == "true") return true;return false;} catch(e) {return dft;}}; /*--数据类型转换函数 End------------------------------------*/ /*--时间相关函数 Start--------------------------------------*/ $.formatDate = function(date, fmt) {try {date = $.toDateTime(date);fmt = fmt || "yyyy-MM-dd HH:mm:ss"; o = {"M+": date.getMonth() + 1,"d+": date.getDate(),"H+": date.getHours(),"h+": date.getHours() /*(date.getHours() > 12 ? (date.getHours() - 12) : date.getHours())*/,"m+": date.getMinutes(),"s+": date.getSeconds(),"q+": Math.floor((date.getMonth() + 3) / 3),"S": date.getMilliseconds(),"f+": date.getMilliseconds()};if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));for (var k in o)if (new RegExp("(" + k + ")").test(fmt)) {var padLeft = (k == "S" || k == "f+") ? "000" : "00";fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : (padLeft + o[k]).substr(("" + o[k]).length));}return fmt;} catch(e) { return ""; }};
$.isLeapYearDate = function(date) {try {date = $.toDateTime(date);return (0 == date.getFullYear() % 4 && ((date.getFullYear() % 100 != 0) || (date.getFullYear() % 400 == 0)));} catch(e) {return false;}}; $.addYears = function(date, num) {try {date = $.toDateTime(date);num = $.toInt(num);var year = date.getFullYear();var month = date.getMonth();var day = date.getDate();var hour = date.getHours();var minute = date.getMinutes();var second = date.getSeconds();var millisecond = date.getMilliseconds();var result = new Date(year + num, month, day, hour, minute, second, millisecond);return result;} catch(e) { return new Date(1900, 01, 01); }};
$.addMonths = function(date, num) {try {date = $.toDateTime(date);num = $.toInt(num);var year = date.getFullYear();var month = date.getMonth();var day = date.getDate();var hour = date.getHours();var minute = date.getMinutes();var second = date.getSeconds();var millisecond = date.getMilliseconds();var addYear = (num + month) / 12;month = (num + month) % 12;var result = new Date(year + addYear, month, day, hour, minute, second, millisecond);return result;} catch(e) { return new Date(1900, 01, 01); }};
$.addDays = function(date, num) {try {date = $.toDateTime(date);num = $.toInt(num);var result = new Date(date.valueOf() + (num * 1000 * 60 * 60 * 24));return result;} catch(e) { return new Date(1900, 01, 01); }};
$.addHours = function(date, num) {try {date = $.toDateTime(date);num = $.toInt(num);var result = new Date(date.valueOf() + (num * 1000 * 60 * 60));return result;} catch(e) { return new Date(1900, 01, 01); }};
$.addMinutes = function(date, num) {try {date = $.toDateTime(date);num = $.toInt(num);var result = new Date(date.valueOf() + (num * 1000 * 60));return result;} catch(e) { return new Date(1900, 01, 01); }};
$.addSeconds = function(date, num) {try {date = $.toDateTime(date);num = $.toInt(num);var result = new Date(date.valueOf() + (num * 1000));return result;} catch(e) { return new Date(1900, 01, 01); }};
$.addMilliseconds = function(date, num) {try {date = $.toDateTime(date);num = $.toInt(num);var result = new Date(date.valueOf() + num);return result;} catch(e) { return new Date(1900, 01, 01); }};
$.getTimeSpan = function(date1, date2) {var timestamp = 0;if((date1 instanceof Date || date2 instanceof Date || date2 == null) || (date1 != null && date2 != null)) {date1 = $.toDateTime(date1);date2 = $.toDateTime(date2);timestamp = $.toFloat(date1 - date2);} else {timestamp = $.toInt(date1);}var temp = $.toInt(timestamp / 1000);var totalMilliSecond = timestamp;var totalSecond = timestamp / (1000);var totalMinute = timestamp / (1000 * 60);var totalHour = timestamp / (1000 * 60 * 60);var totalDay = timestamp / (1000 * 60 * 60 * 24);var milliSecond = $.toInt(totalMilliSecond) % 1000;var second = $.toInt(totalSecond) % 60;var minute = $.toInt(totalMinute) % 60;var hour = $.toInt(totalHour) % 24;var day = $.toInt(totalDay);return {TimeStamp: timestamp,Days: day,Hours: hour,Minutes: minute,Seconds: second,Milliseconds: milliSecond,TotalDays: totalDay,TotalHours: totalHour,TotalMinutes: totalMinute,TotalSeconds: totalSecond,TotalMilliseconds: totalMilliSecond,valueOf: function() { return this.TimeStamp; },toString: function() { return this.Days + "." + $.padLeft(this.Hours, 2, "0") + ":" + $.padLeft(this.Minutes, 2, "0") + ":" + $.padLeft(this.Seconds, 2, "0") + "." + $.padLeft(this.Milliseconds, 3, "0"); } };} /*--时间相关函数 End----------------------------------------*/ })(jQuery);

代码比较长,当时我写完之后,顺手就把 JS压缩了。

代码调用如下:

            var begin = new Date();

            //执行15W次 自动识别转换:

            //i3 CPU
//Chrome: 5秒 平均: 30000次/s
//IE 9 : 26秒 平均: 5770次/s
//i5 CPU
//Chrome: 14秒 20*100000次 平均: 107000次/s
for (var i = 0; i < 10000; i++) {
var result1 = $.toDateTime("2017-03-19 01:43:15 123453");
var result2 = $.toDateTime("2017-03-19T01:43:15 123453");
var result3 = $.toDateTime("2017-03-19");
var result4 = $.toDateTime("2017/03/19 01:43:15");
var result5 = $.toDateTime("03/19/2017 01:43:15");
var result6 = $.toDateTime("03/19/2017 01:43");
var result7 = $.toDateTime("01:43:15 123453");
var result8 = $.toDateTime("01:43:15.123453");
var result9 = $.toDateTime("01:43:15");
var result10 = $.toDateTime("01:43");
var result11 = $.toDateTime("2017/03/19");
var result12 = $.toDateTime("03/19/2017");
var result13 = $.toDateTime("Mon Mar 20 2017 02:46:06 GMT+0800 (中国标准时间)");
var result14 = $.toDateTime("Mon Mar 20 02:46:06 UTC+0800 2017");
var result15 = $.toDateTime("Mon Mar 20 2017 02:46:06");
var result16 = $.toDateTime("2017年3月19日 01时43分15秒");
var result17 = $.toDateTime("2017年03月19日01:43:15");
var result18 = $.toDateTime("2017年03月19日 01:43");
var result19 = $.toDateTime("2017年03月19日");
var result20 = $.toDateTime("1时43分15秒");
} var end = new Date();
document.writeln(
"计算 " + (i) + "*20次, 耗时:"
+ "<br/>" + begin.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/>" + end.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/>" + "计算结果: "
+ "<br/> $.toDateTime(\"2017-03-19 01:43:15 123453\") >> " + result1.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"2017-03-19T01:43:15 123453\") >> " + result2.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"2017-03-19\") >> " + result3.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"2017/03/19 01:43:15\") >> " + result4.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"03/19/2017 01:43:15\") >> " + result5.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"03/19/2017 01:43\") >> " + result6.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"01:43:15 123453\") >> " + result7.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"01:43:15.123453\") >> " + result8.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"01:43:15\") >> " + result9.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"01:43\") >> " + result10.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"2017/03/19\") >> " + result11.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"03/19/2017\") >> " + result12.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"Mon Mar 20 2017 02:46:06 GMT+0800 (中国标准时间)\") >> " + result13.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"Mon Mar 20 02:46:06 UTC+0800 2017\") >> " + result14.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"Mon Mar 20 2017 02:46:06\") >> " + result15.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"2017年3月19日 01时43分15秒\") >> " + result16.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"2017年03月19日01:43:15\") >> " + result17.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"2017年03月19日 01:43\") >> " + result18.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"2017年03月19日\") >> " + result19.format("yyyy-MM-dd HH:mm:ss fff")
+ "<br/> $.toDateTime(\"1时43分15秒\") >> " + result20.format("yyyy-MM-dd HH:mm:ss fff")
);

上面的代码中:

 "Mon Mar 20 2017 02:46:06 GMT+0800 (中国标准时间)"
"Mon Mar 20 02:46:06 UTC+0800 2017"
"Mon Mar 20 2017 02:46:06" 这三种,分别是 Chrome FireFox IE 的 Date 对象 toString() 的结果。
万能函数 也已经进行了反向解析支持。

PS.
看客不禁哈哈大笑:“除非有BUG,否则这种 Date.toString() 的字符串 根本就不该出现在程序中。”

如果您觉得 这三种 字符串类型 不会出现。
—— 那我们看看 大名鼎鼎的 element-ui 库中,DatePicker 控件 是如何 闹心的:

http://element-cn.eleme.io/1.4/#/zh-CN/component/date-picker

http://element-cn.eleme.io/2.4/#/zh-CN/component/date-picker (新版已经修正了BUG)

我们再来看看 各位网友是如何踩坑的:

https://www.cnblogs.com/Mrrabbit/p/7716552.html

https://blog.csdn.net/fabulous1111/article/details/79566624

https://blog.csdn.net/lyz571029230/article/details/77987835

—— 无一例外:控件的值 不能直接获取,只能通过 change 事件取值。

如何获取时间差:

 var timeSpan = $.getTimeSpan("2017-03-27 21:20:05 000", "2017-03-25 10:10:10 000");
alert(timeSpan); //日期比较 是可以直接使用 > < 的
alert(timeSpan.TotalDays); //两个时间相差的天数(有小数,比如 1.5天)
alert(timeSpan.TotalHours); //两个时间相差的小时数(有小数)
alert(timeSpan.TotalMinutes); //两个时间相差的分钟数(有小数)
alert(timeSpan.TotalSeconds); //两个时间相差的秒数(有小数)
alert(timeSpan.TotalMilliseconds); //两个时间相差的毫秒数(有小数) alert($.addYears("2017-03-27 21:20:05 123456", 5)); //在指定时间基础上,增加 5 年
alert($.addMonths("2017-03-27 21:20:05 123456", 48)); //在指定时间基础上,增加 48 月
alert($.addDays("2017-03-27 21:20:05 123456", 365)); //在指定时间基础上,增加 365 天
alert($.addHours("2017-03-27 21:20:05 123456", 48)); //在指定时间基础上,增加 48 消失
alert($.addMinutes("2017-03-27 21:20:05 123456", 120)); //在指定时间基础上,增加 120分钟
alert($.addSeconds("2017-03-27 21:20:05 123456", 480)); //在指定时间基础上,增加 480秒
alert($.addMilliseconds("2017-03-27 21:20:05 123456", 10300)); //在指定时间基础上,增加 10300毫秒

是的, JS 的 Date 对象, 好多你需要但是 底层不提供的 函数 —— 本文 都已经提供。

本文源码,完全开源,才用 MIT 开源协议 —— 源码可以用于 个人、商业,可以修改、添加、删除,仅仅需要保留 作者的著作声明。

源码早在2017年完成,这次项目需要用到 TypeScript —— 于是,就将 之前的部分 底层Js代码,进行了移植。

今天顺带踩了一下 element-ui 的坑,发文纪念一下 ~

InkFx

2018-08-16

『开源』扩展 JS 的 Date 处理函数的更多相关文章

  1. 『开源』Slithice 2013 服务器集群 设计和源码

    相关介绍文章: <『设计』Slithice 分布式架构设计-支持一体式开发,分布式发布> <『集群』001 Slithice 服务器集群 概述> <『集群』002 Sli ...

  2. javascript得知 - js的Date对象函数

    js的Date功能很强大.通常使用. 首先获得当前的日期: var CurDate = new Date(); var Year = CurDate.getFullYear(); //年份(四位 例: ...

  3. 『开源』仿SQLServer山寨一个 跨数据库客户端

    002 Laura.SqlForever项目简单介绍 相关文章 <『练手』001 Laura.SqlForever架构基础(Laura.XtraFramework 的变迁)> <『练 ...

  4. 『开源』设置系统 主音量(0~100 静音) VolumeHelper 兼容 Xp Win7 .Net 20 AnyCPU

    背景: 近来的生活一团乱麻,没心态写高大上的代码,于是就着手 写了几个 辅助类. 在整理 InkFx.Utils 时,发现有几个 辅助类 只写了定义,没有实现函数体,于是就 花了1天时间 完善了一下. ...

  5. JS日期(Date)处理函数总结

    获取日期 1.Date() ——返回当日的日期和时间. 2.getDate() ——从 Date 对象返回一个月中的某一天 (1 ~ 31). 3.getDay() ——从 Date 对象返回一周中的 ...

  6. 『Python』matplotlib划分画布的主要函数

    1. subplot() 绘制网格区域中几何形状相同的子区布局 函数签名有两种: subplot(numRows, numCols, plotNum) subplot(CRN) 都是整数,意思是将画布 ...

  7. 『设计』Laura.Compute 设计思路

    前言: 前一篇文章 <『开源』也顺手写一个 科学计算器:重磅开源> ,继 Laura.Compute 算法开源之后,有 博客园 园友 希望公开一下 Laura.Compute算法 的 设计 ...

  8. 『TensorFlow』SSD源码学习_其一:论文及开源项目文档介绍

    一.论文介绍 读论文系列:Object Detection ECCV2016 SSD 一句话概括:SSD就是关于类别的多尺度RPN网络 基本思路: 基础网络后接多层feature map 多层feat ...

  9. JS 中通过对象关联实现『继承』

    JS 中继承其实是种委托,而不是传统面向对象中的复制父类到子类,只是通过原型链将要做的事委托给父类. 下面介绍通过对象关联来实现『继承』的方法: Foo = { // 需要提供一个 init 方法来初 ...

随机推荐

  1. HTML DOM innerHTML 属性及实现图片连续播放

    定义和用法 innerHTML 属性设置或返回表格行的开始和结束标签之间的 HTML. 语法 tablerowObject.innerHTML=HTML 实例 下面的例子返回了表格行的 inner H ...

  2. Java结合SpringBoot拦截器实现简单的登录认证模块

    Java结合SpringBoot拦截器实现简单的登录认证模块 之前在做项目时需要实现一个简单的登录认证的功能,就寻思着使用Spring Boot的拦截器来实现,在此记录一下我的整个实现过程,源码见文章 ...

  3. ELK 架构之 Elasticsearch 和 Kibana 安装配置

    阅读目录: 1. ELK Stack 简介 2. 环境准备 3. 安装 Elasticsearch 4. 安装 Kibana 5. Kibana 使用 6. Elasticsearch 命令 最近在开 ...

  4. AtomicInteger类的使用

    AtomicInteger介绍 AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减. AtomicInteger使用场景 AtomicInteger提供原子操作 ...

  5. cmd命令行下登陆备份导入导出msql数据

    1.进入服务,找到mysql服务,在属性里找到mysql的安装路径 2.登陆  mysql -h 192.168.0.11 -P 3310 -u root -p 如果是访问的本机并且端口是默认的,那么 ...

  6. HBuilder 插件开发(openinstall 集成)

    离线打包 如果要集成使用非基座包下的第三方 SDK,就必须使用离线打包.可以参考 官方文档 进行离线打包,如果嫌官方文档看不懂,可以查看 其他技术人员的教程 开发插件 编写 Android 原生代码 ...

  7. Oracle-13:Oracle中的表分区

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客记录了表分区 表分区的含义: 典型的拿空间换时间的案例! 表分区对一张表进行分区,分区之后表中的数据存 ...

  8. Yii 1.1 请求报400错误

    Yii的action可以带参数,比如: class PostController extends CController { public function actionCreate($categor ...

  9. Embedded servlet containers

    73. Embedded servlet containers 73.1 Add a Servlet, Filter or Listener to an application There are t ...

  10. error: src refspec XXX matches more than one

    error: dst refspec v1. matches more than one. error: failed to push some refs to '' 错误原因是 branch名和ta ...