Tuesday, October 26, 2010

เรียนรู้วิธีที่ ExtJS format date

ใน ExtJS เราใช้ function format ในการกำหนดรูปแบบการแสดงผลของ Date object
ลองดูตัวอย่าง

new Date().format("c")
"2010-10-26T08:35:30+07:00"

new Date().format("d/n/Y")
"26/10/2010"


คำถามที่น่าสนใจก็คือ เขาใช้วิธีไหนในการ implement function นี้

ลองเปิดไล่ดู code ใน file src/util/Date.js
เริ่มจาก object ที่ชื่อ formatCodes
formatCodes : {
d: "String.leftPad(this.getDate(), 2, '0')",
D: "Date.getShortDayName(this.getDay())", // get localised short day name
j: "this.getDate()",
l: "Date.dayNames[this.getDay()]",
N: "(this.getDay() ? this.getDay() : 7)",
S: "this.getSuffix()",
w: "this.getDay()",
z: "this.getDayOfYear()",
W: "String.leftPad(this.getWeekOfYear(), 2, '0')",
F: "Date.monthNames[this.getMonth()]",
m: "String.leftPad(this.getMonth() + 1, 2, '0')",
M: "Date.getShortMonthName(this.getMonth())", // get localised short month name
n: "(this.getMonth() + 1)",
....
}

คำถามที่ตามมาก็คือ ทำไมถึงเก็บ code ฝั่งขวาเป็น String

ลองไล่จาก top down บ้าง, โดยย้อยกลับไปดู function format ว่า code ข้างในเป็นอย่างไร
Date.prototype.format = Date.prototype.dateFormat;

dateFormat : function(format) {
if (Date.formatFunctions[format] == null) {
Date.createFormat(format);
}
return Date.formatFunctions[format].call(this);
},


จะเห็นว่า เมื่อได้รับ parameter เป็น format แล้ว, function มันจะพยายาม lookup หา function จากตาราง Date.formatFunctions ก่อน
ถ้าไม่เจอ ก็จะไปเรียก Date.createFormat เพื่อสร้าง function ให้ก่อน

ลองตามไปดู function createFormat บ้าง
code ที่เป็นพระเอกของเราก็คือ บรรทัดสุดท้าย
    createFormat : function(format) {
var code = [],
special = false,
ch = '';

for (var i = 0; i < format.length; ++i) {
ch = format.charAt(i);
if (!special && ch == "\\") {
special = true;
} else if (special) {
special = false;
code.push("'" + String.escape(ch) + "'");
} else {
code.push(Date.getFormatCode(ch))
}
}
Date.formatFunctions[format] = new Function("return " + code.join('+'));
},

จะเห็นว่ามัน loop ไปตามแต่ละ character ที่อยู่ใน format string ที่เราส่งให้
จากนั้นก็ไปเอาไป lookup ตาราง formatCodes ที่เราเห็นข้างบน ได้ค่ามาก็จัดการ แปะให้กลายเป็น anonymous function
แล้วก็เก็บ cache ไว้ใน Date.formatFunctions

ลอง dump Date.formatFunctions มาดู
Date.formatFunctions["d/n/Y"]
function anonymous() { return String.leftPad(this.getDate(), 2, '0')+'/'+(this.getMonth() + 1)+'/'+this.getFullYear();
}


พอเห็น code แบบนี้แล้ว การเพิ่มวันที่ไทยเข้าไปเองก็ไม่ยากแล้ว

Related link from Roti

No comments: