js日期转换工具类(仿oracle to_char,to_date等语法)

摘要

js字符串转日期,js日期转字符串。

更新日志

2018/08/21

  • 在字符串转日期中,修改“日”的默认值为1.
  • 可以识别单数字的“日”,”月“。比如 1-9-2018可以直接这样转换NayiUtil.to_date("1-9-2015", "dd-mm-yyyy")

2018/12/04

  • 添加add_days、add_months、add_years三个函数

2019/02/01

  • 修复to_date方法中的bug,例NayiUtil.to_date('20190131 12:13:14', 'yyyymmdd hh24:mi:ss');NayiUtil.to_date('20190131 2:13:14', 'yyyymmdd hh24:mi:ss');在之前会返回错误结果
  • 添加add_months_plus方法,转换原则为

If date is the last day of the month or if the resulting month has fewer days than the day component of date, then the result is the last day of the resulting month. Otherwise, the result has the same day component as date.

2019/04/04

  • 继续修复hh12与hh24的bug。。。
  • 添加last_day方法(传入日期类型,获取当月的最后一天)例:document.write(NayiUtil.last_day(new Date()));
  • 添加last_month_day方法(传入日期类型,获取当月最后一天的日期字符串,两位的,比如31,28,31)例:document.write(NayiUtil.last_month_day(new Date()));
  • 添加months_between方法(三个参数,前两个为需要比较的日期类型,后一个为标识,1时不考虑dd,只做月份加减,永远返回整数;0或者默认时,安下述规则计算)例document.write(NayiUtil.months_between(NayiUtil.to_date("20190228", "yyyymmdd"), NayiUtil.to_date("20190127", "yyyymmdd"), 0));

If date1 and date2 are either the same days of the month or both last days of months, then the result is always an integer. Otherwise Oracle Database calculates the fractional portion of the result based on a 31-day month and considers the difference in time components date1 and date2.

背景

一般来说,应该是要尽量避免在js中做时间操作的,它可能会导致很奇葩的bug产生。但是有时候又确实需要这么做。这个时候就会被蹩脚的语法恶心一脸。为了避免再次发生这种情况,我写了一个时间操作的工具类,在此分享。

我个人比较喜欢oracle中的to_char与to_date函数,所以具体的使用方法与在oracle中是一样的。虽然只实现了最基本的用法,不过熟悉oracle的朋友可以直接把文章最后的代码粘过来用。不熟悉的往下看用法。

用法

to_char

用法示例
NayiUtil.to_char(new Date(2018,0,31,12,30,40), "yyyymmdd");
返回20180130

NayiUtil.to_char(new Date(2018,0,31,12,30,40), "yyyy-mm-dd");
返回2018-01-30

NayiUtil.to_char(new Date(2018,0,31,12,30,40), "y,yyy-yyyy-yyy-yy-y-mm-dd hh12:hh24:mi:ss**sssss***q 季度:qcn 星期d__dc_day");
返回 2,018-2018-018-18-8-01-31 00:12:30:40**45040***1 季度:第一季度 星期3__3_星期三

NayiUtil.to_char(new Date(2018,0,31,12,30,40), "Aa(YyYy)yyyy");
返回aaYyYy2018

NayiUtil.to_char(new Date(2018,0,31,12,30,40), "Aa\\(YyYy\\)yyyy\\\\");
返回aa(2018)2018\

NayiUtil.to_char(new Date(2018,0,31,12,30,40), "fmmm");
返回1

基本凭感觉用就对了,我只解释几点

  • 格式化参数会自动转为小写,除非写在圆括号中。
  • 圆括号中的字符会直接原样输出,其他没有匹配上的字符会小写格式输出。
  • \是转义符号。只有两个作用,输出圆括号和他自己。
  • 优先最长匹配规则。比如ddd 会解析为dd+d,而不会是d+dd或d+d+d。
  • fm,去除多余的前导零。

####to_date
未进行匹配的部分会默认为当前时间

可以匹配的字符(很少用到的没写)
yyyy mm dd hh24 hh mi ss

用法示例
NayiUtil.to_char(NayiUtil.to_date("01-2015-15", "mm-yyyy-dd"), 'yyyy-mm-dd hh24:mi:ss')
返回2015-01-15 19:36:03

NayiUtil.to_char(NayiUtil.to_date("01-aaaaaa2015", "mm-nayinayyyy"), 'yyyy-mm-dd hh24:mi:ss')
返回2015-01-29 19:37:58

