自己实现的javascrip中Date对象的工具类,包含以下方法:
- Date对象与字符串的互转方法(可指定格式化字符串,手动解析版);
- 获取指定日期向前推n天(天、月、年)的日期;
/**
* 日期相关操作
*/
function DateUtil(){
// 用于时间字符串转时间对象时的格式化正则表达式
this.dateRegexpMap = new Map();
// 用于时间字符串转时间对象时的格式化正则表达式(不带分割符)
this.dateRegexpNoSplit = new RegExp("(\\d{4})(\\d{2})(\\d{2})([T\\s](\\d{2})(\\d{2})(\\d{2})((\\d{3}))?)?");
// 用于时间字符串转时间对象时的格式化正则表达式(带分割符)
this.dateRegexpSplit = new RegExp("(\\d{4})-(\\d{2})-(\\d{2})([T\\s](\\d{2}):(\\d{2}):(\\d{2})(\\.(\\d{3}))?)?");
// 用于获取时间字符串中指定部分的正则表达式
this.dateGetRegexpMap = new Map();
// ---------------------formatStr-NoSplit---------------------
this.dateRegexpMap.set('yyyyMMdd HHmmss',this.dateRegexpNoSplit);
this.dateRegexpMap.set('yyyyMMdd HHmmssSSS',this.dateRegexpNoSplit);
this.dateRegexpMap.set('yyyyMMdd',this.dateRegexpNoSplit);
this.dateRegexpMap.set('HHmmss',this.dateRegexpNoSplit);
this.dateRegexpMap.set('HHmmssSSS',this.dateRegexpNoSplit);
// ---------------------formatStr-HasSplit----------------------
this.dateRegexpMap.set('yyyy-MM-dd HH:mm:ss',this.dateRegexpSplit);
this.dateRegexpMap.set('yyyy-MM-dd HH:mm:ss.SSS',this.dateRegexpSplit);
this.dateRegexpMap.set('yyyy-MM-dd',this.dateRegexpSplit);
this.dateRegexpMap.set('HH:mm:ss',this.dateRegexpSplit);
this.dateRegexpMap.set('HH:mm:ss.SSS',this.dateRegexpSplit);
// -----------------hasSplit---------------------------
this.dateRegexpMap.set(true,this.dateRegexpSplit);
this.dateRegexpMap.set(false,this.dateRegexpNoSplit);
// -----------------util正则表达式------------------------
this.dateGetRegexpMap.set('HHmmss',new RegExp("^(\\d{2})(\\d{2})(\\d{2})$"));
this.dateGetRegexpMap.set('HHmmssSSS',new RegExp("^(\\d{2})(\\d{2})(\\d{2})(\\d{3})$"));
this.dateGetRegexpMap.set('HH:mm:ss',new RegExp("^(\\d{2}):(\\d{2}):(\\d{2})$"));
this.dateGetRegexpMap.set('HH:mm:ss.SSS',new RegExp("^(\\d{2}):(\\d{2}):(\\d{2})(\\.\\d{3})$"));
this.dateGetRegexpMap.set('DateValidata',new RegExp("^yyyy.*MM.*dd.* ?HH.*mm.*ss$|^yyyy.*MM.*dd.* ?HH.*mm.*ss.*SSS$|^yyyy.*MM.*dd.* ?HH.*mm$|^yyyy.*MM.*dd$|^HH.*mm.*ss$|^HH.*mm.*ss.*SSS$"));
/**
* 获取所有支持的格式化字符串数组
*/
this.getSupportFormatStrs = function () {
// 支持的格式化字符串
var supportFormatStrsArray = new Array();
this.dateRegexpMap.forEach(function(value,key,map){
if (key !== true && key !== false) {
supportFormatStrsArray.push(key);
}
});
return supportFormatStrsArray;
}
/**
* 时间字符串转时间对象(手动解析字符串)
* @param dateString 时间字符串(不为空时必须)
* @param isHasSplit 时间字符串中是否有分隔符(true/false)(dateString不为空时必须)
* @param formatStr 时间格式化字符串(暂时废弃)
* @param isShowLog 是否显示日志(true/false)
* @return 转换后的时间对象(当dateString为空时返回当前时间,当发生异常时返回null)
*/
this.toDateFromStr = function(dateString,isHasSplit,formatStr,isShowLog){
if (dateString == undefined || dateString == null || dateString.length == 0) {
if (isShowLog == true) {
console.log('时间字符串为空,返回当前时间');
}
return new Date();
} else {
// 时间字符串预处理
// 支持【/】分隔符
dateString = dateString.replace(new RegExp( '/' , 'g' ),'-');
// 针对仅有时分秒的时间字符串的预处理
if (dateString.split(' ').length == 1
&& (this.dateGetRegexpMap.get('HHmmss').test(dateString)
|| this.dateGetRegexpMap.get('HHmmssSSS').test(dateString))) {
// 无分隔符
dateString = '00000000 '+dateString;
} else if (dateString.split(' ').length == 1
&& (this.dateGetRegexpMap.get('HH:mm:ss').test(dateString)
|| this.dateGetRegexpMap.get('HH:mm:ss.SSS').test(dateString))) {
// 有分隔符
dateString = '0000-00-00 '+dateString;
}
}
// 根据参数【isHasSplit】、【formatStr】选定的格式化正则表达式
var dateRegexp = (isHasSplit === true || isHasSplit === false) ? this.dateRegexpMap.get(isHasSplit) : this.dateRegexpMap.get(formatStr);
if (isShowLog == true) {
console.log('dateRegexp','|'+dateRegexp+'|');
}
if (dateRegexp == undefined || dateRegexp == null || dateRegexp == '') {
console.error("不支持的格式化字符串【"+formatStr+"】,仅支持以下格式化字符串【"+this.getSupportFormatStrs()+"】"+(isShowLog === true ? '' : ',详细信息请指定参数isShowLog为true以查看日志'));
return null;
}
// 校验时间字符串
if(dateRegexp.test(dateString)){
// 真正被使用的时间字符串
var usedDateString = dateString.match(dateRegexp)[0];
// 仅部分匹配
if (usedDateString != dateString) {
console.error("时间字符串【"+dateString+"】与格式化字符串部分不匹配,此时的有效部分仅为【"+usedDateString+"】"+(isShowLog === true ? '' : ',详细信息请指定参数isShowLog为true以查看日志'));
dateString = usedDateString;
}
var timestamp = dateString.replace(dateRegexp, function($all,$year,$month,$day,$part2,$hour,$minute,$second,$part3,$milliscond){
if (isShowLog == true) {
console.log('$all','|'+$all+'|');
console.log('$year','|'+$year+'|');
console.log('$month','|'+$month+'|');
console.log('$day','|'+$day+'|');
console.log('$part2','|'+$part2+'|');
console.log('$hour','|'+$hour+'|');
console.log('$minute','|'+$minute+'|');
console.log('$second','|'+$second+'|');
console.log('$part3','|'+$part3+'|');
console.log('$milliscond','|'+$milliscond+'|');
}
var date = new Date($year, $month-1,$day, $hour||"00", $minute||"00", $second||"00", $milliscond||"00");
return date.getTime();
});
var date = new Date();
date.setTime(timestamp);
return date;
} else {
console.error("时间字符串【"+dateString+"】与格式化字符串不匹配"+(isHasSplit === true ? ",时间字符串应有分割符" : (isHasSplit === false ? ",时间字符串应无分割符" : "【"+formatStr+"】"))+(isShowLog === true ? "" : ",详细信息请指定参数isShowLog为true以查看日志")+(isHasSplit === true ? ",时间字符串应有分割符" : (isHasSplit === false ? ",时间字符串应无分割符" : "【"+formatStr+"】"))+(isShowLog === true ? "" : ",详细信息请指定参数isShowLog为true以查看日志"));
return null;
}
}
/**
* 将日期对象转成指定格式的字符串
* @param date 日期对象
* @param formatStr 指定的格式的字符串
* @param isShowLog 是否显示日志(true/false)
* @return 转成的指定格式字符串(若formatStr为空或不被支持,则默认【yyyy-MM-dd HH:mm:ss】)
*/
this.toStrFromDate = function (date,formatStr,isShowLog) {
// 参数校验
if (formatStr == undefined || formatStr == null || formatStr.length == 0) {
formatStr = "yyyy-MM-dd HH:mm:ss";
if (isShowLog === true) {
console.log('格式化字符串【'+formatStr+'】为空,设为默认【yyyy-MM-dd HH:mm:ss】');
}
} else if (!this.dateGetRegexpMap.get('DateValidata').test(formatStr)) {
console.error('不支持的格式化字符串【'+formatStr+'】');
if (isShowLog === true) {
console.log('格式化字符串【'+formatStr+'】不被支持,设为默认【yyyy-MM-dd HH:mm:ss】');
}
formatStr = "yyyy-MM-dd HH:mm:ss";
}
// 获取年月日时分秒
var y = date.getFullYear();
var m = date.getMonth() + 1;
m = m < 10 ? ('0' + m) : m;
var d = date.getDate();
d = d < 10 ? ('0' + d) : d;
var h = date.getHours();
h = h < 10 ? ('0' + h) : h;
var minute = date.getMinutes();
minute = minute < 10 ? ('0' + minute) : minute;
var second= date.getSeconds();
second = second < 10 ? ('0' + second) : second;
var ms = date.getMilliseconds();
ms = minute < 10 ? ('0' + ms) : ms;
return formatStr.replace('yyyy',y).replace('MM',m).replace('dd',d).replace('HH',h).replace('mm',minute).replace('ss',second).replace('SSS',ms);
}
/**
* 减去对应的日期
* 例子(获取当前日期向前推3天的日期):Util.subtractDate(new Date(), 'day', 3)
* @param date 要处理的日期对象(Date())
* @param type 要处理的类型(year,month,day)
* @param num 减去的数量
*/
this.subtractDate = function(date,type,num){
var srcDate = new Date(date.getTime());
if (type == 'year') {
date.setFullYear(date.getFullYear() - num);
} else if (type == 'month') {
date.setMonth(date.getMonth() - num);
} else if (type == 'day') {
date.setDate(date.getDate() - num);
}
if (((type == 'year' || type == 'month') && date.getDate() == srcDate.getDate())
|| type == 'day') {
return date;
}
// 原始日期当前月的最大日期 比 处理后当前月的最大日期大(即原始日期处于当前月最大日期)
// 处理后应为2月,实际处理后为3月
if (date.getMonth() == 2) {
// 闰年
if ((date.getFullYear() % 4 == 0) && (date.getFullYear() % 100 != 0 || date.getFullYear() % 400 == 0)){
date.setDate(29);
} else {
date.setDate(28);
}
date.setMonth(1);
// 处理后应为4 6 9 11月,实际处理后为5 7 10 12月
} else if (date.getMonth() == 4 || date.getMonth() == 6 || date.getMonth() == 9 || date.getMonth() == 11) {
date.setDate(30);
date.setMonth(date.getMonth() - 1);
}
return date;
}
/**
* 取得当前月份的第一天
* @param date 要处理的日期对象(Date())
*/
this.getFirstDayInMonth = function(date){
return this.toDateFromStr(dateUtil.toStrFromDate(new Date(),"yyyy-MM-dd HH:mm:ss",false).replace(/-\d{2} /,"-01 "),true);
}
/**
* 取得当前月份的最后一天
* @param date 要处理的日期对象(Date())
*/
this.getLastDayInMonth = function(date){
// 下一个月的当天
var nextMonthDay = dateUtil.subtractDate(date, 'month', -1);
return this.subtractDate(dateUtil.toDateFromStr(dateUtil.toStrFromDate(nextMonthDay,"yyyy-MM-dd HH:mm:ss",false).replace(/-\d{2} /,"-01 "),true),"day",1);
}
/**
* 取得当前季度的最后一天
* @param date 要处理的日期对象(Date())
*/
this.getLastDayInQuarter = function(date){
var currentMonth = date.getMonth()+1;
if (currentMonth >=1 && currentMonth <=3) {
date.setMonth(2);
} else if (currentMonth >=4 && currentMonth <=6) {
date.setMonth(5);
} else if (currentMonth >=7 && currentMonth <=9) {
date.setMonth(8);
} else if (currentMonth >=10 && currentMonth <=12) {
date.setMonth(11);
}
return this.getLastDayInMonth(date);
}
/**
* 取得当前半年的最后一天
* @param date 要处理的日期对象(Date())
*/
this.getLastDayInHalfYear = function(date){
var currentMonth = date.getMonth()+1;
if (currentMonth >=1 && currentMonth <=6) {
date.setMonth(5);
} else if (currentMonth >=7 && currentMonth <=12) {
date.setMonth(11);
}
return this.getLastDayInMonth(date);
}
/**
* 取得当前年的最后一天
* @param date 要处理的日期对象(Date())
*/
this.getLastDayInYear = function(date){
date.setMonth(11);
return this.getLastDayInMonth(date);
}
/**
* 根据总秒数计算累计 天、时、分、秒
* @param second 总秒数
* @return time (dd:天;hh:时;mm:分;ss:秒;)
*/
this.getSumTimeFromSecond = function(second){
var time = {dd:0,hh:0,mm:0,ss:0};
time.dd = parseInt(second/(60*60*24));
time.hh = CommonUtils_prefixInteger(parseInt(second%(60*60*24)/(60*60)),2);
time.mm = CommonUtils_prefixInteger(parseInt(second%(60*60*24)%(60*60)/60),2);
time.ss = CommonUtils_prefixInteger(parseInt(second%(60*60*24)%(60*60)%60),2);
return time;
}
}