เวลาดูเหมือนง่ายจนกว่าคุณจะลองเขียนซอฟต์แวร์ที่จัดการมันอย่างถูกต้อง อีเวนต์ที่นัดไว้ "บ่าย 3" มีความหมายต่างกันในโตเกียว ลอนดอน และนิวยอร์ก Daylight saving time เลื่อนนาฬิกาไปข้างหน้าหรือข้างหลัง — แต่ไม่ใช่ทุกที่ และไม่ใช่ในวันเดียวกัน Timestamp ที่ดูถูกต้องในสภาพแวดล้อม local ของคุณพังใน production เพราะเซิร์ฟเวอร์อยู่ในโซนที่ต่างกัน
Time zone เป็นหนึ่งในหัวข้อที่สับสนอย่างน่าเชื่อถือที่สุดในการพัฒนาซอฟต์แวร์ บทความนี้อธิบายว่ามันทำงานอย่างไร ความซับซ้อนมาจากไหน และวิธีหลีกเลี่ยงข้อผิดพลาดที่พบบ่อยที่สุด
ทำไมถึงมี Time Zone
โลกหมุน 360 องศาใน 24 ชั่วโมง ซึ่งหมายความว่าดวงอาทิตย์อยู่ที่จุดสูงสุดในเวลาที่ต่างกันขึ้นอยู่กับลองจิจูดของคุณ ก่อนศตวรรษที่ 19 ทุกเมืองตั้งนาฬิกาตามเวลาดวงอาทิตย์ท้องถิ่น — เที่ยงคือเมื่อดวงอาทิตย์อยู่เหนือหัว สิ่งนี้ใช้ได้ดีจนกระทั่งรถไฟเชื่อมต่อเมืองที่ห่างไกลและตารางรถไฟต้องการนาฬิกาที่สม่ำเสมอเพียงตัวเดียว
ในปี 1884 ผู้แทนจาก 25 ประเทศพบกันที่การประชุม International Meridian ในวอชิงตัน ดี.ซี. และตกลงแบ่งโลกออกเป็น 24 time zone มาตรฐาน แต่ละโซน offset จาก prime meridian (ลองจิจูด 0 องศา) ที่ผ่านกรีนิช ประเทศอังกฤษ
ในทางปฏิบัติ ขอบเขต time zone เป็นไปตามเขตแดนทางการเมือง ไม่ใช่เส้นลองจิจูดที่เรียบร้อย จีนครอบคลุมห้าโซนทางภูมิศาสตร์แต่ใช้เวลาเดียว (UTC+8) อินเดียใช้ UTC+5:30 — offset ครึ่งชั่วโมง เนปาลใช้ UTC+5:45 แผนที่จริงของ time zone นั้นยุ่งเหยิง
UTC กับ GMT
GMT (Greenwich Mean Time) คือเวลาดวงอาทิตย์เฉลี่ยที่หอดูดาวหลวงในกรีนิช เป็นเวลาอ้างอิงของโลกมากกว่าหนึ่งศตวรรษ
UTC (Coordinated Universal Time) แทนที่ GMT เป็นมาตรฐานสากลในปี 1972 UTC อิงจากนาฬิกาอะตอมแทนการสังเกตทางดาราศาสตร์ ทำให้แม่นยำกว่ามาก สำหรับวัตถุประสงค์เชิงปฏิบัติส่วนใหญ่ UTC และ GMT แสดงเวลาเดียวกัน แต่ UTC เป็นข้อมูลอ้างอิงทางเทคนิคที่ถูกต้อง
ทำไม "UTC" ไม่ใช่ "CUT"? ตัวย่อนี้เป็นการประนีประนอมระหว่างภาษาอังกฤษ "Coordinated Universal Time" (CUT) และภาษาฝรั่งเศส "Temps Universel Coordonné" (TUC) ไม่มีฝ่ายใดได้ตัวย่อที่ต้องการ จึงเลือก UTC เป็นทางเลือกที่เป็นกลางทางภาษา
Daylight Saving Time: ความวุ่นวายที่เป็นระเบียบ
ประมาณ 70 ประเทศปฏิบัติตาม Daylight Saving Time (DST) เลื่อนนาฬิกาไปข้างหน้าหนึ่งชั่วโมงในฤดูใบไม้ผลิและย้อนกลับในฤดูใบไม้ร่วง จุดประสงค์คือให้ชั่วโมงตื่นสอดคล้องกับแสงแดด ผลลัพธ์คือแหล่งที่มาของบั๊กทุกครึ่งปี
ความซับซ้อนหลัก:
- ไม่เป็นสากล แอฟริกา เอเชีย และอเมริกาใต้ส่วนใหญ่ไม่ปฏิบัติตาม DST ใน US, Arizona และ Hawaii ไม่ร่วมด้วย
- วันที่ต่างกัน EU เปลี่ยนวันอาทิตย์สุดท้ายของมีนาคมและตุลาคม US เปลี่ยนวันอาทิตย์ที่สองของมีนาคมและวันอาทิตย์แรกของพฤศจิกายน พวกเขาไม่ตรงกันหลายสัปดาห์ในแต่ละปี
- เวลาที่กำกวม เมื่อนาฬิกาย้อนกลับ ชั่วโมงตั้งแต่ตี 1 ถึงตี 2 เกิดขึ้นสองครั้ง Timestamp "1:30 AM" ในวันนั้นกำกวม
- เวลาที่ข้ามไป เมื่อนาฬิกาเลื่อนไปข้างหน้า ชั่วโมงตั้งแต่ตี 2 ถึงตี 3 ไม่มีอยู่ การประชุมที่นัดไว้ตี 2:30 ในวันนั้นไม่เกิดขึ้น
- การเปลี่ยนแปลงทางการเมือง รัฐบาลสามารถ (และทำ) เปลี่ยนกฎ DST โดยแจ้งล่วงหน้าเล็กน้อย รัสเซียนำ DST ถาวรมาใช้ในปี 2011 แล้วเปลี่ยนเป็นเวลามาตรฐานถาวรในปี 2014 โมร็อกโกเปลี่ยนกฎ DST หลายครั้ง
ISO 8601: รูปแบบวันที่สากล
เพื่อหลีกเลี่ยงความกำกวม มาตรฐานสากล ISO 8601 กำหนดรูปแบบวันที่และเวลาที่ชัดเจน:
2026-03-29T14:30:00Z
2026-03-29T14:30:00+02:00
2026-03-29T14:30:00-05:00
Tแยกวันที่จากเวลาZหมายถึง UTC (time zone "Zulu" ในคำศัพท์ทหาร)+02:00หรือ-05:00คือ UTC offset
รูปแบบนี้ไม่กำกวม เรียงลำดับเป็นข้อความธรรมดาได้ และเข้าใจได้ทั่วไปโดยไลบรารี date parsing เมื่อสงสัย ใช้ ISO 8601
Unix Timestamp
Unix timestamp (เรียกอีกอย่างว่า epoch time หรือ POSIX time) คือจำนวนวินาทีที่ผ่านไปตั้งแต่ 1 มกราคม 1970, 00:00:00 UTC — ช่วงเวลาที่เรียกว่า Unix epoch
| อ่านได้โดยมนุษย์ | Unix timestamp |
|---|---|
| 1970-01-01 00:00:00 UTC | 0 |
| 2000-01-01 00:00:00 UTC | 946684800 |
| 2026-03-29 12:00:00 UTC | 1774987200 |
Unix timestamp ไม่มี time zone — เป็น UTC เสมอ ทำให้เหมาะสำหรับการจัดเก็บและเปรียบเทียบเวลาในซอฟต์แวร์ คุณแปลงเป็น time zone ท้องถิ่นเฉพาะที่ชั้นการแสดงผล
ปัญหาปี 2038: ระบบที่จัดเก็บ Unix timestamp เป็น 32-bit signed integer จะ overflow ในวันที่ 19 มกราคม 2038 เวลา 03:14:07 UTC ค่าสูงสุด (2,147,483,647) จะกลายเป็นตัวเลขลบ ถูกตีความว่าเป็นเดือนธันวาคม 1901 ระบบสมัยใหม่ส่วนใหญ่ใช้ 64-bit integer ซึ่งจะไม่ overflow อีก 292 พันล้านปี
ฐานข้อมูล IANA Time Zone
ซอฟต์แวร์ไม่ได้ต้องการแค่ UTC offset — ต้องรู้ประวัติทั้งหมดและกฎในอนาคตสำหรับแต่ละภูมิภาค รวมถึงการเปลี่ยนผ่าน DST การเปลี่ยนแปลงทางการเมือง และความผิดปกติทางประวัติศาสตร์ ข้อมูลนี้อยู่ใน IANA Time Zone Database (เรียกอีกอย่างว่า Olson database หรือ tzdata)
ใช้ identifier เช่น America/New_York, Europe/Paris, Asia/Tokyo แต่ละรายการเข้ารหัสประวัติทั้งหมดของ UTC offset และกฎ DST สำหรับสถานที่นั้น
นี่คือเหตุผลที่คุณไม่ควรจัดเก็บ time zone เป็น offset คงที่เช่น "+02:00" Offset บอกคุณแค่ความแตกต่างปัจจุบันจาก UTC แต่ไม่บอกอะไรเกี่ยวกับกฎ DST Europe/Paris คือ UTC+1 ในฤดูหนาวและ UTC+2 ในฤดูร้อน IANA identifier จับทั้งสองกรณี
บั๊กทั่วไปในซอฟต์แวร์
- จัดเก็บเวลาท้องถิ่นโดยไม่มี time zone ค่าอย่าง
2026-03-29 14:30:00ไม่มีความหมายโดยไม่รู้ว่าอ้างถึง time zone ไหน จัดเก็บ UTC เสมอหรือรวม offset - สมมติว่า UTC offset เท่ากับ time zone UTC+2 ในเดือนมีนาคมอาจเป็น UTC+3 ในเดือนกรกฎาคม (ถ้าภูมิภาคปฏิบัติตาม DST) จัดเก็บ IANA identifier ไม่ใช่ offset
- ละเว้นการเปลี่ยนผ่าน DST ในการตั้งเวลา งานประจำวันตี 2:30 จะข้ามปีละครั้งและทำงานสองครั้งปีละครั้งถ้าคุณไม่จัดการ DST
- สมมติว่าวันมี 24 ชั่วโมง ในวันเปลี่ยนผ่าน DST วันหนึ่งมี 23 หรือ 25 ชั่วโมง การคำนวณ "พรุ่งนี้เวลาเดียวกัน" โดยบวก 86,400 วินาทีจะคลาดเคลื่อนหนึ่งชั่วโมง
- ใช้ JavaScript
Dateอย่างไม่ระมัดระวังnew Date("2026-03-29")ถูก parse เป็น UTC ในบาง engine และเป็นเวลาท้องถิ่นในบางตัว ระบุ time zone ให้ชัดเจนเสมอ
แนวปฏิบัติที่ดีที่สุดสำหรับนักพัฒนา
- จัดเก็บเวลาเป็น UTC แปลงเป็น time zone ท้องถิ่นของผู้ใช้เฉพาะที่ชั้นการนำเสนอ
- ใช้ IANA time zone identifier (
America/New_York) ไม่ใช่ offset คงที่ (-05:00) - ใช้ ISO 8601 สำหรับ serialization ไม่กำกวมและ parse ได้ทั่วไป
- ใช้ไลบรารี date ที่สมบูรณ์ ใน JavaScript ใช้
Intl.DateTimeFormatหรือไลบรารีเช่นdate-fns-tzใน Python ใช้zoneinfo(3.9+) หรือpytzใน Java ใช้java.time.ZonedDateTime - อัปเดต
tzdataให้ทันสมัย รัฐบาลเปลี่ยนกฎ DST ระบบปฏิบัติการและ runtime ของภาษาต้องมีข้อมูล timezone ที่เป็นปัจจุบัน - ทดสอบด้วย time zone หลายตัว อย่าสมมติว่าเซิร์ฟเวอร์และผู้ใช้แชร์โซนเดียวกัน
เรียนรู้เพิ่มเติม
เวลานั้นซับซ้อนอย่างน่าหลอกลวง แต่กฎต่าง ๆ มีการบันทึกไว้อย่างดีและเครื่องมือก็สมบูรณ์ กุญแจสำคัญคือเคารพความซับซ้อนแทนที่จะสมมติว่ามันไม่มี
- Cron Expression ไขความลับ — ตั้งเวลางานข้าม time zone
- Hash Generator และ Regex Tester — เครื่องมือสำหรับนักพัฒนาเพิ่มเติมบน ToolK