解释
不需要匹配的部分可以用任意无关字符占位。

完整代码


<html>
    <head>
        <meta charset="UTF-8">
        <title>title>
        <script type="text/javascript">

var NayiUtil = function(){

    var fill_zreo = function(str, length){
        str = str.toString();
        var l = str.length;
        if (str.length >= length) {return str;}

        for(var i = 0; i < length - l; i++){
            str = "0" + str;  
        }
        return str; 
    }


    var to_char = function(dateObj, fmtSrc) {

        if(!(dateObj instanceof Date)){
            return "now, only Datetype is supported";
        }

        if(!dateObj || !fmtSrc){
            return dateObj || "null";
        }

        var fmtModel = "";
        var result = "";

        var init = function(){
            var res = "";
            var inner_flag = false;

            for(var i = 0; i < fmtSrc.length; i++){

                if(fmtSrc.charAt(i) == "\\"){
                    res += fmtSrc.charAt(i) + fmtSrc.charAt(i + 1);
                    i += 1;
                    continue;
                }

                if(fmtSrc.charAt(i) == "("){
                    inner_flag = true;
                }

                res += inner_flag ? fmtSrc.charAt(i) : fmtSrc.charAt(i).toLowerCase();

                if(fmtSrc.charAt(i) == ")"){
                    inner_flag = false;
                }
            }

            fmtSrc = res;
            fmtModel = fmtSrc.match(/fm/g);
            fmtSrc = fmtSrc.replace(/fm/g, "");

        }

        init();

        var validFmt = {
            "yyyy": function() {
                if(fmtModel == "fm"){
                    return dateObj.getFullYear();
                }else {
                    return fill_zreo(dateObj.getFullYear(), 4);
                }
            },
            "mm": function() {

                if(fmtModel == "fm"){
                    return dateObj.getMonth() + 1;
                }else {
                    return fill_zreo(dateObj.getMonth() + 1, 2);
                }
            },
            "dd": function(){
                if(fmtModel == "fm"){
                    return dateObj.getDate();
                }else {
                    return fill_zreo(dateObj.getDate(), 2);
                }
            },
            "yyy": function(){
                if(fmtModel == "fm"){
                    return dateObj.getFullYear().toString().substr(-3);
                }else {
                    return fill_zreo(dateObj.getFullYear().toString().substr(-3), 3);
                }
            },
            "yy": function(){
                if(fmtModel == "fm"){
                    return dateObj.getFullYear().toString().substr(-2);
                }else {
                    return fill_zreo(dateObj.getFullYear().toString().substr(-2), 1);
                }
            },
            "y": function(){
                if(fmtModel == "fm"){
                    return dateObj.getFullYear().toString().substr(-1);
                }else {
                    return fill_zreo(dateObj.getFullYear().toString().substr(-1), 1);
                }
            },
            "y,yyy": function(){
                var temp = fill_zreo(dateObj.getFullYear(), 4);
                var yResult = temp.substr(0, 1) + "," + temp.substr(1, 3);
                return yResult;
            },
            "hh": function(){
                if(fmtModel == "fm"){
                    return (dateObj.getHours()) % 12;
                }else {
                    return fill_zreo((dateObj.getHours()) % 12, 2);
                }
            },
            "hh12": function(){
                if(fmtModel == "fm"){
                    return (dateObj.getHours()) % 12;
                }else {
                    return fill_zreo((dateObj.getHours()) % 12, 2);
                }
            },
            "hh24": function(){
                if(fmtModel == "fm"){
                    return dateObj.getHours();
                }else {
                    return fill_zreo(dateObj.getHours(), 2);
                }
            },
            "mi": function(){
                if(fmtModel == "fm"){
                    return dateObj.getMinutes();
                }else {
                    return fill_zreo(dateObj.getMinutes(), 2);
                }
            },
            "ss": function(){
                if(fmtModel == "fm"){
                    return dateObj.getSeconds();
                }else {
                    return fill_zreo(dateObj.getSeconds(), 2);
                }
            },
            "sssss": function(){
                return dateObj.getSeconds() + dateObj.getHours() * 3600 + dateObj.getMinutes() * 60;
            },
            "ff": function(){
                return dateObj.getMilliseconds();
            },
            "d": function(){
                return fill_zreo(dateObj.getDay(), 1);
            },
            "ddd": function(){
                var dateArr = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
                var date = new Date();
                var day = date.getDate();
                var month = date.getMonth(); //getMonth()是从0开始
                var year = date.getFullYear();
                var result = 0;
                for ( var i = 0; i < month; i++) {
                    result += dateArr[i];
                }
                result += day;
                if (month > 1 && (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
                    result += 1;
                }
                return result;
            },
            "dc": function(){
                return fill_zreo(dateObj.getDay() == 0 ? 7 : dateObj.getDay(), 1);  //中文星期数字(js是0-6,0是星期日)
            },
            "day": function(){
                var arr = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
                return arr[dateObj.getDay()];
            },
            "q": function(){
                var arr = ["1", "1", "1", "1", 
                            "2", "2", "2", "2", 
                            "3", "3", "3", "3", 
                            "4", "4", "4", "4"]
                return arr[dateObj.getMonth()];
            },
            "qcn": function(){
                var arr = ["第一季度", "第一季度", "第一季度", "第一季度", 
                            "第二季度", "第二季度", "第二季度", "第二季度", 
                            "第三季度", "第三季度", "第三季度", "第三季度", 
                            "第四季度", "第四季度", "第四季度", "第四季度"];
                return arr[dateObj.getMonth()];
            }

        }



        var temp = "";
        var bracket_num = 0;
        for(var i = 0; i < fmtSrc.length; ){
            if(fmtSrc.charAt(i) == "("){
                bracket_num++;
                i++;
                continue;
            }
            if(fmtSrc.charAt(i) == ")" && bracket_num > 0){
                bracket_num--;
                i++;
                continue;
            }
            if(fmtSrc.charAt(i) == "\\"){
                result += fmtSrc.charAt(i + 1);
                i += 2;
                continue;
            }
            if(bracket_num > 0){
                result += fmtSrc.charAt(i);
                i++;
                continue;
            }

            var maxLength = 0;
            var j = i + 1;
            for(; j <= fmtSrc.length; j++){
                if(validFmt[fmtSrc.substr(i, j - i)]){
                    maxLength = j - i;
                }
            }
            if(maxLength){
                result += validFmt[fmtSrc.substr(i, maxLength)]();
            }else {
                result += fmtSrc.charAt(i);
            }
            i += maxLength || 1;
        }

        return result;

    }   

    var to_date = function(dateStr, fmt){

        var dateStr_bk = dateStr;

        var init = function(){
            fmt = fmt.toLowerCase();
        }()

        var default_date = new Date();

        var year = default_date.getFullYear();
        var month = default_date.getMonth();
        //var day = default_date.getDate();
		var day = 1;
        var hour = default_date.getHours();
        var minute = default_date.getMinutes();
        var second = default_date.getSeconds();;

        var validFmt = {
            "yyyy": function(str, s_index, length){
				var temp = str.substr(s_index, length);
				year = temp.match(/^[0-9]+/g)[0];
                return temp.length - year.length;
            },
            "mm": function(str, s_index, length){
				var temp = str.substr(s_index, length);
				month = temp.match(/^[0-9]+/g)[0] - 1;
                return temp.length - temp.match(/^[0-9]+/g)[0].length;
            },
            "dd": function(str, s_index, length){
				var temp = str.substr(s_index, length);
				day = temp.match(/^[0-9]+/g)[0];
				return temp.length - day.length;
            },
			"hh12": function(str, s_index, length){
                //hour = str.substr(s_index, length);
				
				var temp = str.substr(s_index, length);
				hour = temp.match(/^[0-9]+/g)[0] ;
				hour = hour.substr(0, 2);
				var returnLength = temp.length - hour.length;
				hour = parseInt(hour) % 12;
				return returnLength;
            },
            "hh24": function(str, s_index, length){
                //hour = str.substr(s_index, length);
				
				var temp = str.substr(s_index, length);
				hour = temp.match(/^[0-9]+/g)[0];
				hour = hour.substr(0, 2);
				return temp.length - hour.length;
            },
            "hh": function(str, s_index, length){
                //hour = str.substr(s_index, length);
				
				var temp = str.substr(s_index, length);
				hour = temp.match(/^[0-9]+/g)[0];
				return temp.length - hour.length;
            },
            "mi": function(str, s_index, length){
                //minute = str.substr(s_index, length);
				
				var temp = str.substr(s_index, length);
				minute = temp.match(/^[0-9]+/g)[0];
				return temp.length - minute.length;
            },
            "ss": function(str, s_index, length){
                //second = str.substr(s_index, length);
				
				var temp = str.substr(s_index, length);
				second = temp.match(/^[0-9]+/g)[0];
				return temp.length - second.length;
            }
        }

        var temp = "";
        var bracket_num = 0;
		var axis = 0;		//主要为处理2018-8-21这种特殊情况(2018-08-21为正常情况)
        for(var i = 0; i < fmt.length; ){
            var maxLength = 0;
            var j = i + 1;
            for(; j <= fmt.length; j++){
                if(validFmt[fmt.substr(i, j - i)]){
                    maxLength = j - i;
                }
            }
            if(maxLength){
                axis += validFmt[fmt.substr(i, maxLength)](dateStr, i - axis, maxLength) || 0;
            }else {
            }
            i += maxLength || 1;
        }
        //alert(year+"_"+ month+"_"+ day+"_"+ hour+"_"+ minute+"_"+ second);
        var resultDate = new Date(year, month, day, hour, minute, second);
        return resultDate;
    }

    var add_days = function(oldDate, addDays){
    	var newDate = new Date(oldDate);
    	return new Date(newDate.setDate(oldDate.getDate() + addDays));
    }
    
    var add_months = function(oldDate, addMonths){
    	var newDate = new Date(oldDate);
    	return new Date(newDate.setMonth(oldDate.getMonth() + addMonths));
    }
    
    var add_years = function(oldDate, addYesrs){
    	var newDate = new Date(oldDate);
    	return new Date(newDate.setFullYear(oldDate.getFullYear() + addYesrs));
    }

	var add_months_plus = function(oldDate, addMonths){
		var dateArr = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
		
		var oldYear = fill_zreo(oldDate.getFullYear(), 4);
		var oldMonth = fill_zreo(oldDate.getMonth(), 2);
		var oldDay = fill_zreo(oldDate.getDate(), 2);
		
		var newYear = parseInt(oldYear) + Math.floor((parseInt(oldMonth) + 1 + parseInt(addMonths)) / 12);
		var newMonth = (parseInt(oldMonth) + 1 + parseInt(addMonths)) % 12;
		var newDay;
		
		var currentLastDay; 
		if((oldMonth == 1) && (oldYear %  400 == 0 || (oldYear % 4 == 0 && oldYear % 100 != 0))){
			currentLastDay = 29;
		}else {
			currentLastDay = dateArr[oldMonth];
		}
		
		if(oldDay == currentLastDay){
			newDay = dateArr[newMonth];
		}else if(oldDay > dateArr[(newMonth - 1) % 12]){
			if(newMonth == 2 && (oldYear %  400 == 0 || (oldYear % 4 == 0 && oldYear % 100 != 0))){
				newDay = 29;
			}else {
				newDay = dateArr[(newMonth - 1) % 12];
			}
		}else{
			newDay = oldDay;
		}
		//alert(to_date("2019-04-30 14:34", 'yyyy-mm-dd hh24:mi'));
		//alert("old : " + oldDay + "__"+newYear+"-"+newMonth+"-"+newDay);
		//alert(""+newYear+"-"+newMonth+"-"+newDay+to_char(oldDate, '-hh24-mi-ss'));
		return to_date(""+newYear+"-"+newMonth+"-"+newDay+" "+to_char(oldDate, 'hh24:mi:ss'), 'yyyy-mm-dd hh24:mi:ss');
	}

    return {
        to_char: to_char,
        to_date: to_date,
        add_days: add_days,
        add_months: add_months,
        add_years: add_years,
        add_months_plus: add_months_plus
    };

}();            

;
                          //"2018","0","31","1","31","13"
//var test = NayiUtil.to_char(new Date(), "yyyy(年)mm月dd(Ri) \\(yyyy-mm-dd\\)  dd-mm-yyyy hh24:mi:ss:ff d dc dcn qcn q ddd sssss y,yyy ---");
//alert(test);
//var ttt = NayiUtil.to_char(new Date(2018,0,31,12,30,40), "fmmm");
//alert(ttt);
//document.write(ttt);
//document.write(NayiUtil.to_char(NayiUtil.to_date("01-2015-15", "mm-yyyy-dd"), 'yyyy-mm-dd hh24:mi:ss'));
//document.write("\r\n  ");
document.write(NayiUtil.to_char(NayiUtil.to_date("1-9-2015", "dd-mm-yyyy"), 'yyyy-mm-dd hh24:mi:ss'));


        script>
    head>
    <body>
    body>

html>

你可能感兴趣的:(js,前端)