ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript カスタム日付書式設定関数の詳細な分析_JavaScript スキル

JavaScript カスタム日付書式設定関数の詳細な分析_JavaScript スキル

WBOY
WBOYオリジナル
2016-05-16 17:03:521225ブラウズ

JavaScript を拡張する最も一般的な方法の 1 つは、Date.prototype を拡張することです。 Date クラスには、getDate()、getMinute() など、日付要素を取得するためのいくつかのメソッドしか提供されていないことがわかっていますが、特定の文字列に変換するための書式設定メソッドはありません。したがって、これらの微妙な方法を使用して、必要な日付文字列形式をカプセル化して結合します。一般に、書式設定関数は Date オブジェクトのプロトタイプで定義することも、別のメソッドとして記述することもできます。プロトタイプメソッドを定義する操作は、Date.prototype.format = function(date){......} のようになります。使用する場合は、 new Date().format(YYYY:MM:DD) を使用するだけです。 Date オブジェクトのネイティブ メソッドの場合。ただし、プロトタイプ メソッドの定義には、JS プロトタイプを「侵害」するという欠点があります。 API を設計する際には、この問題を考慮する必要があります。私の提案は、ユーザーが独自の判断に基づいて決定することですが、呼び出し方法は異なり、プロセスのロジックには影響しません。

次の例は、独立関数、独立フォーマット関数として記述された JavaScript 日付フォーマット関数です。フォーマットの知識ポイントに戻り、フォーマットがどのように実装され、どのような原則が使用されているかを検討します。 IndexOf() substr() などの従来の文字列スプライシングも実装できますが、明らかに非効率であるだけでなく、コードが長くなります。これは、最初に文字列の正規表現を記述してからヒットを実行するのに適した方法です。結果に基づいてマッチングします。まず Steven Levithan の例を見てみましょう:

コードをコピーします コードは次のとおりです:

/**
* 日付形式 1.2.3
* @credit Steven Levithan Scott Trenda による機能強化が含まれています。 and Kris Kowal
* 日付、マスク、または日付とマスクを受け入れます。
* 指定された日付の書式設定されたバージョンを返します。
* 日付のデフォルトは現在の日付/時刻です。
* マスクのデフォルトは dateFormat.masks.default.
 */
dateFormat = (function(){
// 通常のメモ、1. トークン、(?:) は非キャプチャ グループ化を示します。 /1 後方参照(思考: {1,2} は /1 と同じ意味を持ちますか?); ここでの意味によると、[LloSZ] は括弧内の任意の文字と一致することを意味します。非常に単純ですが、理解できません。まだ /L|l|o|S 日付の解析における |Z/ の役割は、「or」の最後の 2 つのグループが引用符と引用符内の内容に一致します (二重引用符があるかどうかは関係ありません)。
var token = /d{1,4}|m{ 1,4}|yy(?:yy)?|([HhMsTt])/1?|[LloSZ]|"[ ^"]*"|'[^']*'/g,
// 2 , timezone, [PMCEA][SDP] は 2 文字を消費します。reg は非キャプチャ グループなので、正規化を高速化できます。速度:太平洋|山|中部|東部|大西洋) (?:標準|夏時間|一般) 時間|(?:GMT|UTC)(?:[- ]/d{4})?)/b/g、
timezoneClip = /[^- /dA-Z]/g,

// 2 文字未満のパディング文字、または桁数を指定可能
Pad = function (val, len) {
val = String(val);
len = len || 2;
while (val.length return val;
} ;
// なぜ関数を返すのでしょうか? 上記で説明した変数はすべて定数なので、以下で返されるパラメータは実際に実行される関数です。これは
// 正規表現を高速化することができます。サポートする関数は、closure
を通じてキャッシュされます。 // パラメータの説明: date: 解析された日付または新しい日付; マスク: フォーマットされた日付の文字列テンプレート; utc:Stirng オプションの UTC。
return function (date, Mask, utc) {
var i18n = dateFormat.i18n;
varmass = dateFormat.masks;
// 他の引数をスキップすると utc を指定できません ( 「UTC:」マスク接頭辞を使用します)
// パラメータが 1 つしかなく、パラメータが数字を含まない文字列である場合、このパラメータはマスクとみなされます。 date は次の if で新しい Date によって生成され、date は現在の日付になります。
if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !//d/.test(date)) {
マスク = 日付;
date = unknown;
}

// Date に日付を渡すと、必要に応じて Date.parse が適用されます
date = date ? new Date(date) : new Date;
if (isNaN(date)) throw SyntaxError("invalid date");
// 以前に指定された方法に関係なく、複数の状況を判断してマスクが何であるかを明確にします。 || トリックに注意してください。
マスク = String(マスク[マスク] || マスク || マスク["デフォルト"]); == "UTC:") {
マスク = マスク.slice(4);
utc = true ;メソッドのメンバーは、JS リテラル インデックスを介して返すこともできることに注意してください。
var _ = utc ? "getUTC" : "get",
d = date[_ "Date"](),
D = date[_ "Day"](),
m = 日付[_ "月"](),
y = 日付[_ "年"](),
H = 日付[_ "時"](),
M = 日付[_ "分"](),
s = 日付[_ "秒"](),
L = 日付[_ "ミリ秒"](),
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),// 文字列の使用法 slide()
yyyy: y,
h: H % 12 | | 12, // h は 12 時間形式を表し、h を 12 で割って (12 進法のため)、余りが 12 時間形式です。
hh: パッド(H % 12 || 12)、
H: H、
HH: パッド(H)、
M: M、
MM: パッド(M)、
s: s,
ss: パッド(s),
l: パッド(L, 3), // Max,999ms
L: パッド(L > 99 ? Math.round(L / 10) : L)、

T: H TT: H // このステップではタイムゾーンを処理する必要があります。
().replace (TimezoneClip, ""),
// 4 ビット TimezoneOffset
O: (O & GT; 0? "- "") Pad (math.floor (math.abs (o) / 60) * S : ["th", "st", "nd", "rd"][d % 10 > 3 ? : (d % 100 - d % 10 != 10) * d % 10]
};
以上です! 🎜> // $0.slice(1, $0.length - 1);? ;
}); 日付の扱い方

日付文字列テンプレートでは、日付の特定の要素を表すために yyyy/mm/dd などの意味のある記号を使用することに同意します。たとえば、日が次の場合、y は年、m は月、d は日を意味します。大文字の M は分を表し、小文字の m は月を表します。要するに、これは私たちが人為的に標準化した規則であり、上記のコードのいわゆる「マスク」です。この規則に従って、書式設定したい書式モードのパラメーターを入力し、次に日付型の値を入力します。印刷可能な文字列として出力できます。日付の解析処理については、まずMaskのすべての要件に従って日付の各要素を1つずつ取得し(getDate()、getMinute()...はすぐに取得できます)、その後Maskの実際の条件に従います。つまり、マスク .replace(regulatory, element) メソッドは、文字列テンプレートと要素の間の置換を実行します。置換プロセスは、ルックアップ テーブルと 1 つずつ照合するための標識として引き続き使用されます。通常の部分に関しては、token 関数と replace() 関数の処理を理解することが重要です。内部の詳細を理解するには、上記のコード コメントを参照してください。

毎回長いマスク文字列を入力するのは面倒ではないでしょうか?定数を定義することで作業負荷を軽減できます:




コードをコピーします

コードは次のとおりです:

dateFormat.masks = {
"default": "ddd mmm dd yyyy HH:MM:ss",
shortDate: "m/d/yy",
shortDate2: "yy /m/d/h:MM:ss",
mediumDate: 「mmmm d, yyyy」,
longDate: 「mmmm d, yyyy」,
fullDate: 「dddd, mmmm d, yyyy」,
shortTime: "h:MM TT",
middleTime: "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: [
"日"、"月"、"火"、"水"、"木"、"金"、"土"、
「日曜日」、「月曜日」、「火曜日」、「水曜日」、「木曜日」、「金曜日」、「土曜日」
]、
monthNames: [
"Jan"、"Feb"、 「3 月」、「4 月」、「5 月」、「6 月」、「7 月」、「8 月」、「9 月」、「10 月」、「11 月」、「12 月」、
「1 月」、「2 月」 、「3 月」、「4 月」、「5 月」、「6 月」、「7 月」、「8 月」、「9 月」、「10 月」、「11 月」、「12 月」
]
};

Steve の dateFormat は、ほとんどの日期変換の任務を完了することができ、茫茫代码中、我们找到了更弘的解法、不出20行代,正则运用得收放自如,就是来月影前辈的JS !
复制代代码如下:

