ฟังก์ชันวันที่และเวลาของ SQLite กลายเป็นแหล่งความหงุดหงิดสำหรับนักพัฒนาที่ทำงานกับแอปพลิเคชัน JavaScript ปัญหาหลักเกิดจากแนวทางของ SQLite ในการจัดรูปแบบ UTC timestamps ซึ่งแตกต่างจากแนวปฏิบัติมาตรฐานและสร้างปัญหาความเข้ากันได้กับการพัฒนาเว็บสมัยใหม่
การขาดตัวบ่งชี้ UTC สร้างปัญหาการแยกวิเคราะห์ใน JavaScript
ปัญหาหลักอยู่ที่พฤติกรรมการจัดรูปแบบวันที่ของ SQLite เมื่อ SQLite สร้าง UTC timestamps จะไม่รวมอักขระ 'Z' ต่อท้ายที่ระบุเวลา UTC ตามมาตรฐาน ISO การละเลยที่ดูเหมือนเล็กน้อยนี้มีผลกระทบอย่างมีนัยสำคัญต่อนักพัฒนา JavaScript เมื่อการแยกวิเคราะห์วันที่ของ JavaScript พบ timestamp ที่ไม่มีส่วนต่อท้าย 'Z' จะถือว่าวันที่อยู่ในเขตเวลาท้องถิ่นของไคลเอนต์แทนที่จะเป็น UTC พฤติกรรมนี้ทำให้เกิดเซสชันการดีบักที่ยาวนานหลายชั่วโมงสำหรับนักพัฒนาที่ไม่ทราบเกี่ยวกับความแปลกประหลาดนี้
ปัญหาจะรุนแรงเป็นพิเศษกับรูปแบบฐานข้อมูลทั่วไปเช่นคอลัมน์ createdAt
ที่ใช้ฟังก์ชัน NOW()
ของ SQLite ทุกครั้งที่ timestamps เหล่านี้ต้องการการประมวลผลจะต้องมีการจัดการเพิ่มเติมเพื่อเพิ่มอักขระ 'Z' ที่ขาดหายไป นักพัฒนาต้องใช้วิธีแก้ไขปัญหาเพื่อตรวจสอบว่าวันที่ UTC รวมตัวบ่งชี้ต่อท้ายหรือไม่และเพิ่มด้วยตนเองเมื่อขาดหายไป
รูปแบบฟังก์ชันวันที่ของ SQLite
ฟังก์ชัน | รูปแบบผลลัพธ์ | ตัวอย่าง |
---|---|---|
date() |
YYYY-MM-DD | 2025-06-16 |
time() |
HH:MM:SS | 13:22:19 |
datetime() |
YYYY-MM-DD HH:MM:SS | 2025-06-16 13:22:19 |
current_timestamp |
YYYY-MM-DD HH:MM:SS | 2025-06-15 19:50:50 |
หมายเหตุ: รูปแบบเหล่านี้ไม่มีตัวบ่งชี้ UTC 'Z' โดยค่าเริ่มต้น
ความสับสนเรื่องการปฏิบัติตาม ISO 8601
จุดสับสนอีกประการหนึ่งเกี่ยวข้องกับการอ้างสิทธิ์ของ SQLite เรื่องการปฏิบัติตาม ISO 8601 ฟังก์ชัน current_timestamp
ส่งคืนวันที่ในรูปแบบเช่น 2025-06-15 19:50:50
โดยใช้ตัวคั่นช่องว่างแทนอักขระ 'T' ที่คาดหวังโดยทั่วไปในรูปแบบ ISO 8601 สิ่งนี้สร้างความไม่สอดคล้องเมื่อทำงานกับเมธอด .toISOString()
ของ JavaScript ซึ่งสร้างสตริง ISO ที่จัดรูปแบบอย่างถูกต้อง
แม้ว่าบางคนจะโต้แย้งว่าการใช้ช่องว่างแทน 'T' ได้รับอนุญาตภายใต้การตีความบางประการของมาตรฐาน ISO 8601 แต่เอกสารไม่ได้อธิบายความแตกต่างนี้อย่างชัดเจน มาตรฐานอนุญาตให้ละเว้นตัวคั่น 'T' โดยข้อตกลงร่วมกันในแอปพลิเคชันเฉพาะ แต่การแทนที่ด้วยช่องว่างไม่ได้รับอนุญาตอย่างชัดเจนในข้อกำหนดหลัก
วิธีแก้ปัญหาชั่วคราว
การเพิ่ม UTC Indicator แบบแมนนวล:
strftime('%Y-%m-%dT%H:%M:%SZ')
- รูปแบบ UTC พื้นฐานพร้อม Zstrftime('%Y-%m-%dT%H:%M:%fZ')
- รูปแบบ UTC พร้อมเศษส่วนของวินาที
วิธีการจัดเก็บข้อมูลทางเลือก:
- จัดเก็บเป็น INTEGER (Unix epoch มิลลิวินาที/นาโนวินาที)
- ใช้ Julian day numbers สำหรับวันที่ในอดีต
- ใช้งาน custom JSON serialization สำหรับ time zones ที่ซับซ้อน
แนวทางการจัดเก็บทางเลือก
นักพัฒนาหลายคนได้เลิกใช้ฟังก์ชัน datetime แบบสตริงของ SQLite ทั้งหมด การจัดเก็บ timestamps เป็นจำนวนเต็มที่แสดงมิลลิวินาทีหรือนาโนวินาทีตั้งแต่ Unix epoch กลายเป็นทางเลือกที่ได้รับความนิยม แนวทางนี้มีข้อดีหลายประการ: ประมวลผลเร็วกว่า ใช้พื้นที่จัดเก็บน้อยกว่า และหลีกเลี่ยงความไม่สอดคล้องในการจัดรูปแบบโดยสิ้นเชิง
อย่างไรก็ตาม แนวทางแบบจำนวนเต็มนี้มาพร้อมกับการแลกเปลี่ยนของตัวเอง วันที่แบบสตริงสามารถอ่านได้ทันทีเมื่อตรวจสอบเนื้อหาฐานข้อมูลโดยตรง ในขณะที่ timestamps แบบจำนวนเต็มต้องการการแปลงเพื่อให้มนุษย์เข้าใจ นักพัฒนาบางคนแก้ปัญหานี้โดยการสร้างมุมมองฐานข้อมูลที่แสดงวันที่ที่มนุษย์อ่านได้เมื่อจำเป็นสำหรับการตรวจสอบ
ข้อพิจารณาการย้ายฐานข้อมูล
ปัญหาการจัดรูปแบบ datetime ได้มีอิทธิพลต่อการเลือกระบบฐานข้อมูลของนักพัฒนาบางคน ฟังก์ชันวันที่ของ PostgreSQL รวมส่วนต่อท้าย 'Z' โดยอัตโนมัติสำหรับ UTC timestamps ทำให้เข้ากันได้กับแอปพลิเคชัน JavaScript มากกว่าทันที ข้อได้เปรียบด้านความเข้ากันได้นี้กลายเป็นปัจจัยในการตัดสินใจเลือกฐานข้อมูล โดยเฉพาะสำหรับแอปพลิเคชันเว็บที่พึ่งพาการประมวลผลวันที่ฝั่งไคลเอนต์อย่างมาก
สำหรับนักพัฒนาที่ต้องทำงานกับทั้ง SQLite และฐานข้อมูลอื่น ๆ ความไม่สอดคล้องในการจัดรูปแบบเหล่านี้สร้างความซับซ้อนเพิ่มเติมในการรักษาพฤติกรรมที่สอดคล้องกันในระบบฐานข้อมูลที่แตกต่างกัน
ชุมชนนักพัฒนา SQLite ยังคงหารือเกี่ยวกับปัญหาเหล่านี้ โดยผู้ใช้บางคนเสนอส่วนขยายและการปรับเปลี่ยนเพื่อปรับปรุงการจัดการ datetime อย่างไรก็ตาม พฤติกรรมการจัดรูปแบบหลักยังคงไม่เปลี่ยนแปลง ทำให้นักพัฒนาต้องใช้โซลูชันของตนเองสำหรับการรวม JavaScript ที่ราบรื่น
อ้างอิง: sqlite - Date And Time Functions