รูปแบบวันที่และเวลาของ JSON ควรเป็นแบบไหน
สรุปสำคัญ: ตัวเลข epoch และสตริง ISO ต่างมีข้อแลกเปลี่ยน แต่การผสมกันคือสิ่งที่ทำให้พังจริง ๆ ใช้ ISO 8601 พร้อม offset เก็บเป็น UTC และแสดงตามเขตเวลาของผู้ใช้

สรุปสั้น ๆ: ใช้ ISO 8601 พร้อม offset ที่ชัดเจนบน wire เก็บเป็น UTC โดยมี Z ต่อท้าย และแปลงเฉพาะตอนแสดงผล; ถ้าเลือกใช้ตัวเลข epoch ให้กำหนดวินาทีหรือมิลลิวินาทีให้ชัดทั้งระบบและใส่หน่วยในชื่อฟิลด์
ทำไม 2026-10-30 14:30:00 ยังไม่พอ
สตริงนั้นไม่มีเขตเวลากำกับ 14:30 ในเซี่ยงไฮ้กับ 14:30 ในลอนดอนห่างกันแปดชั่วโมง และไม่มีทางรู้ว่าหมายถึงอันไหน new Date('2026-10-30 14:30:00') parse ตามเขตเวลาท้องถิ่นของ รันไทม์ เซิร์ฟเวอร์กับเบราว์เซอร์จึงได้เวลาที่ต่างกันสองค่าจาก payload เดียว — บั๊กประเภทที่ทำซ้ำไม่ได้
2026-10-30 เปล่า ๆ ไม่ใช่จุดเวลาเลย เหมาะกับวันเกิดและรอบบิล แต่ผิดสำหรับเวลาที่สร้าง
สองรูปแบบที่ใช้ได้
สตริง ISO 8601
{
"createdAt": "2026-10-30T14:30:00+08:00",
"updatedAt": "2026-10-30T06:30:00Z"
}
อ่านได้ เรียงลำดับได้เมื่อรูปแบบสม่ำเสมอ มีความละเอียดถึงมิลลิวินาทีหากต้องการ และอธิบายตัวเอง
ตัวเลข epoch
{ "createdAt": 1793519400 }
กะทัดรัดและไม่กำกวม แต่อ่านไม่ออก และ วินาทีกับมิลลิวินาทีคือภัยถาวร ถ้าเลือกใช้ epoch ให้กำหนดหน่วยให้เป็นมาตรฐานและใส่ในชื่อฟิลด์: createdAtMs ปลอดภัยกว่า createdAt มาก
ข้อกำหนดที่ควรตั้งไว้แต่เนิ่น ๆ
| รายการ | ข้อกำหนด |
|---|---|
| รูปแบบบน wire | ISO 8601 พร้อม Z หรือ +08:00 |
| เขตเวลาที่เก็บ | UTC เพื่อไม่ให้ DST เข้ามาเกี่ยวข้อง |
| ความละเอียด | มิลลิวินาทีก็พอ |
| การตั้งชื่อฟิลด์ | createdAt, updatedAt, expiresAt |
| วันที่ล้วน | ฟิลด์ date แยกต่างหาก เช่น birthday: "1990-01-01" |
| ระยะเวลา | จำนวนเต็มบวกหน่วย เช่น timeoutMs: 3000 |
การแสดงผล
new Intl.DateTimeFormat('en-GB', {
dateStyle: 'medium',
timeStyle: 'short',
timeZone: 'Europe/London',
}).format(new Date('2026-10-30T06:30:00Z'));
ระบุ timeZone อย่างชัดเจนเมื่อการแสดงผลต้องไม่ตามอุปกรณ์ การพึ่งค่าเริ่มต้นของเบราว์เซอร์ถูกสำหรับเวลาที่ผู้ใช้เห็น แต่ผิดสำหรับรายงาน
บั๊กที่เกิดซ้ำสามอย่าง
วันที่เปล่า ๆ ถูก parse เป็นเที่ยงคืน UTC ตามสเปก ECMAScript สตริงที่มีเฉพาะวันที่เป็น UTC ขณะที่สตริงวันที่และเวลาเป็นเวลาท้องถิ่น ความไม่สอดคล้องนี้เป็นแหล่งของบั๊กคลาดเคลื่อนหนึ่งวันที่พบได้บ่อย
เขตเวลาของฐานข้อมูลไม่ตรงกับ serializer datetime ของ MySQL ไม่มีเขตเวลา; เขียนเป็นเวลาท้องถิ่น อ่านเป็น UTC แล้วทุกอย่างเลื่อนตาม offset
เวลาออมแสง การเก็บเวลาท้องถิ่นในอนาคตสร้างจุดเวลาที่ไม่มีอยู่หรือเกิดซ้ำสองครั้ง UTC ไม่มีช่องว่างเช่นนั้น
คำถามที่พบบ่อย
ควรเลือกระหว่าง ISO 8601 กับตัวเลข epoch อย่างไร?
ใช้ ISO 8601 เมื่อมีคนอ่าน payload, เมื่อต้องการลำดับแบบ lexical หรือเมื่อค่าต้องพาเขตเวลาของตัวเองไปด้วย; ต้นทุนคือไบต์เพิ่มราวสิบกว่าไบต์และไลบรารี parse ใช้ตัวเลข epoch เมื่อความกะทัดรัดและการจัดการข้ามภาษาง่าย ๆ สำคัญกว่า แต่กำหนดวินาทีหรือมิลลิวินาทีให้ชัดทั้งระบบและบอกว่าฟิลด์เก็บหน่วยใด
วันที่เปล่า ๆ กับ timestamp ควรใช้ฟิลด์เดียวกันไหม?
ไม่ควร 2026-10-30 เปล่า ๆ คือวันในปฏิทินที่ไม่มีเวลาและไม่มีเขตเวลา ขณะที่ฟิลด์ timestamp คาดหวังจุดเวลาที่แน่นอน ให้เก็บวันเกิดและรอบบิลในฟิลด์ date แยก และใช้ฟิลด์ ISO 8601 ที่ลงท้ายด้วย At สำหรับเวลาสร้างหรืออัปเดต