Date.prototype.format = function(format) //作成者: meizz
{
var o = {
"M " : this.getMonth() 1, //month
"d " : this.getDate(), //日
"h " : this.getHours(), //時
"m " : this.getMinutes(), //分
"s " : this.getSeconds(), //秒
"q " : Math.floor((this.getMonth() 3)/3), //四半期
"S" : this.getMilliseconds() //ミリ秒
}
if (/(y )/.test(format)) format=format.replace(RegExp.$1,
(this.getFull Year() "").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));
戻り形式;
}
alert(new Date ().format("yyyy-MM-dd hh:mm:ss"));

原理は Steve のメソッドと似ていますが、コードはより凝縮されており、スキルと包括性を兼ね備えています。ソースコードの12行目以降のtest()メソッドは、一致するかどうかを検出するという基本的な機能を備えているだけでなく、実際には一致結果を記憶し、年を処理するためのRegExp.$1結果群を生成します(最初はそう思っていました)。 test() は効率的でしたが、結果は生成されませんでしたが、そうではありません)。次に、new RegExp を使用して、文字列の形式で正規表現のインスタンスを作成します。これも賢い方法です。これは、o! のハッシュ テーブルに直接接続されているためです。次に、法律に従って、まず一致するかどうかをテストし、一致する場合は交換します。

さらに、コード内の ("00" o[k]).substr(String(o[k]).length) も興味深いです。前に 2 を追加することは何を意味しますか?本来の目的は、配列の最後の 2 桁を取得することです。これはsubstr()メソッドを総合的に利用する手法で、substrの第一引数はインターセプトを開始するインデックスとなり、第二引数のインデックスが指定されていない場合は文字列が最後まで保持されます(str.length)。したがって、事前に何ビット追加し、元の固定文字列長が変更されないまま (String(o[k].length)) になった場合、何ビットが残るでしょうか。 (p.s "00" はプレースホルダーに相当し、違いなく他の文字列 "XX" に置き換えることもできます)

このコードはまだ難しいですか?私たちは Yueying の関数をより読みやすいコードに書き直そうとしましたが、原理は一貫していますが、これによってすべての人の時間を節約できると考えています。

コードをコピー コードは次のとおりです。

date = {
format: function (date, format){
date = new Date(date); // 強制 con.
date = {
year : date.getFull Year()
,month : date.getMonth() 1 // Month 、月はゼロから始まります
、day : date.getDate()
、hour : date.getHours()
、minut : date.getMinutes()
、秒 : 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. minutes);
} }
if(match.indexOf('s') != -1){
format = format.replace(match, date.second);
}
if(match.indexOf('u') != -1){
format = format.replace(match, date .milute);
}
ext 4.0 の日付書式設定コードを見つけました。文字列を JS 標準の日付に変換する方法は?新しい内線がどのように行われるかわかりますか?



コードをコピー

コードは次のとおりです:


/**
* 特定の形式パターンに従って日付を形式設定します。
* 指定された書式パターンを使用して、値を書式設定された日付に解析します。
* @param {String/Date} value 書式設定される値 (文字列は JavaScript 日付オブジェクトの書式要件に準拠している必要があります。< を参照) ;a href="http://www.w3schools.com/jsref/jsref_parse.asp" mce_href="http://www.w3schools.com/jsref/jsref_parse.asp">parse() )書式設定する値 (文字列は、JavaScript
* Date オブジェクトの parse()method)
* @param {String} 形式 (オプション) 任意の日付形式の文字列。 (デフォルトは 'm/d/Y') (オプション) 任意の有効な日付形式文字列 (デフォルトは 'm/d/Y')
* @return {String} 形式設定された文字列。フォーマットされた日付文字列
*/
date: function(v, format) {
if (!v) {
return "";
}
if (!Ext.isDate(v)) {
v = new Date(Date.parse(v));
}


日付コンストラクターは、 1970 年からのミリ秒数? ——確かに、これも可能です。——言い換えれば、この質問は、一例から推測すると、js date の最小単位がミリ秒であることを示しています。

最終バージョン:


/**
* 日付の形式。詳細については、ブログ記事を参照してください: http://blog.csdn.net/zhangxin09/archive/2011/01/01/6111294.aspx
* 例: new Date().format("yyyy-MM-dd hh :mm :ss")
* @param {String} 形式
* @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() // 1000 秒
};
var key, value;

if (/(y)/.test(format)) { $1 = RegExp.$1,

format = format.replace($1, String(this.getFull Year()).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);
}
}
戻り値;
}


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。