

ข้อมูลเวลาเดินผ่านหลายส่วนของระบบ ตั้งแต่หน้าจอที่ผู้ใช้กรอก API ที่รับค่า ฐานข้อมูล ไปจนถึงหน้ารายงาน หากแต่ละจุดสมมติ timezone ไม่ตรงกัน เวลาเดียวกันอาจถูกแสดงต่างรูปแบบ หรือร้ายกว่านั้นคือถูกตีความเป็นคนละเหตุการณ์ตั้งแต่ตอนเก็บ
การเห็นตัวเลขเวลาในเครื่องมือฐานข้อมูลต่างจากหน้าเว็บจึงยังต้องแยกก่อนว่าเป็นการแสดงผลของ instant เดียวกัน หรือข้อมูลถูกแปลงผิดจริง หากรีบชดเชยด้วยการบวกชั่วโมงทั้งชุด อาจไปแก้ค่าที่เก็บถูกอยู่แล้วจนผิดแทน
แอดว่าเรื่องนี้เริ่มจากถามความหมายของ field ก่อนครับ ว่าต้องการเก็บเหตุการณ์หนึ่งจุดบนเส้นเวลา วันที่ในปฏิทิน หรือเวลาที่คนคาดหวังในพื้นที่หนึ่ง แล้วค่อยเลือกชนิดข้อมูลและข้อตกลงการรับส่งให้ตรงกัน
เวลาที่รายการถูกสร้างหรืออุปกรณ์รายงานเหตุการณ์มักต้องอ้าง instant ที่คนละระบบเทียบกันได้ ส่วนวันนัดหมายตามปฏิทินหรือเวลาเปิดร้านเป็นข้อมูลอีกลักษณะที่อาจต้องรักษาความหมายท้องถิ่นไว้ตามงาน
ตัวอย่างสมมติ 2026-01-01T12:00:00+07:00 กับ 2026-01-01T05:00:00Z ระบุ instant เดียวกันในรูปที่มี offset ต่างกัน นี่เป็นการแปลงตาม offset ของตัวอย่าง ไม่ใช่ผลทดลองของฐานข้อมูลหรือข้อสรุปเรื่องเวลาท้องถิ่นทุกพื้นที่

หากเก็บวันที่อย่างเดียว การแปลงเป็นเวลาเที่ยงคืนใน timezone หนึ่งแล้วส่งให้ทุกคนแสดงอาจทำให้บางหน้ากลายเป็นวันก่อนหน้าได้ ควรใช้ชนิด date กับข้อตกลงวันที่ล้วนเมื่อเหมาะกับความหมาย ไม่สร้าง instant ขึ้นมาโดยไม่จำเป็น
ส่วนงานนัดหมายในอนาคตที่ต้องยึดพื้นที่ ต้องพิจารณาชื่อ timezone กับกติกาตารางเวลาเพิ่ม การเก็บ offset ปัจจุบันเพียงตัวเดียวไม่ได้แทนกฎของพื้นที่ตลอดทุกวันในอนาคต จึงต้องเลือกข้อมูลจากคำถามของงานจริง
PostgreSQL มี timestamp without time zone กับ timestamp with time zone ซึ่งนิยมเรียกสั้นว่า timestamptz แบบแรกเก็บวันและเวลาโดยไม่มีความหมาย timezone ติดอยู่ในชนิดข้อมูล ส่วนแบบหลังแทน instant โดยมีขั้นตีความ timezone ตอนรับและตอนแสดง
สำหรับ timestamptz เอกสารระบุว่าเก็บภายในเป็น UTC และไม่รักษาชื่อ timezone เดิมที่ผู้เรียกส่งหรือระบบสมมติไว้ การอ่านกลับจึงอาจแสดงตาม TimeZone ของ session ไม่ใช่คืนข้อความ offset เดิมเหมือนที่กรอกมาทุกครั้ง
ชื่อ with time zone จึงไม่ควรถูกเข้าใจว่าเป็นที่เก็บชื่อพื้นที่ต้นฉบับครบอยู่แล้ว หากงานต้องรู้ว่าผู้ใช้เลือกเขตเวลาใด เช่น สำหรับการนัดครั้งถัดไป อาจต้องเก็บชื่อ timezone แยกตามข้อตกลงของแอปด้วย
ส่วน timestamp without time zone ไม่ควรถูกนำมาใช้เหมือน instant โดยไม่มีข้อตกลงเพิ่ม การแนบ offset ในข้อความเข้าไปไม่ได้เปลี่ยนชนิดของคอลัมน์ให้รักษาความหมายแบบ timestamptz โดยอัตโนมัติ ต้องตรวจชนิดที่ parser กับฐานข้อมูลใช้จริง
ถ้า API รับข้อความเวลาโดยไม่มี offset แล้วแต่ละส่วนเลือกตีความตามค่าของเครื่องหรือ session ผลอาจต่างกันเมื่อย้าย environment หรือเปลี่ยนการเชื่อมต่อ การส่งค่าที่มีความหมายชัดช่วยลดการพึ่งค่าแวดล้อมที่ไม่มีใครตั้งใจให้เป็นข้อตกลง
ควรกำหนดในสัญญา API ว่า field ใดเป็น instant ที่ต้องมี offset หรือใช้รูป UTC และ field ใดเป็นวันที่หรือเวลาท้องถิ่นพร้อมชื่อ timezone แล้วตรวจข้อมูลก่อนเก็บ ไม่ใช้การเติม Z ลงท้ายทุกข้อความเพื่อทำให้ดูเหมือนเป็น UTC โดยยังไม่รู้ความหมายต้นทาง

