<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        JavaScript自定義日期格式化函數詳細解析_javascript技巧

        來源:懂視網 責編:小采 時間:2020-11-27 21:18:42
        文檔

        JavaScript自定義日期格式化函數詳細解析_javascript技巧

        JavaScript自定義日期格式化函數詳細解析_javascript技巧:我們對 JavaScript 擴展其中一個較常的做法便是對 Date.prototype 的擴展。因為我們知道,Date 類只提供了若干獲取日期元素的方法,如 getDate(),getMinute()……卻沒有一個轉換為特定字符串的格式化方法。故所以,利用這些細微的方法,加以封裝,組合我們想
        推薦度:
        導讀JavaScript自定義日期格式化函數詳細解析_javascript技巧:我們對 JavaScript 擴展其中一個較常的做法便是對 Date.prototype 的擴展。因為我們知道,Date 類只提供了若干獲取日期元素的方法,如 getDate(),getMinute()……卻沒有一個轉換為特定字符串的格式化方法。故所以,利用這些細微的方法,加以封裝,組合我們想

        我們對 JavaScript 擴展其中一個較常的做法便是對 Date.prototype 的擴展。因為我們知道,Date 類只提供了若干獲取日期元素的方法,如 getDate(),getMinute()……卻沒有一個轉換為特定字符串的格式化方法。故所以,利用這些細微的方法,加以封裝,組合我們想要的日期字符串形式。一般來說,該格式化函數可以定義在 Date 對象的原型身上,也可以獨立一個方法寫出。定義原型方法的操作如 Date.prototype.format = function(date){……},使用時候直接 new Date().format(YYYY:MM:DD) 即可,仿佛就是 Date 對象的原生方法。但是定義原型方法卻略嫌有“入侵” JS 原型的不足。設計 API 之時必須考慮這個問題。我的建議是,用戶按照自己的判斷去做決定,只是調用的方式不同,不影響過程的邏輯即可。

        下面的一個例子就是以獨立函數寫出的 JavaScript 日期格式化函數,獨立的 format 函數。回到格式化的這一知識點上,我們考查的是怎么實現的、運用了哪些原理。傳統字符串拼接如 indexOf()+substr() 雖然能夠實現,但明顯不僅效率低下,而且代碼冗長,還是適宜引入正則表達式的方法,先寫出字符串正則然后再進行結果的命中匹配。我們先看看來自 Steven Levithan 的例子:
        代碼如下:
        /**
        * Date Format 1.2.3
        * @credit Steven Levithan Includes enhancements by Scott Trenda and Kris Kowal
        * Accepts a date, a mask, or a date and a mask.
        * Returns a formatted version of the given date.
        * The date defaults to the current date/time.
        * The mask defaults to dateFormat.masks.default.
        */
        dateFormat = (function(){
        // 正則筆記, 1、token,(?:)表示非捕獲分組;/1 反向引用(思考:{1,2}可否和/1一樣意思?);根據這里的意義[LloSZ]表示括號內的任意一個字符拿去匹配,很簡單,但暫時不明白/L|l|o|S|Z/在解析日期時的作用;最后的兩組“或”是匹配引號和引號內的內容(無所謂雙引號或單引號)。
        var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])/1?|[LloSZ]|"[^"]*"|'[^']*'/g,
        // 2、timezone, [PMCEA][SDP]產生兩個字符的消耗;該reg的都是非捕獲分組,可加快正則速度。
        timezone = //b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]/d{4})?)/b/g,
        timezoneClip = /[^-+/dA-Z]/g,

        // 不足兩位填充字符,或可指定位數
        pad = function (val, len){
        val = String(val);
        len = len || 2;
        while (val.length < len) val = "0" + val;
        return val;
        };
        // 為什么返回一個function,因為前面說明的變量都變作常量,下面返回的參數才是真正到時執行的函數。這一點透過閉包的寫法來實現。如英文注釋說的,可以提速。
        // Regexes and supporting functions are cached through closure
        // 參數說明:date: Date 被解析的日期或新日期;mask:String 格式化日期的模板;utc:Stirng 可選的UTC。
        return function (date, mask, utc) {
        var i18n = dateFormat.i18n;
        var masks = dateFormat.masks;
        // You can't provide utc if you skip other args (use the "UTC:" mask prefix)
        // 如果只有一個參數,其該參數是不包含數字的字符串,則視作這個參數為mask。date由下一個if中的new Date產生,那么date就是現在的日期。
        if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !//d/.test(date)) {
        mask = date;
        date = undefined;
        }

        // Passing date through Date applies Date.parse, if necessary
        date = date ? new Date(date) : new Date;
        if (isNaN(date)) throw SyntaxError("invalid date");
        // 通過判斷多種情況明確mask是什么,不論前面是如何指定的。留意 || 的技巧。
        mask = String(masks[mask] || mask || masks["default"]);
        // Allow setting the utc argument via the mask
        if (mask.slice(0, 4) == "UTC:") {
        mask = mask.slice(4);
        utc = true;
        }
        // 分兩種情況,用UTC格式的情況和一般的。注意通過JS的字面索引也可以返回方法的成員。
        var _ = utc ? "getUTC" : "get",
        d = date[_ + "Date"](),
        D = date[_ + "Day"](),
        m = date[_ + "Month"](),
        y = date[_ + "FullYear"](),
        H = date[_ + "Hours"](),
        M = date[_ + "Minutes"](),
        s = date[_ + "Seconds"](),
        L = date[_ + "Milliseconds"](),
        o = utc ? 0 : date.getTimezoneOffset(),
        flags = {
        d: d,
        dd: pad(d),
        ddd: i18n.dayNames[D],
        dddd: i18n.dayNames[D + 7],// 位寬:7, 見 dateFormat.dayNames。
        m: m + 1, // 從0開始起月份
        mm: pad(m + 1),
        mmm: i18n.monthNames[m],
        mmmm: i18n.monthNames[m + 12], // 位寬:12,見 dateFormat.monthNames
        yy: String(y).slice(2),// 字符串slice()的用法
        yyyy: y,
        h: H % 12 || 12, // h表示12小時制,h除以12(因為十二進制),取余的結果為12小時制的。
        hh: pad(H % 12 || 12),
        H: H,
        HH: pad(H),
        M: M,
        MM: pad(M),
        s: s,
        ss: pad(s),
        l: pad(L, 3), // Max,999ms
        L: pad(L > 99 ? Math.round(L / 10) : L),
        // 大小寫有影響
        t: H < 12 ? "a" : "p",
        tt: H < 12 ? "am" : "pm",
        T: H < 12 ? "A" : "P",
        TT: H < 12 ? "AM" : "PM",
        // 這一步求 timezone,就是要處理一下。
        // 前文有timezone,timezoneClip = /[^-+/dA-Z]/g,
        // String返回日期的字符串形式,包括很長的……UTC……信息
        // 假如沒有,則[""].pop() 返回空字符
        Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
        // 4位的TimezoneOffset
        o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
        // 求英文的["th", "st", "nd", "rd"],依據是d的個位數
        S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
        };
        return mask.replace(token, function ($0 /*很好$0,須知$1、$2由系統占用了*/) {
        // 怎么檢測某個對象身上有指定的屬性?用 in 檢測即可!
        // $0.slice(1, $0.length - 1);?什么意思?
        return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
        });
        };
        })();

        該段代碼對日期處理考慮得比較周全,我們就進入原理看看它的奧秘,——是怎么處理日期的!

        日期字符串模板中,我們約定用 yyyy/mm/dd 等的有意義的符號分別表示日期中某一個元素,像 y 即 year 某一年份,m 即 month 某一月份,d 即 day 某一天,如果是大寫的話還要注意區分開來,大寫 M 代表分鐘,小寫 m 是月份。總之,這是一份我們人為規范好的約定,即上述代碼所謂的“mask”,遵照此約定輸入欲格式化模式的參數,便可將日期類型的值輸出可供打印的字符串。至于解析的日期過程是,先按照 Mask 的全部要求,逐個獲取到日期的每一個元素(getDate(),getMinute()……可以很快獲取到),接著按照 Mask 真實的條件是什么,即Mask.replace(正則, 元素)方法進行字符串模板與元素之間的替換,替換的過程還是以 flag 為標志去逐一匹配的對照表。至于正則部分,關鍵在于理解 token 和 replace() 函數的過程。參加上述代碼注釋,即可了解內部細節。

        如果每一次都要輸入冗長的 Mask 字符串豈不是很累?我們可以通過定義常量的方法縮減我們的工作量:
        代碼如下:
        dateFormat.masks = {
        "default": "ddd mmm dd yyyy HH:MM:ss",
        shortDate: "m/d/yy",
        shortDate2: "yy/m/d/h:MM:ss",
        mediumDate: "mmm d, yyyy",
        longDate: "mmmm d, yyyy",
        fullDate: "dddd, mmmm d, yyyy",
        shortTime: "h:MM TT",
        mediumTime: "h:MM:ss TT",
        longTime: "h:MM:ss TT Z",
        isoDate: "yyyy-mm-dd",
        isoTime: "HH:MM:ss",
        isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
        isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
        // 加入中國類型的日期 @Edit 2010.8.11
        ,ChineseDate :'yyyy年mm月dd日 HH時MM分'
        }

        dateFormat.i18n = {
        dayNames: [
        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
        ],
        monthNames: [
        "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
        "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
        ]
        };

        Steve 的 dateFormat 足可以完成大多數日期轉化的任務,不過在茫茫代碼中,我們找到了更優的解法,不出20行代碼,把正則運用得收放自如,就是來自月影前輩的JS !
        代碼如下:
        Date.prototype.format = function(format) //author: meizz
        {
        var o = {
        "M+" : this.getMonth()+1, //month
        "d+" : this.getDate(), //day
        "h+" : this.getHours(), //hour
        "m+" : this.getMinutes(), //minute
        "s+" : this.getSeconds(), //second
        "q+" : Math.floor((this.getMonth()+3)/3), //quarter
        "S" : this.getMilliseconds() //millisecond
        }
        if(/(y+)/.test(format)) format=format.replace(RegExp.$1,
        (this.getFullYear()+"").substr(4 - RegExp.$1.length));
        for(var k in o)if(new RegExp("("+ k +")").test(format))
        format = format.replace(RegExp.$1,
        RegExp.$1.length==1 ? o[k] :
        ("00"+ o[k]).substr((""+ o[k]).length));
        return format;
        }
        alert(new Date().format("yyyy-MM-dd hh:mm:ss"));

        原理上與 Steve 方法相似,但更濃縮的代碼,卻集技巧性和全面性于一身。從源碼第12行開始,test() 方法不但可以檢測是否匹配的這個起碼功能,而且實際上是有記憶匹配結果的,產生 RegExp.$1 結果組來處理年份(開始我認為 test() 效率高并不會產生結果,實則不然)。然后,再使用 new RegExp 在字符串形式創建正則表達式的實例,又是一個高明的地方,——因為直接與 o 的 hash 表直接對接起來了!繼而依法瓢葫蘆,先測試是否命中匹配,有的話就進行替換。

        另外,代碼中的 ("00" + o[k]).substr(String(o[k]).length) 也是有趣的地方,前面加上兩個什么意思呢?原來目的是為了取數組的最后兩位。這是綜合利用 substr() 方法的一個技巧,substr 第一個參數是開始截取的 index,若不指定第二個參數 index 則保留字符串到最后(str.length)。于是,我們事先加多了多少位,原本固定的字符串長度不變(String(o[k].length))的情況下,那么就留下多少個位。(p.s “00”相當于占位符,亦可用其他字符串“XX”代替無區別)

        仍然覺得這段代碼有不少的困難?我們嘗試把月影的函數重寫為可讀性較強的代碼,原理上趨于一致可是沒那么多的技巧,相信這樣可以節省大家的時間,回頭再去看月影的代碼也不遲。
        代碼如下:
        date = {
        format: function(date, format){
        date = new Date(date); // force con.
        date = {
        year : date.getFullYear()
        ,month : date.getMonth() + 1 // 月份, 月份從零算起
        ,day : date.getDate()
        ,hour : date.getHours()
        ,minute : date.getMinutes()
        ,second : date.getSeconds()
        ,milute : date.getMilliseconds()
        };
        var
        match
        ,reg = /(y+)|(Y+)|(M+)|d+|h+|m+|s+|u+/g;
        while((match = reg.exec(format)) != null){
        match = match[0];
        if(/y/i.test(match)){
        format = format.replace(match, date.year);
        }
        if(match.indexOf('M') != -1){
        format = format.replace(match, date.month);
        }
        if(match.indexOf('d') != -1){
        format = format.replace(match, date.day);
        }
        if(match.indexOf('h') != -1){
        format = format.replace(match, date.hour);
        }
        if(match.indexOf('m') != -1){
        format = format.replace(match, date.minute);
        }
        if(match.indexOf('s') != -1){
        format = format.replace(match, date.second);
        }
        if(match.indexOf('u') != -1){
        format = format.replace(match, date.milute);
        }
        }
        return format;
        }
        };

        2011--1-7:

        從 ext 4.0 淘到的日期格式化的代碼,怎么講字符串轉為 js 標準日期?看看新 ext 是怎么做的?
        代碼如下:
        /**
        * 按照特定的格式模式格式化日期。
        * Parse a value into a formatted date using the specified format pattern.
        * @param {String/Date} value 要格式化的值(字符串必須符合JavaScript日期對象的格式要求,參閱parse())The value to format (Strings must conform to the format expected by the javascript
        * Date object's parse() method)
        * @param {String} format (可選的)任意的日期格式化字符串。(默認為'm/d/Y')(optional) Any valid date format string (defaults to 'm/d/Y')
        * @return {String} 已格式化字符串。The formatted date string
        */
        date: function(v, format) {
        if (!v) {
        return "";
        }
        if (!Ext.isDate(v)) {
        v = new Date(Date.parse(v));
        }
        return v.dateFormat(format || Ext.util.Format.defaultDateFormat);
        }

        date 構造器還可以通過算出距離1970起為多久的毫秒數來確定日期?——的確,這樣也行,——也就說,舉一反三,從這個問題說明,js 日期最小的單位是毫秒。

        最終版本:
        代碼如下:
        /**
        * 日期格式化。詳見博客文章:http://blog.csdn.net/zhangxin09/archive/2011/01/01/6111294.aspx
        * e.g: new Date().format("yyyy-MM-dd hh:mm:ss")
        * @param {String} format
        * @return {String}
        */
        Date.prototype.format = function (format) {
        var $1, o = {
        "M+": this.getMonth() + 1, // 月份,從0開始算
        "d+": this.getDate(), // 日期
        "h+": this.getHours(), // 小時
        "m+": this.getMinutes(), // 分鐘
        "s+": this.getSeconds(), // 秒鐘
        // 季度 quarter
        "q+": Math.floor((this.getMonth() + 3) / 3),
        "S": this.getMilliseconds() // 千秒
        };
        var key, value;

        if (/(y+)/.test(format)) {
        $1 = RegExp.$1,
        format = format.replace($1, String(this.getFullYear()).substr(4 - $1));
        }

        for (key in o) { // 如果沒有指定該參數,則子字符串將延續到 stringvar 的最后。
        if (new RegExp("(" + key + ")").test(format)) {
        $1 = RegExp.$1,
        value = String(o[key]),
        value = $1.length == 1 ? value : ("00" + value).substr(value.length),
        format = format.replace($1, value);
        }
        }
        return format;
        }

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        JavaScript自定義日期格式化函數詳細解析_javascript技巧

        JavaScript自定義日期格式化函數詳細解析_javascript技巧:我們對 JavaScript 擴展其中一個較常的做法便是對 Date.prototype 的擴展。因為我們知道,Date 類只提供了若干獲取日期元素的方法,如 getDate(),getMinute()……卻沒有一個轉換為特定字符串的格式化方法。故所以,利用這些細微的方法,加以封裝,組合我們想
        推薦度:
        標簽: 時間 自定義 js
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 国产A在亚洲线播放| 午夜精品射精入后重之免费观看| 国产精品永久免费10000| 国产成人无码综合亚洲日韩| 成人毛片18女人毛片免费96 | 在线观看亚洲AV日韩A∨| 亚洲人成免费电影| 2015日韩永久免费视频播放| 亚洲大片免费观看| 日韩免费福利视频| 免费看一级毛片在线观看精品视频| 国产免费人成视频在线观看| a级毛片免费观看在线| 亚洲va久久久噜噜噜久久男同| 日本免费一区二区三区四区五六区| 亚洲欧洲国产精品你懂的| 无码日韩精品一区二区免费暖暖| 亚洲成av人片在www鸭子| 午夜网站在线观看免费完整高清观看| 自拍偷区亚洲国内自拍| 无码少妇一区二区浪潮免费| 久久亚洲免费视频| 拍拍拍无挡免费视频网站| 永久黄网站色视频免费直播| 亚洲欧洲日产v特级毛片| 亚洲午夜久久久影院| 免费毛片在线视频| 2020久久精品国产免费| 日本免费一区二区三区四区五六区| 一级成人a做片免费| 日韩黄色免费观看| 四虎永久在线观看免费网站网址 | 立即播放免费毛片一级| 亚洲免费人成视频观看| 91亚洲国产成人久久精品网站| 免费a级毛片无码a∨免费软件| 人成电影网在线观看免费| 亚洲精品欧洲精品| 成人性生交大片免费看无遮挡| 亚洲AV日韩综合一区| 伊人久久亚洲综合|