One of our more common practices for JavaScript expansion is the expansion of Date.prototype. Because we know that the Date class only provides several methods of obtaining date elements, such as getdate (), getminute () ... but none of the formatting methods converted to specific string. Therefore, use these subtle methods to encapsulate and combine the date string form we want. Generally speaking, this formatization function can be defined on the prototype of the DATE object, or it can be written independently. The operation of the definition prototype is such as date.prototype.format = function (date) {...}, and directly new date (). Format (yyyy: mm: dd), as if the native method of the Date object. However, the definition prototype method is slightly suspected of the lack of "invasion" JS prototype. This issue must be considered when designing API. My suggestion is that users make decisions in accordance with their own judgment, but the method of calling is different, and the logic of the process does not affect the process.
The following example is the formatting function of the JavaScript date written by independent functions, an independent format function. Back to this knowledge point of formatting, we examined how and what principles were used. Although traditional string stitching such as indexof ()+substr () can be achieved, it is obviously not only low -efficiency, but also the code is long. It is still suitable for introducing regular expressions. First, write the regular string regularity and then match the results of the results. Let's first look at examples from Steven Levithan:
Copy code code as follows:
/**
* Date Format 1.2.3
* @credit Steven Levithan <Stevenlevithan.com> Includes Enhancements by Scott Trenda <scott.trenda.net> And Kris Kowal <Cixar.com/~kris.kowal/>
* Accepts a date, a master, or a date and a master.
* Return 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 notes, 1. Token, (? :) indicate non -capture group;/1 reverse reference (think: {1,2} can it mean the same as/1?); According to the meaning of [llosz] here, it means in the bracket It is simple to match any character, but it is not understood for the time being/l | l | o | s | Z/in the parsing date; the last two groups are "or" Double quotes or single quotes).
vartoken = /d {1,4} | m {1,4} | yy (?: yy)? | ([hhmstt]) /1? | [llosz] | [^"] |^[^' ]*'/g,
// 2. Timezone, [pmcea] [SDP] generates the consumption of two characters; the REG is a non -capture packet, which can speed up regularity.
timezone = // b (?: [pmcea] [SDP] T | (?: Pacific | Mountain | Central | Eastern | Atlantic) (?: Standard | DayLight | Prevailing) Time | (?: GMT | UTC) (? [-+]/d {4})?)/b/g,
TimezoneClip =/[^-+/DA-Z]/g,
// In less than two -bit filling character, or the number of positioning can be positioned
pad = function (value, len) {
value = string (val);
len = len || 2;
While (Val.Length <Len) val = "0" + value;
Return value;
};
// Why returns a function, because the variables explained earlier have become constant, and the parameters returned below are the function of the real time. This is implemented by closing writing. As comments in English, you can speed up.
// Regexes and Supporting Functions Are Cached Through CLOSURE
// Parameter description: Date: Date: Date or new date; Mask: String Formatting Date; 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, this parameter is a string that does not contain numbers, which is regarded as MASK. Date is generated by New Date in the next IF, so date is the current date.
If (ARGUMES.LENGTH == 1 && Object.prototype.tostring.call (date) == "[Object String]" &&! // D /TEST (DATE)) {
mask = date;
date = undefined;
}
// Passing Date Three APLIES DATE.PARSE, If NECESSARY
date = date? New date (date): new date;
if (ISNAN (Date)) Throw Syntaxerror ("Invalid Date");
// It is clear what MASK is by judging in many cases, no matter how previously specified it. Pay attention to the skills of ||.
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;
}
// Two cases, use the situation and general in UTC format. Note that the literal indexes of JS can also return to members of the method.
var_ = utc? "getutc": "get",
d = date [_ + "date"],,,
D = date [_ + "day"] (),,
m = date [_ + "month"] (),,
y = date [_ + "fullyear"] (),
H = date [_ + "hold"] (),,,
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, // 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), // String slice () usage
yyyy: y,
H: H % 12 || 12, // H means 12 hours, H divides 12 (because duodes), and the result of the remainder is 12 hours.
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),
// Patronize influence
t: h <12? "A": "p",
tt: h <12? "AM": "PM",
T: h <12? "A": "p",
Tt: h <12? "AM": "PM",
// Seek timezone at this step, just deal with it.
// The previous article is timezone, timezoneClip =/[^-+/da-z]/g,
// String The string form of the return date, including a long ... UTC ... Information
// If not, [""] .pop () return the 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),
// Find in English ["th", "st", "nd", "rd"], according to the single digits of D
S: ["th", "st", "nd", "rd"] [d % 10> 3? 0: (d % 100 -d % 10! = 10) * d % 10]
};
Return mask.replace (token, function ($ 0 /*is good $ 0, notice $ 1, $ 2 by the system occupied* /) {) {) {) {) {) {) {) {) {) {) {)
// How to detect the specified attributes on a certain object? Just detect it!
// $ 0.slice (1, $ 0.Length -1) ;? What does it mean?
Return $ 0 in Flags? Flags [$ 0]: $ 0.slice (1, $ 0.Length -1);
});
};
}) ();
The code is considered comprehensive about the date processing, so we enter the principle to see its mystery, -how to deal with the date!
In the date strings template, we agreed to use meaningful symbols of yyyy/mm/dd, etc., respectively indicate a certain element in the date, like Y, that is a year, Month, Month If you are uppercase, you should also pay attention to distinguished. The capital M represents a minute, and the lowercase M is the month. In short, this is a standardized agreement, that is, the so -called "Mask" of the above code. Following this agreement to enter the parameter of the formatting mode, we can output the date type value for printed string. As for the date of the analysis, first according to the entire requirements of Mask, get each element of each date one by one (getdate (), getminute ()) ... you can get it soon), and then follow the real conditions of Mask, that is, Mask The .replace (regular, element) method to replace the string template and the element, and the replacement process is still a comparison table that matches the flag by flag. As for the regular part, the key is the process of understanding the token and the replace () function. Participate in the above code comments to understand the internal details.
Isn't it tiring to enter the lengthy Mask string every time? We can reduce our workload by defining constant methods:
Copy code code as follows:
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'T'T'T'HH: MM: SS",
IsoutCDateTime: "UTC: YYYYY-MM-DD'T'T'T'T'T'HH: MM: SS'Z '"
// Add the date of China @Edit 2010.8.11
, Chinesetate: 'yyyy year MM month DD day HH time mm points'
}
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's DateFormat is enough to complete the task of most date conversion, but in the vast code, we have found a better solution, without the 20 lines of code, and the regular use is free, that is, JS from the senior of the moon shadow!
Copy code code 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), // 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");
The principle is similar to the Steve method, but the more concentrated code integrates skills and comprehensiveness. Starting from the 12th line of source code, the test () method can not only detect the minimum function of matching, but also in fact there is memory matching results. It will not produce results, it is not true). Then, use New RegExp to create an instance of regular expression in the form of a string, and it is a clever place, because it is directly connected with the Hash table directly with O! Then, according to the law, the gourd is tested for the matching of the life first, and if some, replace it.
In addition, the ("00" + o [k]). Substr (String (O [K]). LENGTH) is also an interesting place. What does two mean? The original purpose was to take the last two of the array. This is a skill that comprehensively uses the Substr () method. The first parameter of the Substr is the index that starts to intercept. If you do not specify the second parameter Index, you retain the string to the end. As a result, how many digits we added in advance, and the original fixed string length is unchanged (O [K] .Length), then how many digits were left. (PS "00" is equivalent to a placement symbol, and it can also be used with other string "XX" instead of no difference)
Do you still feel that this code has a lot of difficulties? We tried to rewrite the function of the moon shadow as a strong readability. The principle tends to be consistent, but there are not so many techniques. I believe that this can save everyone's time, and it is not too late to go back to watch the code of Yueying.
Copy code code 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.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:
How can I turn the string to the JS standard date? See how the new Ext is done?
Copy code code as follows:
/**
* According to the specific format formatting date.
* Parse a value insto a formatted date user using the specified format pattern.
* @param {string/date} Value to formatting (the string must meet the format requirements of the JavaScript date object, see <a href = "http://www.w3schools.com/jsref/jsref_parser.asp" mce_href = = "http://www.w.w3schools.com/jsref/jsref_parse.asp"> Parse () </a>) The value to format (Strings Must Conform to the format expected by the javasCrift
* Date Object's <a href = "http://www.w3schools.com/jsref/jsref_parse.asp" mce_href = "http://www.w3schools.com/jsref_parse.asp" (PARSE " ) </A > Method)
* @param {string} format (optional) format formatting string. (Optional) (Optional) Any Valid Date Format String (defaults to 'm/d/y')
* @Return {string} has formatted the string. The formatted date string
*/
Date: Function (v, Format) {
if (! v) {{
Return "" ";
}
if (! EXT.ISDATE (v)) {
v = new date (date.pars (v));
}
Return v.DateFormat (Format || EXT.UTIL.FORMAT.DEFAULTDATEFORMAT);
}
Can the Date constructor also determine the date by calculating the number of milliseconds from 1970? ——Ip, this is OK, -that is, in the other way, from the perspective of this problem, the unit with the smallest JS date is milliseconds.
Final version:
Copy code code as follows:
/**
* Date formatting. For details, see the blog post: http://blog.csdn.net/zhangxin09/archive/2011/01/6111294.aspx
* EG: 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, start from 0
"D+": this.getdate (), // date
"H+": this.getHours (), // hours
"m+": this.getminutes (), // minutes
"S+": This.getSeconds (), // seconds
// Quate 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 the parameter is not specified, the sub -string 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;
}