JavaScript를 확장하는 가장 일반적인 방법 중 하나는 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 의 향상된 기능이 포함되어 있습니다. 및 Kris Kowal
* 날짜, 마스크 또는 날짜와 마스크를 허용합니다.
* 지정된 날짜의 형식화된 버전을 반환합니다.
* 날짜의 기본값은 현재 날짜/시간입니다.
* 마스크의 기본값은 dateFormat.masks.default입니다.
*/
dateFormat = (function(){
// 일반 메모, 1. 토큰, (?:)는 비캡처 그룹화를 나타냅니다. /1 역참조 (생각하기: {1,2}가 /1과 같은 의미를 가질 수 있습니까?); 여기서의 의미에 따르면 [LloSZ]는 괄호 안의 모든 문자가 일치할 수 있다는 것을 의미합니다. 매우 간단하지만 이해가 되지 않습니다. 아직 /L|l|o|S 날짜 구문 분석에서 |Z/의 역할은 "or"의 마지막 두 그룹이 따옴표 및 따옴표 안의 내용과 일치합니다(큰따옴표가 있는지 여부는 중요하지 않음). 또는 작은따옴표)
var token = /d{1,4}|m{ 1,4}|yy(?:yy)?|([HhMsTt])/1?|[LloSZ]|"[ ^"]*"|'[^']*'/g,
// 2 , timezone, [PMCEA][SDP]는 두 문자를 사용합니다. 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 < len) val = "0" val;
return val;
} ;
/ / 함수를 반환하는 이유는 무엇입니까? 위에 설명된 변수는 모두 상수이므로 아래에 반환된 매개변수는 실제로 실행되는 함수입니다. 이는 속도를 높일 수 있는 클로저를 작성함으로써 달성됩니다.
// 정규식 및 지원 함수는 클로저를 통해 캐시됩니다
// 매개변수 설명: 날짜: 날짜를 구문 분석한 날짜 또는 새 날짜; 마스크: 형식화된 날짜에 대한 문자열 템플릿:Stirng 선택적 UTC.
반환 함수(날짜, 마스크, utc) {
var i18n = dateFormat.i18n;
varmask = dateFormat.masks;
// 다른 인수를 건너뛰면 utc를 제공할 수 없습니다( "UTC:" 마스크 접두사 사용)
// 매개변수가 하나만 있고 매개변수가 숫자를 포함하지 않는 문자열인 경우 이 매개변수를 마스크로 간주합니다. 날짜는 다음의 새 날짜에 의해 생성됩니다. 그러면 날짜는 현재 날짜입니다.
if (arguments.length == 1 && Object.prototype.toString.call(date) == "[객체 문자열]" && !//d/.test(date) {
마스크 = 날짜;
날짜 = 정의되지 않음;
}
// 필요한 경우 Date를 통해 날짜를 전달하면 Date.parse가 적용됩니다.
date = date ? new Date(date) : new Date;
if (Isnan (Date)) Throw Syntaxerror ("Invalid Date");
// 이전에 어떻게 지정했는지에 관계없이 많은 경우에 판단하여 MASK가 무엇인지 결정합니다. || 트릭을 조심하세요.
마스크 = String(마스크[마스크] || 마스크 || 마스크["기본값"]) == "UTC:") {
마스크 = 마스크.슬라이스(4);
utc = true ; 메소드의 멤버는 JS 리터럴 인덱스를 통해 반환될 수도 있습니다.
var _ = utc ? "getUTC" : "get",
d = 날짜[_ "날짜"](),
D = 날짜[_ "일"](),
m = 날짜[_ "월"](),
y = 날짜[_ "연도 전체"](),
H = 날짜[_ "시간"](),
M = 날짜[_ " 분"](),
s = 날짜[_ "초"](),
L = 날짜[_ "밀리초"](),
o = utc ? 0 : date.getTimezoneOffset() ,
플래그 = {
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로 나누어지고 나머지는 12시간 형식입니다.
hh: 패드(H % 12 || 12),
H: H,
HH: 패드(H),
M: M,
MM: 패드(M),
s: s,
ss: 패드(들),
l: 패드(L, 3), // Max,999ms
L: 패드(L > 99 ? Math.round(L / 10) : L),
",
T: H < 12 ? "A" : "P",
TT: H < 12 ? "PM",
// 이 단계에는 시간대가 필요합니다.
~ / 그렇지 않은 경우, [""].pop()은 빈 문자
Z: utc ? "UTC"를 반환합니다: (String(date).match(timezone) || [""]).pop ().replace (TimezoneClip, ""),
// 4비트 TimezoneOffset
O: (O & GT; 0? "- "") pad (math.floor (math.abs (o) / 60) * S : ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
};
그
// $0.slice(1, $0.length - 1);? ;
}) ——날짜 처리 방법!
날짜 문자열 템플릿에서는 yyyy/mm/dd와 같은 의미 있는 기호를 사용하여 날짜의 특정 요소를 나타내는 데 동의합니다. 예를 들어 y는 연도, m은 월, d는 일을 의미합니다. 대문자 M은 분, 소문자 m은 월을 의미하므로 구별에 주의하세요. 간단히 말해서 이것은 우리가 인위적으로 표준화한 관례인데, 이것이 바로 위 코드의 소위 "마스크"입니다. 이 관례에 따라 포맷하려는 형식 모드의 매개변수를 입력한 다음 날짜 유형 값을 입력합니다. 인쇄할 수 있는 문자열로 출력될 수 있습니다. 날짜 파싱 과정은 먼저 Mask의 모든 요구 사항을 따라 날짜의 각 요소를 하나씩 가져오고(getDate(), getMinute()...빠르게 얻을 수 있음) Mask의 실제 조건을 따릅니다. 즉, Mask .replace(regular, element) 메소드는 문자열 템플릿과 요소 간의 교체를 수행합니다. 교체 프로세스는 여전히 조회 테이블과 하나씩 일치하는 기호로 플래그를 기반으로 합니다. 정규 부분에서는 토큰과 교체() 함수의 프로세스를 이해하는 것이 핵심입니다. 내부 세부 사항을 이해하려면 위의 코드 주석을 참조하십시오.
매번 긴 마스크 문자열을 입력하기는 힘들지 않을까요? 상수를 정의하여 작업 부하를 줄일 수 있습니다.
코드 복사
코드는 다음과 같습니다.
dateFormat.masks = {
"기본값": "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: [
"일", "월", "화", "수", "목", "금", "토",
"일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"
],
MonthNames: [
"1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월",
"1월", "2월" , "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"
]
};
Steve의 dateFormat 足可以完成大多数日期转化的任务,不过在茫茫茫代码中,我们找到了更优的解法,不out20行代码,把正则运用得收放自如,就是来自月影前辈的JS !
Date.prototype.format = function(format) //작성자: meizz
{
var o = {
"M " : this.getMonth() 1, //월
"d " : this.getDate(), //일
"h " : this.getHours(), //시간
"m " : this.getMinutes(), //분
"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));
반환 형식;
}
alert(새 날짜 ().format("yyyy-MM-dd hh:mm:ss"));
원리는 스티브의 방식과 유사하지만 코드가 더 압축되어 기술과 포괄성이 결합되었습니다. 소스 코드의 12번째 줄부터 test() 메소드는 일치 여부를 감지하는 기본 기능을 가지고 있을 뿐만 아니라 실제로 일치하는 결과를 기억하고 RegExp.$1 결과 그룹을 생성하여 연도를 처리합니다(처음에는 생각했습니다. test()는 효율적이어서 결과를 생성하지 않습니다. 그러나 그렇지 않습니다. 그런 다음 새로운 RegExp를 사용하여 문자열 형식의 정규식 인스턴스를 생성합니다. 이는 또 다른 영리한 일입니다. 왜냐하면 o!의 해시 테이블에 직접 연결되어 있기 때문입니다. 그런 다음 법에 따라 먼저 일치하는 항목이 있는지 테스트하고 일치하는 경우 교체하십시오.
추가로 코드의 ("00" o[k]).substr(String(o[k]).length) 앞에 2개를 추가한다는 것은 무엇을 의미하나요? 원래 목적은 배열의 마지막 두 자리를 얻는 것입니다. substr() 메소드를 종합적으로 활용하는 기법입니다. substr의 첫 번째 매개변수는 차단을 시작할 인덱스입니다. 두 번째 매개변수 인덱스를 지정하지 않으면 문자열이 끝까지 유지됩니다(str.length). 따라서 미리 몇 비트를 추가하고 원래 고정 문자열 길이는 변경되지 않고(String(o[k].length)) 그대로 유지된 다음 몇 비트가 남습니다. (p.s "00"은 자리표시자와 동일하며, 다른 문자열 "XX"로 대체할 수도 있습니다.)
아직도 이 코드가 어려우신가요? 우리는 Yueying의 기능을 더 읽기 쉬운 코드로 다시 작성하려고 했습니다. 원칙은 일관적이지만 이것이 모든 사람의 시간을 절약할 수 있다고 생각합니다. 다시 돌아가서 Yueying의 코드를 살펴보는 것도 늦지 않았습니다.
날짜 = {
형식: 기능 (날짜, 형식){
date = new Date(date); // force con.
date = {
year : date.getFullYear()
,month : date.getMonth() 1 // 월, 월은 0부터 시작
,일 : date.getDate()
,시 : date.getHours()
,분 : 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.replace(일치, 날짜.연도);
}
if(match.indexOf('M') != -1){
형식 = 형식.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.replace(일치, 날짜.분);
} }
if(match.indexOf('s') != -1){
형식 = format.replace(일치, 날짜.초);
}
if(match.indexOf('u') != -1){
형식 = 형식.replace(일치, 날짜 .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() 메소드)
* @param {String} 형식(선택 사항) 모든 날짜 형식 문자열. (기본값은 'm/d/Y') (선택 사항) 모든 유효한 날짜 형식 문자열(기본값은 'm/d/Y')
* @return {String} 형식화된 문자열입니다. 형식화된 날짜 문자열
*/
날짜: 함수(v, 형식) {
if (!v) {
return "";
}
if (!Ext.isDate(v)) {
v = new Date(Date.parse(v))
}
날짜 생성자는 다음을 계산하여 날짜를 결정할 수도 있습니다. 1970년 이후 몇 밀리초? ——사실 이것도 가능합니다. ——즉, 한 예에서 유추해보면 이 질문은 js 날짜의 최소 단위가 밀리초임을 보여줍니다.
최종 버전:
/**
* 날짜 형식. 자세한 내용은 블로그 기사를 참조하세요: http://blog.csdn.net/zhangxin09/archive/2011/01/01/6111294.aspx
* 예: new Date().format("yyyy-MM-dd hh :mm :ss")
* @param {문자열} 형식
* @return {문자열}
*/
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.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);
}
}
반환 형식 ;
}