การใช้ connection pool ยังทำให้ต้องระวัง state ระดับ session ถ้ามีโค้ดเปลี่ยน TimeZone แล้วคืน connection โดยไม่ดูข้อตกลงของ pool ผู้เรียกถัดไปอาจเห็นพฤติกรรมต่างจากที่คาด จึงควรจัด configuration และการแปลงอย่างมีขอบเขต
ในหน้าจอ เครื่องมือดูข้อมูลกับ browser อาจตั้ง zone สำหรับแสดงต่างกัน การตรวจควรอ่านค่าพร้อมชนิดและ context ไม่เทียบเพียง string ที่เห็นแล้วสรุปว่าถูกเก็บผิดทันที
PostgreSQL มี AT TIME ZONE สำหรับการแปลงที่มีความหมายต่างกันตามชนิดฝั่งเข้า จึงต้องรู้ว่ากำลังตีความเวลาที่ไม่มี zone ให้เป็น instant หรือกำลังแสดง instant ในเวลาของพื้นที่ใด ไม่ใช้ expression เดียวกันซ้อนหลายรอบโดยไม่ตามชนิดที่ได้
หากพบข้อมูลเก่าที่เก็บ timestamp โดยไม่มี zone ต้องหาข้อตกลงเดิมก่อนว่าตอนเขียนหมายถึงพื้นที่ใด และมีช่วงใดที่ต้นทางเปลี่ยนพฤติกรรมหรือไม่ การเลือก zone เดียวแปลงทั้งตารางอาจถูกสำหรับบางส่วนและผิดอีกส่วนได้
การย้ายชนิดข้อมูลจึงควรใช้สำเนาทดสอบกับรายการตัวแทนที่มีหลักฐานต้นทาง เช่น เหตุการณ์ที่มี offset ชัด แล้วอ่านกลับผ่านเส้นทางเดียวกับแอป ไม่ตรวจเฉพาะค่าที่เครื่องมือฐานข้อมูลหนึ่งตัวแสดง
กรณีที่ยังไม่มีหลักฐานพอ ควรเก็บความไม่แน่ใจไว้และแยกข้อมูลที่ยืนยันได้ ไม่แต่ง timezone ต้นฉบับจากที่ตั้งของเจ้าของเว็บหรือเวลาที่คุ้น เพราะคนส่งข้อมูลหรือระบบก่อนหน้าอาจอยู่คนละบริบท
รายงานที่บอกว่าวันนี้มีรายการเท่าไรต้องนิยามว่าวันนี้ตาม timezone ใด แล้วแปลงขอบเขตเริ่มกับสิ้นสุดให้ตรงชนิดข้อมูลก่อน query การตัดวันจากรูปแสดงผลของอีก session อาจทำให้รายการใกล้เที่ยงคืนอยู่คนละวันกับที่ผู้ใช้คาด
หากใช้ช่วงครึ่งเปิดตั้งแต่ต้นวันจนก่อนต้นวันถัดไป ควรคำนวณขอบเขตจากปฏิทินและ timezone ที่เลือก ไม่สมมติว่าทุกวันที่เกี่ยวกับทุกพื้นที่ยาวเท่ากันตามหน่วยวินาทีเสมอไป ทั้งนี้ต้องตรวจเครื่องมือวันเวลาที่ระบบใช้จริงด้วย
ชุดทดสอบควรมีเวลาใกล้ขอบวัน ข้อมูลที่ระบุ offset ต่างกันแต่เป็น instant เดียวกัน และ field วันที่ล้วน รวมถึงเส้นทางจาก API ถึงหน้าจอ เพื่อให้รู้ว่าการแปลงเกิดตรงไหนและเกิดซ้ำโดยไม่ตั้งใจหรือไม่
เวลาควรถูกเก็บตามความหมายของงานก่อนเลือกรูปแสดง timestamp กับ timestamptz ตอบคนละข้อตกลง และ instant เดียวอาจแสดงต่างกันตาม zone เมื่อกำหนดขอบเขตที่ API ฐานข้อมูล และหน้าจอให้ตรง แล้วตรวจชนิดก่อนแปลง เราจะตามความต่างได้โดยไม่แก้ข้อมูลทั้งชุดจากข้อความเวลาที่เห็นเพียงจุดเดียว