ฉันได้คิดออกเพื่อจุดประสงค์ของฉัน ฉันจะสรุปสิ่งที่ฉันได้เรียนรู้ (ขออภัยบันทึกเหล่านี้เป็นรายละเอียดพวกมันมากพอ ๆ กับการอ้างอิงในอนาคตของฉันเหมือนอย่างอื่น)
ตรงกันข้ามกับสิ่งที่ฉันพูดในความคิดเห็นก่อนหน้านี้ช่อง DATETIME และ TIMESTAMP จะทำงานแตกต่างกัน ช่อง TIMESTAMP (ตามที่เอกสารระบุ) รับสิ่งที่คุณส่งในรูปแบบ "YYYY-MM-DD hh: mm: ss" และแปลงจากเขตเวลาปัจจุบันของคุณเป็นเวลา UTC การย้อนกลับเกิดขึ้นอย่างโปร่งใสทุกครั้งที่คุณดึงข้อมูล ช่อง DATETIME ไม่ทำให้เกิด Conversion นี้ พวกเขานำสิ่งที่คุณส่งไปและจัดเก็บไว้โดยตรง
ทั้งชนิดเขตข้อมูลการประทับเวลา DATETIME มิได้ถูกต้องสามารถเก็บข้อมูลในเขตที่ตั้งข้อสังเกต DST หากคุณจัดเก็บ "2009-11-01 01:30:00" ช่องจะไม่มีทางแยกได้ว่าคุณต้องการเวอร์ชันใดของ 01:30 น. - เวอร์ชัน -04: 00 หรือ -05: 00 น.
ตกลงดังนั้นเราต้องจัดเก็บข้อมูลของเราในเขตเวลาที่ไม่ใช่ DST (เช่น UTC) ช่อง TIMESTAMP ไม่สามารถจัดการข้อมูลนี้ได้อย่างถูกต้องด้วยเหตุผลที่ฉันจะอธิบาย: หากระบบของคุณตั้งค่าเป็นเขตเวลา DST สิ่งที่คุณใส่ไว้ใน TIMESTAMP อาจไม่ใช่สิ่งที่คุณได้รับคืน แม้ว่าคุณจะส่งข้อมูลที่แปลงเป็น UTC ไปแล้ว แต่ก็ยังถือว่าข้อมูลอยู่ในเขตเวลาท้องถิ่นของคุณและทำการแปลงเป็น UTC อีกครั้ง การเดินทางไปกลับในท้องถิ่นถึง UTC-back-to-local ที่บังคับใช้ TIMESTAMP นี้จะสูญเสียไปเมื่อเขตเวลาท้องถิ่นของคุณสังเกต DST (ตั้งแต่ "2009-11-01 01:30:00" จะจับคู่เวลาที่เป็นไปได้ 2 แบบ)
ด้วย DATETIME คุณสามารถจัดเก็บข้อมูลของคุณในเขตเวลาใดก็ได้ที่คุณต้องการและมั่นใจได้ว่าคุณจะได้รับสิ่งที่คุณส่งกลับมา (คุณไม่ได้ถูกบังคับให้ต้องรับการแปลงแบบไปกลับที่สูญเสียซึ่ง TIMESTAMP จะส่งผลให้คุณ) ดังนั้นวิธีแก้ปัญหาคือใช้ฟิลด์ DATETIME และก่อนที่จะบันทึกลงในฟิลด์ให้แปลงจากโซนเวลาระบบของคุณเป็นโซนที่ไม่ใช่ DST ที่คุณต้องการบันทึกไว้ (ฉันคิดว่า UTC น่าจะเป็นตัวเลือกที่ดีที่สุด) สิ่งนี้ช่วยให้คุณสร้างตรรกะการแปลงเป็นภาษาสคริปต์ของคุณเพื่อให้คุณสามารถบันทึกค่า UTC ที่เทียบเท่ากับ "2009-11-01 01:30:00 -04: 00" หรือ "" 2009-11-01 01:30 ได้อย่างชัดเจน: 00 -05: 00 น.”.
สิ่งสำคัญอีกอย่างที่ควรทราบคือฟังก์ชันคณิตศาสตร์วันที่ / เวลาของ MySQL ทำงานไม่ถูกต้องตามขอบเขต DST หากคุณจัดเก็บวันที่ของคุณใน DST TZ ดังนั้นเหตุผลอื่น ๆ ทั้งหมดที่จะบันทึกใน UTC
สรุปตอนนี้ฉันทำสิ่งนี้:
เมื่อดึงข้อมูลจากฐานข้อมูล:
ตีความข้อมูลจากฐานข้อมูลอย่างชัดเจนว่าเป็น UTC นอก MySQL เพื่อให้ได้เวลาประทับของ Unix ที่ถูกต้อง ฉันใช้ฟังก์ชัน strtotime () ของ PHP หรือคลาส DateTime สำหรับสิ่งนี้ ไม่สามารถทำได้อย่างน่าเชื่อถือภายใน MySQL โดยใช้ฟังก์ชัน CONVERT_TZ () หรือ UNIX_TIMESTAMP () ของ MySQL เนื่องจาก CONVERT_TZ จะแสดงเฉพาะค่า 'YYYY-MM-DD hh: mm: ss' ซึ่งมีปัญหาด้านความคลุมเครือและ UNIX_TIMESTAMP () จะถือว่า อินพุตอยู่ในเขตเวลาของระบบไม่ใช่เขตเวลาที่ข้อมูลถูกเก็บไว้ใน (UTC) จริง
เมื่อจัดเก็บข้อมูลลงในฐานข้อมูล:
แปลงวันที่ของคุณเป็นเวลา UTC ที่แม่นยำที่คุณต้องการนอก MySQL ตัวอย่างเช่นด้วยคลาส DateTime ของ PHP คุณสามารถระบุ "2009-11-01 1:30:00 EST" ให้แตกต่างจาก "2009-11-01 1:30:00 EDT" จากนั้นแปลงเป็น UTC และบันทึกเวลา UTC ที่ถูกต้อง ไปยังช่อง DATETIME ของคุณ
วุ้ย. ขอบคุณมากสำหรับข้อมูลและความช่วยเหลือของทุกคน หวังว่าสิ่งนี้จะช่วยให้คนอื่นปวดหัวได้บ้าง
BTW ฉันเห็นสิ่งนี้ใน MySQL 5.0.22 และ 5.0.27