Detailed parsing of JavaScript custom date formatting functions _ javascript skills

Source: Internet
Author: User
Tags comparison table javascript extension
The following example is a JavaScript date Formatting Function written using an independent function, an independent format function. Back to the knowledge point of formatting, we examine how to implement and what principles are used. One of the most common examples of JavaScript extension is the extension of Date. prototype. As we know, the Date class only provides several methods for getting Date elements, such as getDate (), getMinute ()...... There is no formatting Method for converting to a specific string. Therefore, these subtle methods are used to encapsulate and combine the desired date string form. Generally, this formatting function can be defined on the prototype of the Date object or written independently by a method. Operations for defining the prototype method, such as Date. prototype. format = function (date ){......}, Use new Date (). format (YYYY: MM: DD) directly, as if it is the native method of the Date object. However, the prototype method is slightly less intrusive than the JS prototype. This issue must be taken into account when designing an API. My suggestion is that users make decisions based on their own judgment, but the calling method is different without affecting the process logic.

The following example is a JavaScript date Formatting Function written using an independent function, an independent format function. Back to the knowledge point of formatting, we examine how to implement and what principles are used. Although traditional String concatenation such as indexOf () + substr () can be implemented, it is not only inefficient, but also code is lengthy. It is also suitable for introducing regular expressions, write the string regular expression first, and then perform hit matching in the result. Let's take a look at the example from Steven Levithan:

The Code is as follows:


/**
* 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 (){
// Regular note, 1. token ,(? :) Indicates a non-capturing group;/1 reverse reference (think: {1, 2} can it be the same as/1 ?); According to the meaning here [losz], it is very easy to match any character in the brackets, however, I do not understand the functions of/L | l | o | S | Z/in parsing date; the last two sets of "or" match the content in quotation marks and quotation marks (no double quotation marks or single quotation marks ).
Var token =/d {1, 4} | m {1, 4} | yy (? : Yy )? | ([HhMsTt])/1? | [Losz] | "[^"] * "| '[^'] * '/g,
// 2. timezone and [PMCEA] [SDP] generate the consumption of two characters. The reg is a non-capturing group, which can accelerate the regular expression speed.
Timezone = // B (? : [PMCEA] [SDP] T | (? : Pacific | Mountain | Central | Eastern | Atlanta )(? : Standard | Daylight | Prevailing) Time | (? : GMT | UTC )(? : [-+]/D {4 })?) /B/g,
TimezoneClip =/[^-+/dA-Z]/g,

// Enter less than two characters or a specified number of digits.
Pad = function (val, len ){
Val = String (val );
Len = len | 2;
While (val. length <len) val = "0" + val;
Return val;
};
// Why is a function returned? Because all the variables described above are changed to constants, the parameters returned below are the functions actually executed at that time. This is achieved through the writing of closures. For example, the speed can be increased.
// Regexes and supporting functions are cached through closure
// Parameter description: date: the parsed Date or new date, mask: String formatted Date template, and utc: Stirng optional 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)
// If there is only one parameter, which is a string that does not contain digits, this parameter is regarded as mask. Date is generated by the new Date in the next if statement, so date is the current 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 ");
// Determine what a mask is, regardless of how it is specified, in multiple cases. Note | tips.
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;
}
// There are two cases, in UTC format and general. Note that you can also return the member of the method through the JS literal index.
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], // Bit Width: 7, see dateFormat. dayNames.
M: m + 1, // month starting from 0
Mm: pad (m + 1 ),
Mmm: i18n. monthNames [m],
Mmmm: i18n. monthNames [m + 12], // Bit Width: 12, see dateFormat. monthNames
Yy: String (y). slice (2), // usage of the String slice ()
Yyyy: y,
H: H % 12 | 12, // h indicates the 12-hour system. h is divided by 12 (because 12 hours). The remainder is in the 12-hour system.
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, 999 ms
L: pad (L> 99? Math. round (L/10): L ),
// Case sensitive
T: H <12? "A": "p ",
Tt: H <12? "Am": "pm ",
T: H <12? "A": "P ",
TT: H <12? "AM": "PM ",
// Calculate timezone in this step, which is to be processed.
// Timezone, timezoneClip =/[^-+/dA-Z]/g,
// String returns the String format of the date, including a long String ...... UTC ...... Information
// If NO, [""]. pop () returns an empty character
Z: utc? "UTC": (String (date). match (timezone) | [""]). pop (). replace (timezoneClip ,""),
// 4-bit TimezoneOffset
O: (o> 0? "-": "+") + Pad (Math. floor (Math. abs (o)/60) * 100 + Math. abs (o) % 60, 4 ),
// Calculate the English ["th", "st", "nd", "rd"] based on the single digit of d
S: ["th", "st", "nd", "rd"] [d % 10> 3? 0: (d % 100-d % 10! = 10) * d % 10]
};
Return mask. replace (token, function ($0/* Good $0, note $1, $2 occupied by the system */){
// How can I check that an object has a specified attribute? Check with in!
// $0. slice (1, $0. length-1 );? What does it mean?
Return $0 in flags? Flags [$0]: $0. slice (1, $0. length-1 );
});
};
})();


This section of code takes a thorough consideration of Date Processing, and we will go into the principle to see its mysteries-how to deal with the date!

In the date string template, we agree to use meaningful symbols such as yyyy, mm, and dd to represent an element of the date, for example, y, year, and m, month, or February, d indicates a day. If it is in upper case, it must be distinguished. in upper case, M indicates minute, and in lower case m indicates month. In short, this is a well-regulated Convention, that is, the so-called "mask" of the above Code. Follow this convention to enter the parameters for formatting mode, the date type value can be printed as a string. As for the parsing date process, according to all the requirements of the Mask, each element of the date (getDate (), getMinute ()...... Can be obtained soon), and then according to what is the actual condition of the Mask, that is, the Mask. replace (Regular Expression, element) is used to replace the string template and elements. The replacement process is a comparison table matching one by one with the flag. As for the regular expression, the key is to understand the process of token and replace () functions. Participate in the above Code comments to learn internal details.

Isn't it tiring to enter a lengthy Mask string every time? We can reduce our workload by defining constants:

The Code is as follows:


DateFormat. masks = {
"Default": "ddd mmm dd yyyy HH: MM: ss ",
Expiry date: "m/d/yy ",
ShortDate2: "yy/m/d/h: MM: ss ",
MediumDate: "mmm d, yyyy ",
LongDate: "mmmm d, yyyy ",
FullDate: "dddd, mmmm d, yyyy ",
Processing time: "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 '"
// Date added to the China type @ Edit 2010.8.11
, ChineseDate: 'Mm minutes on mm dd, yyyy'
}

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", "maid", "May", "June", "July", "August", "September", "October ", "November", "December"
]
};


Steve's dateFormat is enough to complete most date conversion tasks. However, in the vast code, we have found a better solution. There are no more than 20 lines of code, so we can use regular expressions freely, is the JS from the predecessors of yueying!

The Code is as follows:


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 "));


In principle, it is similar to Steve's method, but more concentrated code is a combination of skill and comprehensiveness. Starting from line 1 of the source code, the test () method can not only detect the minimum function of matching, but also has a memory matching result to generate RegExp. $1 result group to process the year (in my opinion, test () is efficient and does not produce results, but it is actually not ). Then, use new RegExp to create a regular expression instance in the string format, which is a brilliant place-because it is directly connected to the hash table of o! Then, the system tests whether matching is hit, and replaces it If yes.

In addition, the ("00" + o [k]). substr (String (o [k]). length) in the Code is also interesting. What do you mean by adding the above two? The original purpose is to get the last two digits of the array. This is a comprehensive technique for using the substr () method. The first parameter of substr is the index to be intercepted. If the second parameter is not specified, the string is retained to the end (str. length ). Therefore, how many digits are added in advance, and when the original fixed String length remains unchanged (String (o [k]. length), how many digits are left. (P.s "00" is equivalent to a placeholder and can be replaced by other strings "XX)

Still think this code has a lot of difficulties? We try to rewrite the functions of the shadow to code with high readability. The principle tends to be consistent, but there are not so many skills. I believe this will save you time, it's not too late to go back to the Shadow code.

The Code is as follows:


Date = {
Format: function (date, format ){
Date = new Date (date); // force con.
Date = {
Year: date. getFullYear ()
, Month: date. getMonth () + 1 // month. The month starts from zero.
, 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.exe c (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:

How to convert a string into a standard js date from the date format code obtained by ext 4.0? How does the new ext work?

The Code is as follows:


/**
* Format the date in a specific format.
* Parse a value into a formatted date using the specified format pattern.
* @ Param {String/Date} value the value to be formatted (the String must comply with the format requirements of the JavaScript Date object, see parse ()) the value to format (Strings must conform to the format expected by the javascript
* Date object's parse () method)
* @ Param {String} format (optional) any date format String. (Default value:'m/d/Y') (optional) Any valid date format string (defaults to'm/d/Y ')
* @ Return {String} the formatted 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 );
}


The date constructor can also determine the date by calculating the number of milliseconds from 1970? -- Indeed, this is the case. -- that is to say, the smallest unit of js date is millisecond.

Final Version:

The Code is as follows:


/**
* Format the date. For more information, see blog: 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, // month, starting from 0
"D +": this. getDate (), // Date
"H +": this. getHours (), // hour
"M +": this. getMinutes (), // minute
"S +": this. getSeconds (), // second
// Quarterly quarter
"Q +": Math. floor (this. getMonth () + 3)/3 ),
"S": this. getMilliseconds () // thousands of seconds
};
Var key, value;

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

For (key in o) {// if this parameter is not specified, the substring will continue to the end of 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;
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.