slot ส่งของที่รอดทั้งเส้นทาง
เจ็ดบทที่ผ่านมาวัดเวลาทีละจุด บทนี้เอาจุดเหล่านั้นมาต่อกันเป็นท่อเดียว แล้วส่งออเดอร์ใบหนึ่งเข้าไปจริง
ออเดอร์ A-1042 มี delivery slotdelivery slotช่วงเวลาส่งของที่ร้านสัญญากับลูกค้า ระบุเป็นวันที่และเวลาบนหน้าปัดในโซนของร้าน · คอร์สนี้ใช้มันเป็นค่าที่ต้องรอดทั้งเส้นทาง ตั้งแต่ฟอร์มที่ลูกค้ากรอกจนถึงระบบที่อยู่อีกโซน (ช่วงเวลาส่งของที่ร้านสัญญากับลูกค้า) ให้เลือกสี่ใบ
ทุกใบเป็นเวลาบนหน้าปัดของโซน America/New_York และ body ทั้งใบคือสิ่งที่ท่อทั้งสองเส้นรับเข้าไป
{"orderId": "A-1042", "zone": "America/New_York", "slots": ["2026-03-07T12:00", "2026-03-07T02:30", "2026-03-08T02:30", "2026-11-01T01:30"]}คำถามของบทนี้ไม่ใช่ว่าท่อเส้นไหนเขียนสวยกว่า แต่เป็นว่า slot แต่ละใบออกจากปลายทางของสองเส้นเป็นค่าอะไร เมื่ออินพุตเป็นใบเดียวกัน ทุกคำตอบในบทนี้เป็นค่าที่ probe วัด
orderctl คือเครื่องมือประมวลผลออเดอร์ที่คอร์สภาษาในเสานี้สร้างซ้ำทีละภาษา repo ตัวอย่าง
กำลังจัดทำ
ระหว่างนี้ทุกค่าในบทนี้รันเองได้ด้วย npm run verify:time-semantics
ซึ่งเรียก python3 scripts/time-semantics/probe.py · ไม่ต้องมี Docker แต่การรันครั้งแรก
ต้องต่อเน็ตเพื่อดึง chrono กับ chrono-tz จาก crates.io
อินพุตใบเดียว กับสี่ slot ที่เลือกมา
หัวข้อที่มีชื่อว่า “อินพุตใบเดียว กับสี่ slot ที่เลือกมา”ท่อทั้งสองเส้นอยู่ใน file เดียวกัน อ่าน body จากตัวแปรตัวเดียวกัน และ slot แต่ละใบถูกเลือกมาเพื่อแตะจุดหนึ่งของคอร์ส
การเทียบท่อสองเส้นไม่มีความหมาย ถ้าใครสักคนเถียงได้ว่าสองเส้นรับอินพุตคนละใบ เงื่อนไขนี้จึงถูกบังคับไว้ที่ตัวโปรแกรม ไม่ได้ฝากไว้กับวินัยของคนรัน
body = json.loads(sys.argv[1])ZONE = ZoneInfo(body["zone"])
# ...
out = {"naive": {s: naive(s) for s in body["slots"]}, "guarded": {s: guarded(s) for s in body["slots"]}}body มาจากอาร์กิวเมนต์ตัวเดียวทาง argv แล้วฟังก์ชันทั้งสองตัวรับ slot จากรายการเดียวกันนั้น
probe รัน file นี้ด้วย Python 3.14.6 ซึ่งอ่าน tzdata รุ่น 2026c จาก /usr/share/zoneinfo ของระบบ บน darwin/arm64
slot สี่ใบไม่ได้สุ่มมา แต่ละใบแตะจุดที่บทก่อนหน้าวัดไว้
2026-03-07T12:00เป็นเวลาปกติของวันก่อนที่ DST เริ่ม ใบนี้มีไว้วัดการเลื่อนนัดข้ามคืนนั้น2026-03-07T02:30มีอยู่จริงในวันนั้น แต่วันพรุ่งนี้ของมันไม่มี02:302026-03-08T02:30คือเวลาที่ไม่มีอยู่จริงของบทที่ 12026-11-01T01:30คือเวลาที่มีสองครั้งของบทที่ 4
ทั้งสองเส้นเดินสี่ขั้นเหมือนกัน คือรับ slot จากฟอร์ม · ส่ง JSON ไปหาคลังสินค้า · ให้คลังอ่านออกมาเป็นจุดบนเส้นเวลา · แล้วเลื่อนนัดไปวันพรุ่งนี้เวลาเดิม
flowchart LR
A["ฟอร์ม · slot บนหน้าปัด"] --> B{"ท่อเส้นไหน"}
B -->|"ท่อเปล่า"| C["รับทุกใบ"]
C --> D["สาย · สตริงที่มีแค่ offset"]
D --> E["คลัง · tzinfo เป็น offset คงที่"]
E --> F["เลื่อนนัด · บวกหนึ่งวันบน offset"]
B -->|"ท่อที่มีด่าน"| G{"ชี้จุดเดียวไหม"}
G -->|"ไม่"| H["ValueError · ไม่ส่งต่อ"]
G -->|"ใช่"| I["สาย · instant กับชื่อโซนสองช่อง"]
I --> J["คลัง · tzinfo เป็นโซน"]
J --> K{"เลื่อนนัด · ใบใหม่ชี้จุดเดียวไหม"}
K -->|"ไม่"| H
K -->|"ใช่"| L["slot ใบใหม่"]
คำบรรยายภาพ: สองเส้นต่างกันสามที่ คือด่านก่อนรับ ของที่อยู่บนสาย และกฎที่ใช้เลื่อนนัด ส่วนที่เหลือของบทวัดว่าความต่างสามที่นั้นออกมาเป็นค่าอะไรที่ปลายทาง
ท่อเปล่า · รับทุกใบ แล้วส่ง offset ไปบนสาย
หัวข้อที่มีชื่อว่า “ท่อเปล่า · รับทุกใบ แล้วส่ง offset ไปบนสาย”เส้นแรกเขียนตามสัญชาตญาณ ไม่มีขั้นไหนล้ม และไม่มีขั้นไหนรายงานอะไรเลย
ท่อเส้นแรกติดโซนให้เวลาบนหน้าปัดด้วย replace แล้วส่ง isoformat() ออกไป ปลายทาง parse สตริงนั้นกลับมา
แล้วบวก timedelta(days=1) เพื่อเลื่อนนัด
# 1 · รับ · ไม่มีอะไรล้มได้ตรงนี้local = datetime.fromisoformat(slot).replace(tzinfo=ZONE)# 2 · ส่งwire = json.dumps({"orderId": body["orderId"], "slot": local.isoformat()})# 3 · ปลายทางgot = datetime.fromisoformat(json.loads(wire)["slot"])# 4 · เลื่อนนัด · บวกบน offset ที่ได้มาจากสายmoved = got + timedelta(days=1)ท่อเปล่ารับ slot ครบทั้งสี่ใบ และช่อง error ของทุกใบเป็นสตริงว่างทั้งตอนรับและตอนเลื่อนนัด
สิ่งที่ขึ้นสาย และสิ่งที่คลังได้
หัวข้อที่มีชื่อว่า “สิ่งที่ขึ้นสาย และสิ่งที่คลังได้”body ที่ขึ้นสายของ slot 2026-03-07T12:00 คือ
{"orderId": "A-1042", "slot": "2026-03-07T12:00:00-05:00"}ชื่อ America/New_York ไม่อยู่บนสายแล้ว สิ่งที่เหลือคือ offset -05:00 ตัวเดียว
คลังจึงได้ tzinfo เป็น datetime.timezone(datetime.timedelta(days=-1, seconds=68400)) ซึ่งเป็น offset คงที่
เอกสารของ Python เขียนข้อจำกัดของ timezone ไว้ตรงๆ ว่า “Objects of this class cannot be used to represent
time zone information in the locations where different offsets are used in different days of the year”
ส่วน slot 2026-11-01T01:30 ได้ tzinfo เป็น datetime.timezone(datetime.timedelta(days=-1, seconds=72000))
ซึ่งก็เป็น offset คงที่อีกตัวหนึ่ง
slot ที่ลูกค้าจอง กับนาฬิกาของลูกค้าตอนรถมาถึง
หัวข้อที่มีชื่อว่า “slot ที่ลูกค้าจอง กับนาฬิกาของลูกค้าตอนรถมาถึง”ช่องสุดท้ายของตารางข้างล่างไม่ได้มาจากท่อเปล่า เพราะท่อเปล่าไม่มีชื่อโซนอยู่ในมือแล้ว probe อ่านมันเองด้วยโซน
America/New_York เพื่อบอกว่ารถมาถึงตอนไหนในสายตาของลูกค้า
| slot ที่จอง | บนสาย | instant ที่คลังได้ | นาฬิกาของลูกค้า |
|---|---|---|---|
2026-03-07T12:00 | 2026-03-07T12:00:00-05:00 | 2026-03-07T17:00:00Z | 2026-03-07T12:00:00-05:00 |
2026-03-07T02:30 | 2026-03-07T02:30:00-05:00 | 2026-03-07T07:30:00Z | 2026-03-07T02:30:00-05:00 |
2026-03-08T02:30 | 2026-03-08T02:30:00-05:00 | 2026-03-08T07:30:00Z | 2026-03-08T03:30:00-04:00 |
2026-11-01T01:30 | 2026-11-01T01:30:00-04:00 | 2026-11-01T05:30:00Z | 2026-11-01T01:30:00-04:00 |
แถวที่สามเป็นแถวเดียวที่นาฬิกาของลูกค้าไม่ตรงกับ slot ที่จอง ลูกค้าจอง 02:30 บนสายเขียน 02:30:00-05:00
แต่รถมาถึงตอนนาฬิกาของลูกค้าบอก 03:30:00-04:00
แถวที่สี่ตรงกับที่จองทุกตัวอักษร แต่ 01:30 ของวันนั้นมีสองครั้ง ท่อเปล่าเลือก -04:00 ให้โดยไม่มีใครถาม
ในทรงที่ probe วัด การเลือกนี้มาจาก replace(tzinfo=ZONE) ที่ไม่ได้ตั้ง fold ซึ่งค่าตั้งต้นคือ 0
การเลื่อนนัดไปวันพรุ่งนี้
หัวข้อที่มีชื่อว่า “การเลื่อนนัดไปวันพรุ่งนี้”ขั้นที่สี่บวก timedelta(days=1) บน offset ที่ได้จากสาย ผลคือ
| slot ที่จอง | หลังเลื่อน | instant หลังเลื่อน | นาฬิกาของลูกค้าหลังเลื่อน |
|---|---|---|---|
2026-03-07T12:00 | 2026-03-08T12:00:00-05:00 | 2026-03-08T17:00:00Z | 2026-03-08T13:00:00-04:00 |
2026-03-07T02:30 | 2026-03-08T02:30:00-05:00 | 2026-03-08T07:30:00Z | 2026-03-08T03:30:00-04:00 |
2026-03-08T02:30 | 2026-03-09T02:30:00-05:00 | 2026-03-09T07:30:00Z | 2026-03-09T03:30:00-04:00 |
2026-11-01T01:30 | 2026-11-02T01:30:00-04:00 | 2026-11-02T05:30:00Z | 2026-11-02T00:30:00-05:00 |
ทั้งสี่แถว นาฬิกาของลูกค้าหลังเลื่อนไม่ได้แสดงเวลาเดิมของวันพรุ่งนี้เลยสักแถว
- แถวแรก ลูกค้าขอ
12:00ของวันพรุ่งนี้ แต่รถมาตอน13:00:00-04:00เพราะ offset-05:00ที่ติดมากับสายไม่รู้ว่า DST เริ่มแล้ว เป็นจุดเดียวกับที่บทที่ 3วัดไว้ - แถวที่สอง วันพรุ่งนี้ของ
02:30ไม่มี02:30ท่อเปล่าไม่รู้เรื่องนี้ และส่งรถไปตอน03:30:00-04:00 - แถวที่สาม slot ที่ไม่มีอยู่จริงตั้งแต่ต้น พาความคลาดเคลื่อนของมันไปถึงวันถัดไปด้วย
- แถวที่สี่
-04:00ที่ถูกเลือกให้เงียบๆ เมื่อวานใช้ไม่ได้แล้วในวันนี้ รถจึงมาตอน00:30:00-05:00
แถวที่สองหลังเลื่อนกับแถวที่สามก่อนเลื่อน คือ 02:30 ของวันที่ 2026-03-08 ที่มาถึงสองทาง
ทั้งสองทางลงที่ instant เดียวกัน คือ 2026-03-08T07:30:00Z และไม่มีทางไหนบอกว่าเวลานั้นไม่มีอยู่จริง
ท่อที่มีด่าน · instant กับชื่อโซนเป็นสองช่อง
หัวข้อที่มีชื่อว่า “ท่อที่มีด่าน · instant กับชื่อโซนเป็นสองช่อง”เส้นที่สองตรวจก่อนรับ ส่งชื่อโซนไปบนสาย และตรวจซ้ำทุกครั้งที่สร้างเวลาบนหน้าปัดใบใหม่
ด่านของเส้นที่สองคือฟังก์ชัน resolve ตัวเดียว มันแปลงเวลาบนหน้าปัดเป็นจุดเดียวบนเส้นเวลา หรือโยน ValueError
def resolve(wall: datetime) -> datetime: """เวลาท้องถิ่น → จุดเดียวบนเส้นเวลา หรือ ValueError""" a = wall.replace(tzinfo=ZONE, fold=0) b = wall.replace(tzinfo=ZONE, fold=1) back = a.astimezone(timezone.utc).astimezone(ZONE).replace(tzinfo=None) if back != wall: raise ValueError(f"nonexistent local time {wall:%Y-%m-%dT%H:%M} in {ZONE.key}") if a.utcoffset() != b.utcoffset(): raise ValueError(f"ambiguous local time {wall:%Y-%m-%dT%H:%M} in {ZONE.key}: " f"{a:%:z} or {b:%:z}") return aด่านนี้ถามสองคำถาม และทั้งสองคำถามใช้กลไกที่บทก่อนหน้าวัดไว้แล้ว
- เวลานี้มีอยู่จริงไหม ส่งไป UTC แล้วกลับมา ถ้าไม่ได้ค่าเดิม แปลว่าไม่มี เป็นวิธีเดียวกับหลักฐานในบทที่ 1 PEP 495 เขียนไว้ว่า “The fromutc() method should never produce a time in the gap.”
- เวลานี้มีครั้งเดียวไหม ถาม offset ทั้งที่
fold=0และfold=1ถ้าได้คนละค่า แปลว่ามีสองครั้ง
ท่อนี้ปฏิเสธเวลาที่มีสองครั้งด้วย ทั้งที่เวลานั้นมีอยู่จริง นี่เป็นการตัดสินของคนเขียนท่อ ไม่ใช่ของ Python เพราะ slot ส่งของต้องชี้จุดเดียว ท่อแบบอื่นอาจเลือกถามลูกค้าแทนการปฏิเสธก็ได้
ส่วนที่เหลือของเส้นที่สองส่ง instant แบบ UTC กับชื่อโซนเป็นสองช่อง แล้วเลื่อนนัดบนหน้าปัดของโซนนั้น
# 1 · รับ · ตรวจก่อนlocal = resolve(datetime.fromisoformat(slot))# 2 · ส่ง · instant กับชื่อโซนเป็นสองช่องwire = json.dumps({"orderId": body["orderId"], "instant": utc(local), "zone": ZONE.key})# 3 · ปลายทางmsg = json.loads(wire)got = datetime.fromisoformat(msg["instant"]).astimezone(ZoneInfo(msg["zone"]))# 4 · เลื่อนนัด · บวกวันบนหน้าปัดของโซน แล้วตรวจซ้ำmoved = resolve(got.replace(tzinfo=None) + timedelta(days=1))สองใบไม่ผ่านด่านตั้งแต่ขั้นแรก
หัวข้อที่มีชื่อว่า “สองใบไม่ผ่านด่านตั้งแต่ขั้นแรก”ท่อที่มีด่านรับ 2026-03-07T12:00 กับ 2026-03-07T02:30 และปฏิเสธอีกสองใบด้วยข้อความเหล่านี้
ValueError: nonexistent local time 2026-03-08T02:30 in America/New_YorkValueError: ambiguous local time 2026-11-01T01:30 in America/New_York: -04:00 or -05:00สองใบนี้ไม่ขึ้นสาย คลังไม่เห็นมัน และไม่มีรถคันไหนถูกส่งไปตามมัน ช่องค่าของมันทุกช่องในขั้นถัดไปเป็นสตริงว่าง
สิ่งที่ขึ้นสาย และสิ่งที่คลังได้
หัวข้อที่มีชื่อว่า “สิ่งที่ขึ้นสาย และสิ่งที่คลังได้”body ที่ขึ้นสายของ slot 2026-03-07T12:00 คือ
{"orderId": "A-1042", "instant": "2026-03-07T17:00:00Z", "zone": "America/New_York"}คลังได้ tzinfo เป็น zoneinfo.ZoneInfo(key='America/New_York') คือได้โซนกลับมาทั้งชุดกฎ ไม่ใช่ offset ตัวเดียว
นาฬิกาของลูกค้าที่ instant นั้นคือ 2026-03-07T12:00:00-05:00 ตรงกับที่จอง
slot 2026-03-07T02:30 ขึ้นสายเป็น instant 2026-03-07T07:30:00Z และนาฬิกาของลูกค้าคือ 2026-03-07T02:30:00-05:00
ซึ่งก็ตรงกับที่จองเช่นกัน ทุกใบที่ท่อนี้รับ นาฬิกาของลูกค้าตรงกับ slot ที่จอง
การเลื่อนนัดที่ตรวจซ้ำ
หัวข้อที่มีชื่อว่า “การเลื่อนนัดที่ตรวจซ้ำ”slot 2026-03-07T12:00 เลื่อนไปได้ 2026-03-08T12:00:00-04:00 ซึ่งเป็น instant 2026-03-08T16:00:00Z
และนาฬิกาของลูกค้าบอก 2026-03-08T12:00:00-04:00 คือเวลาเดิมของวันพรุ่งนี้
slot 2026-03-07T02:30 ผ่านด่านตอนรับ แต่ตกด่านตอนเลื่อนนัด เพราะวันพรุ่งนี้ของมันไม่มี 02:30
ValueError: nonexistent local time 2026-03-08T02:30 in America/New_Yorkใบนี้คือใบที่ท่อเปล่าส่งรถไปตอน 03:30:00-04:00 โดยไม่มีใครรู้ ท่อที่มีด่านไม่ส่งรถไปเลย แล้วคืนข้อความที่บอกว่าทำไม
สองเส้น บนปลายทางเดียวกัน
หัวข้อที่มีชื่อว่า “สองเส้น บนปลายทางเดียวกัน”ค่าที่ออกจากปลายทางของสองเส้นต่างกันตรงไหน วัดเป็นสตริงทุกช่อง
ตารางนี้เอานาฬิกาของลูกค้าจากสองเส้นมาวางคู่กัน ทั้งตอนรถมาตามนัดแรก และตอนรถมาตามนัดที่เลื่อนแล้ว
| slot ที่จอง | ท่อเปล่า · นัดแรก | ท่อที่มีด่าน · นัดแรก | ท่อเปล่า · หลังเลื่อน | ท่อที่มีด่าน · หลังเลื่อน |
|---|---|---|---|---|
2026-03-07T12:00 | 12:00:00-05:00 | 12:00:00-05:00 | 13:00:00-04:00 | 12:00:00-04:00 |
2026-03-07T02:30 | 02:30:00-05:00 | 02:30:00-05:00 | 03:30:00-04:00 | ValueError ตอนเลื่อน |
2026-03-08T02:30 | 03:30:00-04:00 | ValueError ตอนรับ | 03:30:00-04:00 | ไม่ได้รับไว้ |
2026-11-01T01:30 | 01:30:00-04:00 | ValueError ตอนรับ | 00:30:00-05:00 | ไม่ได้รับไว้ |
แต่ละช่องตัดมาเฉพาะส่วนเวลาของค่าที่บทนี้ยกไว้ข้างบน ค่าเต็มพร้อมวันที่อยู่ในหัวข้อของแต่ละเส้น
แถวแรกเป็นแถวเดียวที่ทั้งสองเส้นรับและเลื่อนได้ครบ นัดแรกของสองเส้นเป็น instant เดียวกัน คือ 2026-03-07T17:00:00Z
แต่หลังเลื่อน ท่อเปล่าได้ 2026-03-08T17:00:00Z ส่วนท่อที่มีด่านได้ 2026-03-08T16:00:00Z ซึ่งเป็นคนละจุด
สิ่งที่แยกสองเส้นออกจากกันในแถวนี้ไม่ใช่ด่าน แต่เป็นชื่อโซนบนสาย ชื่อ America/New_York อยู่ใน body ของท่อที่มีด่าน
และไม่อยู่ใน body ของท่อเปล่า ปลายทางที่ไม่มีชื่อโซนจึงบวกวันตามกฎของโซนไม่ได้ เป็นจุดเดียวกับที่
บทที่ 6วัดไว้
ส่วนที่แยกสองเส้นในอีกสามแถวคือด่าน ท่อเปล่าไม่รายงานความล้มเหลวสักจุด ส่วนท่อที่มีด่านเป็นเส้นเดียวที่รายงาน
ด่านไม่ได้ทำให้ slot สามใบที่ตกด่านกลายเป็นนัดที่ใช้ได้ สิ่งที่ด่านเปลี่ยนคือความคลาดเคลื่อนกลายเป็นข้อความที่อ่านได้ แทนที่จะเป็นรถที่มาผิดเวลา
ราคาที่เห็นได้จากค่าที่วัดในบทนี้มีสามข้อ
- รูปของ body บนสายเปลี่ยน จากช่อง
slotช่องเดียว เป็นช่องinstantกับzoneทุก service ที่อ่าน body นี้ต้องแก้ตาม - slot สองใบถูกปฏิเสธตั้งแต่ฟอร์ม ระบบต้องมีทางถามลูกค้าใหม่ ซึ่งท่อในบทนี้ไม่ได้เขียนไว้
- การเลื่อนนัดหนึ่งใบไม่มีคำตอบ ผู้เรียกต้องเขียนทางเดินของความล้มเหลวเอง ไม่ใช่รับค่ามาแล้วไปต่อ
probe ของคอร์สนี้ไม่ได้วัดเวลาที่ใช้รัน และไม่ได้วัดต้นทุนของด่าน บทนี้จึงไม่บอกว่าด่านถูกหรือแพง มันบอกเฉพาะค่าที่ออกจากปลายทางของสองเส้น
ท่อทั้งสองเส้นเขียนด้วย Python ภาษาเดียว ค่าในบทนี้จึงเป็นค่าของ Python ในทรงที่ probe วัด
ไม่ใช่ค่าของอีกสี่ภาษา ฝั่ง JavaScript มี Temporal เป็นทิศทางที่น่าตามต่อ แต่ probe ไม่ได้วัดมัน
บทนี้จึงไม่พิมพ์ค่าของมันสักค่า
หกจุดที่วัด กับท่อที่เดินผ่านสี่จุด
หัวข้อที่มีชื่อว่า “หกจุดที่วัด กับท่อที่เดินผ่านสี่จุด”บทนี้ไม่ได้เป็นเจ้าของจุดไหน มันคือที่ที่จุดที่วัดแล้วถูกวางต่อกันเป็นท่อเดียว
ธีสิสของคอร์สนี้เป็นประโยคเดียว คือ wall-clock time ค่าหนึ่งไม่ได้ระบุจุดเดียวบนเส้นเวลา มันอาจไม่มีจุดเลย มีสองจุด หรือมีจุดเดียวที่แต่ละภาษาเลือกต่างกัน และในทรงที่ probe วัด มีภาษาเดียวจากห้าภาษาที่บอกคุณ
เจ็ดบทก่อนหน้าวัดหกจุดที่เวลาเปลี่ยนไประหว่างทาง
| จุด | เรื่อง | บท |
|---|---|---|
| 1 | เวลาท้องถิ่นที่ไม่มีอยู่จริง | บทที่ 1 |
| 2 | วันที่ที่ไม่มีเวลา | บทที่ 2 |
| 3 | offset ที่มากับสาย | บทที่ 3 และบทที่ 6 |
| 4 | เวลาท้องถิ่นที่มีสองครั้ง | บทที่ 4 |
| 5 | การบวกข้ามคืนที่เปลี่ยน DST | บทที่ 5 |
| 6 | กฎของโซนที่เปลี่ยนตามปี | บทที่ 7 |
ท่อในบทนี้เดินผ่านสี่จุดในหกจุดนั้น
- จุดที่ 1 คือ slot
2026-03-08T02:30และวันพรุ่งนี้ของ slot2026-03-07T02:30 - จุดที่ 3 คือ body ของท่อเปล่าที่พาแค่ offset ไปบนสาย แล้วคลังได้ tzinfo เป็น offset คงที่
- จุดที่ 4 คือ slot
2026-11-01T01:30ที่ท่อเปล่าเลือก-04:00ให้เงียบๆ - จุดที่ 5 คือการเลื่อน
2026-03-07T12:00ข้ามคืนที่ DST เริ่ม
จุดที่ 2 กับจุดที่ 6 ไม่มีที่นั่งในท่อนี้ เพราะไม่มี slot ใบไหนเป็นวันที่ที่ไม่มีเวลา และทุกใบอยู่ในปี 2026 การเขียนว่าสองจุดนั้นโผล่ที่นี่ด้วยจะเป็นการอ้างค่าที่ probe ไม่ได้วัด
บทสุดท้ายของคอร์สจำนวนเต็มที่เชื่อไม่ได้ใช้ท่อสองเส้นแบบเดียวกัน แต่เดินตามยอดของออเดอร์แทนเวลาของออเดอร์ สิ่งที่สองคอร์สชี้ไปที่เดียวกันคือ ตัวตัดสินว่าค่าจะรอดถึงปลายทางหรือไม่ คือสิ่งที่คุณส่งไปบนสาย กับด่านที่คุณเขียนหรือไม่ได้เขียนไว้
-
Python — datetime (เข้าถึง 2026-10-03) — ที่มาของข้อจำกัดของ
timezoneที่ท่อเปล่าได้จากสาย หน้านี้เขียนว่า “The timezone class is a subclass of tzinfo, each instance of which represents a time zone defined by a fixed offset from UTC.” และ “Objects of this class cannot be used to represent time zone information in the locations where different offsets are used in different days of the year or where historical changes have been made to civil time.” -
Python — zoneinfo (เข้าถึง 2026-10-03) — ที่มาของ
ZoneInfoที่ท่อที่มีด่านได้กลับมาจากชื่อโซนบนสาย หน้านี้เขียนว่ามัน “represents an IANA time zone specified by the string key” -
PEP 495 — Local Time Disambiguation (เข้าถึง 2026-10-03) — ที่มาของสองกลไกใน
resolveคือ “The fromutc() method should never produce a time in the gap.” และกฎของเวลาใน gap ที่fold=0ใช้ “the rules in effect before the transition” ส่วนfold=1ใช้ “the rules in effect after the transition” -
MDN — Temporal (เข้าถึง 2026-10-03) — หน้านี้เขียนว่า “The Temporal object enables date and time management in various scenarios, including built-in time zone and calendar representation” และติดป้าย “Limited availability” ไว้ · probe ไม่ได้วัดมัน
-
ค่าทุกค่าในบทนี้มาจากช่อง
slotBodyช่องpipelineและช่องversionsของscripts/time-semantics/measured.jsonซึ่งscripts/time-semantics/probe.pyเขียนเมื่อ 2026-10-02 บน darwin/arm64 · probe วัดทั้งชุดสามรอบต่อการเรียกหนึ่งครั้ง
เช็กความเข้าใจ — บทที่ 8
ข้อ 1 / 3ในท่อเปล่า slot `2026-03-08T02:30` ขึ้นสายเป็น `2026-03-08T02:30:00-05:00` นาฬิกาของลูกค้าบอกเวลาอะไรตอนรถมาถึง