Bangkok ไม่ได้เป็น +07:00 มาตลอด
ร้านของคุณอยู่ใน Bangkok ออเดอร์ที่สั่งเวลา 09:00 ของวันที่ 2026-10-02 ออกจาก Java กับ Go
เป็น 2026-10-02T09:00:00+07:00 offset ของร้านคือ +07:00 และไม่มีใครสงสัยค่านี้
สมมติว่าร้านกำลังย้ายข้อมูลจากระบบเดิม ระบบเดิมเติม 1900-01-01 00:00 ลงในช่องวันส่งของออเดอร์
ที่ยังไม่มีวันส่ง เป็นค่าแทน “ยังไม่กำหนด” แล้ว service ใหม่อ่านค่านั้นในโซน Asia/Bangkok
คำถามของบทนี้มีสองข้อ ข้อแรกคือ offset ของ Bangkok ในวันนั้นคืออะไร ข้อที่สองคือ
ห้าภาษาพิมพ์มันออกมาเหมือนกันไหม คำตอบของข้อแรกคือไม่ใช่ +07:00 และคำตอบของข้อที่สองคือไม่เหมือน
ทั้งที่ instant ที่วัดได้ตรงกันทุกค่า
orderctl คือเครื่องมือประมวลผลออเดอร์ที่คอร์สภาษาในเสานี้สร้างซ้ำทีละภาษา repo ตัวอย่าง
กำลังจัดทำ
ระหว่างนี้ทุกค่าในบทนี้รันเองได้ด้วย npm run verify:time-semantics
ซึ่งเรียก python3 scripts/time-semantics/probe.py · ไม่ต้องมี Docker แต่การรันครั้งแรก
ต้องต่อเน็ตเพื่อดึง chrono กับ chrono-tz จาก crates.io
เวลาของ Bangkok ก่อนจะเป็น +07:00
หัวข้อที่มีชื่อว่า “เวลาของ Bangkok ก่อนจะเป็น +07:00”tzdata ให้
Asia/Bangkokในปี 1900 ใช้ offset ที่มีเศษวินาที เพราะมันเป็นเวลาที่ตั้งตามดวงอาทิตย์ของเมือง
ก่อนจะมีโซนมาตรฐาน แต่ละเมืองตั้งนาฬิกาตามดวงอาทิตย์ของตัวเอง เวลาแบบนี้เรียกว่า local mean timelocal mean time (LMT)เวลาท้องถิ่นที่ตั้งตามดวงอาทิตย์ของเมืองนั้น ก่อนที่จะมีโซนมาตรฐาน · offset ของมันจึงมีเศษวินาที Bangkok ในปี 1900 ใช้ +06:42:04 และ tzdata ยังเก็บกฎนั้นไว้สำหรับวันที่ในช่วงนั้น (เวลาท้องถิ่นที่ตั้งตามดวงอาทิตย์ ย่อว่า LMT) offset ของมันจึงไม่ลงตัวที่นาที
ซอร์สของ tzdata เก็บกฎของ Asia/Bangkok ไว้ใน file ชื่อ asia แถวต้นๆ ของโซนนี้ใช้ offset
เดียวกับ +06:42:04 ช่วงแรกใช้ชื่อย่อ LMT ช่วงถัดมาใช้ชื่อย่อ BMT และมีคอมเมนต์ขยายว่า
“Bangkok Mean Time” แถวสุดท้ายคือ offset +07:00 ที่ใช้มาถึงวันนี้
1900-01-01 ตกอยู่ในแถวของ BMT ซึ่งเป็น local mean time ของ Bangkok เอง สามภาษาที่ probe
อ่านชื่อย่อได้ คือ Go, Python และ Rust ตอบ BMT ตรงกันทั้งสามภาษา
ข้อมูลชุดนี้ไม่ได้มาพร้อมระบบปฏิบัติการเสมอไป แต่ละภาษาได้มันมาคนละทาง และแต่ละทางอาจเป็นคนละรุ่น รุ่นของข้อมูลที่ภาษานั้นอ่านจริงตอนรันเรียกว่า tzdata versiontzdata versionรุ่นของ IANA tz database ที่ภาษานั้นใช้อยู่จริงตอนรัน · ภาษาต่างกันบนเครื่องเดียวกันอาจใช้คนละรุ่น ตารางที่เทียบผลหลายภาษาจึงต้องระบุรุ่นของทุกภาษา ไม่ใช่รุ่นเดียวของเครื่อง (รุ่นของ tzdata) บนเครื่องที่วัด ห้าภาษาอ่านสามรุ่น
- Java
openjdk 25.0.4.1อ่านรุ่น2026bจากtzdb.datของ JDK - Node
v24.19.0อ่านรุ่น2026bจาก ICU ที่ฝังใน node - Go
go1.27.0อ่านรุ่น2026cจาก/usr/share/zoneinfoของระบบ - Python
3.14.6อ่านรุ่น2026cจาก/usr/share/zoneinfoของระบบ - Rust อ่านรุ่น
2025bที่ฝังในchrono-tz0.10.4
ข้ออ้างของบทนี้ยืนอยู่ได้บนสามรุ่นนั้น เพราะสี่ภาษาที่อ่าน offset เป็นวินาทีได้ค่าเดียวกันทั้งสี่ภาษา ถ้ากฎของ Bangkok ในปี 1900 ถูกแก้ในรุ่นหน้า probe จะแดง ไม่ใช่บทเรียนที่ผิดเงียบๆ
flowchart LR A["1900-01-01 00:00 ที่ Asia/Bangkok"] --> B["tzdata ตอบ offset +06:42:04"] B --> C["instant 1899-12-31T17:17:56Z"] B --> D["ตัวพิมพ์ที่มีช่องวินาทีของ offset"] B --> E["ตัวพิมพ์ที่ไม่มีช่องวินาทีของ offset"] D --> F["+06:42:04 · Java · Python · layout ที่ Go เขียนเอง"] E --> G["+06:42 · time.RFC3339 ของ Go · to_rfc3339 ของ chrono"] E --> H["GMT+0642 · toString ของ Node ที่ TZ=Asia/Bangkok"]
คำบรรยายภาพ: ค่าที่ทุกภาษาเก็บไว้มีสี่วินาทีครบ และ instant ที่วัดได้ตรงกัน ส่วนที่แยกภาษาออกจากกันอยู่ที่ปลายทาง คือรูปแบบของสตริงที่ใช้พิมพ์ offset ออกมา
ห้าภาษาอ่าน offset ได้ค่าเดียวกัน
หัวข้อที่มีชื่อว่า “ห้าภาษาอ่าน offset ได้ค่าเดียวกัน”สี่ภาษาที่อ่าน offset เป็นวินาทีได้
24124และทุก instant ที่ probe อ่านจากเวลานี้ของ Bangkok ชี้จุดเดียวกับ1899-12-31T17:17:56Z
ทุกการเรียกข้างล่างตัดมาจาก runner ของ probe ใน scripts/time-semantics/runners/ และค่าในคอมเมนต์
คือค่าที่ probe วัดได้
1900-01-01 00:00 ของ Asia/Bangkok ไม่ได้ตกอยู่ในช่วงที่นาฬิกาของโซนนั้นกระโดดหรือถอย
probe จึงผูกค่าของ Go ในทรงนี้เป็นข้ออ้างได้ ต่างจากค่าของ Go ใน
บทที่ 1
Java เก็บครบและพิมพ์ครบ
หัวข้อที่มีชื่อว่า “Java เก็บครบและพิมพ์ครบ”ZoneId bkk = ZoneId.of("Asia/Bangkok");ZonedDateTime b = ZonedDateTime.of(1900, 1, 1, 0, 0, 0, 0, bkk);b.getOffset().toString(); // +06:42:04b.getOffset().getTotalSeconds(); // 24124b.toString(); // 1900-01-01T00:00+06:42:04[Asia/Bangkok]DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(b); // 1900-01-01T00:00:00+06:42:04b.toInstant().toString(); // 1899-12-31T17:17:56Z24124 วินาทีคือ 6 ชั่วโมง 42 นาที กับอีก 4 วินาที และ instant ที่ได้คือ 00:00:00 ลบด้วย offset นั้น
จึงเป็น 17:17:56 ของวันก่อนหน้าใน UTC วินาทีที่ 56 คือร่องรอยของสี่วินาทีนั้น
Python เก็บครบและพิมพ์ครบ
หัวข้อที่มีชื่อว่า “Python เก็บครบและพิมพ์ครบ”from datetime import datetimefrom zoneinfo import ZoneInfo
bkk = ZoneInfo("Asia/Bangkok")b = datetime(1900, 1, 1, tzinfo=bkk)b.isoformat() # 1900-01-01T00:00:00+06:42:04int(b.utcoffset().total_seconds()) # 24124b.tzname() # BMTเอกสารของ isoformat() เขียนรูปของ offset ไว้เป็น +HH:MM[:SS[.ffffff]] คือมีช่องวินาทีที่ใส่เมื่อจำเป็น
offset ของ Bangkok ปี 1900 มีวินาที Python จึงพิมพ์มันออกมา probe ไม่ได้อ่าน instant ของ Python ในทรงนี้
Go เก็บครบ แต่พิมพ์ครบเฉพาะ layout ที่เขียนเอง
หัวข้อที่มีชื่อว่า “Go เก็บครบ แต่พิมพ์ครบเฉพาะ layout ที่เขียนเอง”bkk, err := time.LoadLocation("Asia/Bangkok")// ...t := time.Date(1900, 1, 1, 0, 0, 0, 0, bkk)name, off := t.Zone()t.Format("2006-01-02T15:04:05-07:00:00") // 1900-01-01T00:00:00+06:42:04t.Format(time.RFC3339) // 1900-01-01T00:00:00+06:42fmt.Sprint(off) // 24124name // BMTt.UTC().Format(time.RFC3339) // 1899-12-31T17:17:56Zค่า t ตัวเดียวกันให้สองสตริง layout ที่เขียนเองมี -07:00:00 ซึ่งเอกสารของ package time ระบุว่าเป็นรูป
±hh:mm:ss ส่วน time.RFC3339 คือ layout "2006-01-02T15:04:05Z07:00" ซึ่งมีแค่ชั่วโมงกับนาที
off ยังเป็น 24124 และ instant ใน UTC ยังเป็น 1899-12-31T17:17:56Z สี่วินาทีจึงไม่ได้หายจากค่าที่ Go เก็บ
มันหายตอนพิมพ์ด้วย time.RFC3339 เท่านั้น
Rust เก็บครบ แต่ to_rfc3339 พิมพ์ไม่ครบ
หัวข้อที่มีชื่อว่า “Rust เก็บครบ แต่ to_rfc3339 พิมพ์ไม่ครบ”use chrono::{Offset, TimeZone, Utc};use chrono_tz::Asia::Bangkok;
let b = Bangkok.with_ymd_and_hms(1900, 1, 1, 0, 0, 0).unwrap();b.offset().fix().local_minus_utc(); // 24124b.to_rfc3339(); // 1900-01-01T00:00:00+06:42b.with_timezone(&Utc).to_rfc3339(); // 1899-12-31T17:17:56+00:00format!("{}", b.format("%Z")); // BMTรูปแบบเดียวกับ time.RFC3339 ของ Go offset ที่อ่านเป็นวินาทียังเป็น 24124 instant ยังตรงกับ Java แต่
to_rfc3339() พิมพ์ +06:42 chrono ไม่ได้ตัดวินาทีอยู่ตัวเดียว time.RFC3339 ของ Go
ให้สตริงเดียวกันทุกตัวอักษร
Node อ่านวันที่กับชั่วโมงในโซนของ process
หัวข้อที่มีชื่อว่า “Node อ่านวันที่กับชั่วโมงในโซนของ process”new Date(1900, 0, 1) อ่านวันที่และชั่วโมงเป็นเวลาท้องถิ่น คือเวลาในโซนของ process ซึ่งมาจาก TZ
probe จึงรัน file เดียวกันสองครั้ง
// 1900-01-01 00:00 ในโซนของ process · เดือนของ Date เริ่มที่ 0const b = new Date(1900, 0, 1);b.toString();b.toISOString();b.getTimezoneOffset();TZ | toString() | toISOString() | getTimezoneOffset() |
|---|---|---|---|
Asia/Bangkok | Mon Jan 01 1900 00:00:00 GMT+0642 (Indochina Time) | 1899-12-31T17:17:56.000Z | -402 |
America/New_York | Mon Jan 01 1900 00:00:00 GMT-0500 (Eastern Standard Time) | 1900-01-01T05:00:00.000Z | 300 |
แถวแรกคือแถวที่ตอบคำถามของบทนี้ toISOString() ได้ 17:17:56 ตรงกับ Java ทุกวินาที
สี่วินาทีจึงยังอยู่ใน instant ที่ Node เก็บ
แต่อีกสองการเรียกไม่มีมัน toString() พิมพ์ GMT+0642 และ getTimezoneOffset() คืน -402
ซึ่งเป็นนาที คือ 6 ชั่วโมง 42 นาทีพอดี ชื่อในวงเล็บก็ไม่ใช่ BMT แต่เป็น Indochina Time
แถวที่สองไม่ได้ตอบคำถามของบทนี้เลย บน server ที่ตั้ง TZ=America/New_York การเรียก
new Date(1900, 0, 1) ได้ 00:00 ของ New York คือ 1900-01-01T05:00:00.000Z ไม่ใช่ 00:00 ของ Bangkok
สี่วินาทีที่หายตอนพิมพ์
หัวข้อที่มีชื่อว่า “สี่วินาทีที่หายตอนพิมพ์”ค่าที่ทุกภาษาเก็บมีสี่วินาทีครบ แต่ RFC 3339 ไม่มีช่องให้มัน และ RFC เขียนข้อนี้ไว้เอง
grammar ของ RFC 3339 นิยามช่อง offset ไว้บรรทัดเดียว
time-numoffset = ("+" / "-") time-hour ":" time-minuteไม่มี time-second ในบรรทัดนั้น สตริงที่ผ่าน grammar นี้จึงเขียน offset +06:42:04 ไม่ได้
time.RFC3339 ของ Go กับ to_rfc3339() ของ chrono ทำตาม grammar นี้ จึงได้ +06:42 ทั้งสองตัว
RFC 3339 รู้ปัญหานี้ ในหัวข้อตัวอย่างมันยกเวลาของเนเธอร์แลนด์ที่ offset มีเศษวินาที แล้วเขียนว่า “This time zone cannot be represented exactly using the HH:MM format, and this timestamp uses the closest representable UTC offset.”
ตัวอย่างของ RFC เลื่อนเวลาบนหน้าปัดตามไปด้วย เพื่อให้สตริงยังชี้ instant เดิม ส่วน Go กับ chrono
พิมพ์ 00:00:00 ตามเดิม แล้วพิมพ์ offset โดยไม่มีสี่วินาที
ผลคือสตริง 1900-01-01T00:00:00+06:42 อ่านตาม grammar แล้วชี้จุดที่ห่างจาก 1899-12-31T17:17:56Z
อยู่สี่วินาที นี่เป็นการคิดเลขจาก offset ที่วัดได้ probe ไม่ได้ parse สตริงนี้กลับ บทนี้จึงไม่พิมพ์ค่าที่ parse ได้
ฝั่งที่พิมพ์ครบก็จ่ายราคาเหมือนกัน
หัวข้อที่มีชื่อว่า “ฝั่งที่พิมพ์ครบก็จ่ายราคาเหมือนกัน”Javadoc ของ ZoneOffset.getId() แยกรูปของ offset ไว้สามแบบ และเขียนกำกับแบบที่มีวินาทีไว้ว่า
“+hh:mm:ss or -hh:mm:ss - if the seconds are non-zero (not ISO-8601)”
สตริง 1900-01-01T00:00:00+06:42:04 ของ Java และ Python จึงตรงกับ instant แต่ไม่ผ่าน grammar ของ RFC 3339
probe ไม่ได้วัดว่า parser ตัวไหนรับหรือปฏิเสธสตริงนี้ สิ่งที่พูดได้คือมันอยู่นอก grammar
สรุปเป็นสองทางที่มีราคาทั้งคู่
- สตริงที่ผ่าน RFC 3339 อย่าง
+06:42ของ Go กับ chrono ไม่มีสี่วินาที - สตริงที่มีสี่วินาทีครบ อย่าง
+06:42:04ของ Java กับ Python ไม่ผ่าน grammar ของ RFC 3339
ในค่าที่ probe วัด รูปที่ทั้งผ่าน grammar และชี้ instant ตรง คือ instant ที่เขียนเป็น UTC เช่น
1899-12-31T17:17:56Z ของ Java กับ Go เพราะ offset ของ UTC ไม่มีเศษวินาทีให้หาย
ห้าภาษา กับ offset ค่าเดียว
หัวข้อที่มีชื่อว่า “ห้าภาษา กับ offset ค่าเดียว”รวมทุกตัวพิมพ์ไว้ในตารางเดียว พร้อมรุ่นของ tzdata ที่แต่ละภาษาอ่านจริง
| ภาษา | การเรียก | ค่าที่วัดได้ | วินาทีของ offset | tzdata ที่ใช้ |
|---|---|---|---|---|
Java openjdk 25.0.4.1 | ISO_OFFSET_DATE_TIME.format(b) | 1900-01-01T00:00:00+06:42:04 | ครบ | 2026b · tzdb.dat ของ JDK |
Python 3.14.6 | b.isoformat() | 1900-01-01T00:00:00+06:42:04 | ครบ | 2026c · /usr/share/zoneinfo ของระบบ |
Go go1.27.0 | t.Format("2006-01-02T15:04:05-07:00:00") | 1900-01-01T00:00:00+06:42:04 | ครบ | 2026c · /usr/share/zoneinfo ของระบบ |
Go go1.27.0 | t.Format(time.RFC3339) | 1900-01-01T00:00:00+06:42 | หาย | 2026c · /usr/share/zoneinfo ของระบบ |
Rust chrono 0.4.45 | b.to_rfc3339() | 1900-01-01T00:00:00+06:42 | หาย | 2025b · ฝังใน chrono-tz 0.10.4 |
Node v24.19.0 ที่ TZ=Asia/Bangkok | b.toString() | Mon Jan 01 1900 00:00:00 GMT+0642 (Indochina Time) | หาย | 2026b · ICU ที่ฝังใน node |
Node v24.19.0 ที่ TZ=Asia/Bangkok | b.toISOString() | 1899-12-31T17:17:56.000Z | อยู่ใน instant | 2026b · ICU ที่ฝังใน node |
offset ที่อ่านเป็นวินาทีได้ 24124 ทั้งสี่ภาษาที่ probe อ่าน คือ Java, Go, Python และ Rust ทั้งที่สี่ภาษานั้นอ่าน
tzdata สามรุ่น
ความต่างของตารางนี้จึงไม่ได้มาจากข้อมูลของโซน มันมาจากรูปแบบของสตริงที่แต่ละการเรียกเลือกใช้ และในภาษาเดียวกันอย่าง Go สองการเรียกให้สองคำตอบ
ค่าแทนวันที่ว่างที่สองระบบพิมพ์ไม่ตรงกัน
หัวข้อที่มีชื่อว่า “ค่าแทนวันที่ว่างที่สองระบบพิมพ์ไม่ตรงกัน”ค่า
1900-01-01 00:00ค่าเดียว ออกจากสอง service เป็นสองสตริง และไม่มีสตริงไหนมี+07:00
กลับไปที่การย้ายข้อมูลของร้าน สมมติว่า service ที่เขียนด้วย Java ส่งช่องวันส่งที่ว่างออกไปเป็น
1900-01-01T00:00:00+06:42:04 ส่วน service ที่เขียนด้วย Go และใช้ time.RFC3339 ส่งออกไปเป็น
1900-01-01T00:00:00+06:42
ทั้งสองสตริงมาจาก instant เดียวกัน คือ 1899-12-31T17:17:56Z ซึ่ง probe วัดได้ตรงกันทั้งใน Java และ Go
แต่ระบบปลายทางที่ถามว่า “ช่องนี้เป็นค่าแทนวันที่ว่างหรือเปล่า” ด้วยการเทียบสตริง จะตอบสองคำตอบ
ระบบที่สามซึ่งเชื่อว่า Bangkok เป็น +07:00 เสมอ จะไม่เจอทั้งสองสตริง เพราะไม่มีการเรียกไหนที่ probe วัด
พิมพ์ +07:00 ให้วันที่นั้น
ทางออกไม่ใช่การเลือกภาษาที่พิมพ์ครบ แต่คือการเลิกส่ง offset แทนโซน ส่ง instant เป็น UTC แล้วส่งชื่อโซนแยกไปอีกช่อง ปลายทางจะได้ offset ของวันนั้นจาก tzdata ของมันเอง
ราคาคือปลายทางต้องมี tzdata และรุ่นที่มันอ่านอาจไม่ตรงกับต้นทาง ข้ออ้างของบทนี้รอดสามรุ่น เพราะกฎของ Bangkok ปี 1900 ไม่ได้เปลี่ยนในสามรุ่นนั้น กฎที่เพิ่งถูกแก้ไม่มีการรับปากแบบนี้
บทความ ภาษาไทยทำให้ code พังคนละชั้นกันสี่ชั้น เป็นเจ้าของเรื่อง
การแสดงปี คือ locale th-TH ที่ผูกกับปฏิทินพุทธ บทนี้เป็นเจ้าของ จุดบนเส้นเวลา
คือ offset ที่โซนใช้ในวันนั้น
สองเรื่องนี้แยกกันได้ ปีที่แสดงบนหน้าจอเปลี่ยนตาม locale ของผู้อ่าน แต่ไม่ได้ย้าย instant ไปไหน
ส่วน offset +06:42:04 ย้าย instant จริง และไม่ได้เปลี่ยนตาม locale
จุดที่หก กฎของโซนที่เปลี่ยนตามปี
หัวข้อที่มีชื่อว่า “จุดที่หก กฎของโซนที่เปลี่ยนตามปี”โซนเดียวกันใช้คนละ offset ในคนละปี และบทนี้ปิดจุดสุดท้ายในหกจุดของคอร์ส
Asia/Bangkok ปี 2026 ใช้ +07:00 และ Asia/Bangkok ปี 1900 ใช้ +06:42:04 ทั้งสองค่ามาจากโซนเดียวกัน
offset จึงเป็นคำตอบของคำถามว่า “โซนนี้ ณ จุดนี้” ไม่ใช่คุณสมบัติของโซน
จุดที่หกคือข้อนี้ กฎของโซนเปลี่ยนตามปี ในทรงที่ probe วัด สี่ภาษาที่อ่าน offset เป็นวินาทีได้ค่าเดียวกัน จาก tzdata สามรุ่น แต่ตัวพิมพ์ที่ใช้รูปแบบของ RFC 3339 พิมพ์มันได้ไม่ครบ และไม่มีการเรียกไหนแดง
ในค่าที่บทนี้วัด รูปที่ไม่เสียสี่วินาทีและผ่าน grammar คือ instant ที่เขียนเป็น UTC ซึ่งไม่พึ่ง offset บนสายเลย บทที่ 8 รวมทุกจุดของคอร์สเข้าเป็นท่อเดียว แล้ววัดว่า slot ส่งของรอดถึงปลายทางได้อย่างไร
-
IANA tz database — file
asia(เข้าถึง 2026-10-03) — ที่มาของแถวของAsia/Bangkokที่ใช้ offset เดียวกับ+06:42:04ชื่อย่อLMTกับBMTและคอมเมนต์ “Bangkok Mean Time” -
RFC 3339 — Date and Time on the Internet: Timestamps (เข้าถึง 2026-10-03) — ที่มาของบรรทัด
time-numoffsetใน §5.6 และของประโยค “This time zone cannot be represented exactly using the HH:MM format, and this timestamp uses the closest representable UTC offset.” ใน §5.8 -
Go — package time, constants (เข้าถึง 2026-10-03) — ที่มาของ
RFC3339 = "2006-01-02T15:04:05Z07:00"และของรูป"-07:00:00"ที่เอกสารระบุว่าเป็น±hh:mm:ss -
chrono 0.4.45 — DateTime::to_rfc3339 (เข้าถึง 2026-10-03) — ที่มาของ
to_rfc3339()ที่บทนี้วัด -
Java SE 25 — ZoneOffset.getId() (เข้าถึง 2026-10-03) — ที่มาของประโยค “+hh:mm:ss or -hh:mm:ss - if the seconds are non-zero (not ISO-8601)”
-
Python — datetime.isoformat (เข้าถึง 2026-10-03) — ที่มาของรูป offset
+HH:MM[:SS[.ffffff]] -
ECMAScript — TimeZoneString ( tv ) (เข้าถึง 2026-10-03) — ขั้นสุดท้ายของมันเขียนว่า “Return the string-concatenation of offsetSign, offsetHour, offsetMinute, and timeZoneName.” คือ
toString()ของDateไม่มีช่องวินาทีของ offset และชื่อในวงเล็บเป็นสิ่งที่ implementation เลือกเอง -
ECMAScript — Date.UTC (เข้าถึง 2026-10-03) — หมายเหตุของมันเขียนว่า
Date.UTCต่างจาก constructor ของDateตรงที่ “it interprets the arguments in UTC rather than as local time.” คือnew Date(1900, 0, 1)อ่านวันที่และชั่วโมงเป็นเวลาท้องถิ่นของ process -
ค่าทุกค่าในบทนี้มาจาก
scripts/time-semantics/measured.jsonซึ่งscripts/time-semantics/probe.pyเขียนเมื่อ 2026-10-02 บน darwin/arm64 · probe วัดทั้งชุดสามรอบต่อการเรียกหนึ่งครั้ง และ Node รันด้วยTZที่ probe ตั้งเองทุกครั้ง
เช็กความเข้าใจ — บทที่ 7
ข้อ 1 / 3tzdata ให้ `Asia/Bangkok` วันที่ `1900-01-01 00:00` ใช้ offset อะไร