📘 Hermes Enterprise Standard · v1.0 · 04/08/2026

⏰ Date/Time Golden Rules

มาตรฐานกลางการจัดการวันที่และเวลาสำหรับระบบไทย (BKK, UTC+7) ที่ทำงานบน Teable — แหล่งข้อผิดพลาดอันดับ #1 ของ Agent ทุกตัวในองค์กร

🎯 ทำไมต้องมีมาตรฐานนี้

ระบบของเราตกลงใช้เวลาไทย (BKK, UTC+7) แต่ Teable เก็บฟิลด์ date เป็น UTC ISO — ความไม่ตรงกันนี้ทำให้ Agent ทุกตัว (Aim, Gai, Aiya, Zai, YS และ agent ลูกค้า enterprise) พลาดซ้ำแล้วซ้ำเล่า: ข้อมูลวันหาย, off-by-one, TQL ไม่ match, บันทึกแล้วไม่ขึ้น

🔴 ผลกระทบจริงที่เจอ: ข้อมูล Gar* วันที่หาย (ดูเหมือนไม่มี แต่อยู่ใน Teable เป็น UTC ของวันก่อน), BP user ติดผิด, ใบเสนอราคา Dec* ได้วันที่เมื่อวานหลังเที่ยงคืน — ทั้งหมดมาจาก format เวลาคนละแบบ

1️⃣ Teable Date = UTC ISO แต่ Convention = BKK-Midnight

ทิศทางFormatตัวอย่าง
เขียน (write)BKK-midnight2026-08-04T00:00:00.000Z
Query (TQL)BKK-midnight{Date} = '2026-08-04T00:00:00.000Z'
อ่านกลับมา (read)UTC ISO2026-08-03T17:00:00.000Z = BKK 04/08 00:00
❌ ห้ามเด็ดขาด:
• Slice Date[:10] แล้วเทียบกับวัน BKK → off-by-one เสมอ
• TQL {Date} = '2026-08-04' (ไม่มีเวลา) → ไม่ match เลย

2️⃣ แหล่งข้อมูลแต่ละตัว format เวลาต่างกัน

แหล่งข้อมูลFormat ต้นทางต้องแปลงเป็น
Teable API (read)UTC ISO T17:00:00.000Z→ BKK (astimezone +7)
Teable API (write)BKK-midnightส่ง {date}T00:00:00.000Z เสมอ
Gar* ConnectUTC ISO / local startTimeLocalตรวจ field ทุกครั้ง
OMR* CSVBKK wall time 2026/07/24 22:15ใช้ BKK ตรงๆ
Arb*BKK wall + .000Zตาม convention ของ script
Air*US timezone→ BKK ก่อน sync
G* Fitepoch ms UTC→ BKK
💡 จำไว้: "BKK convention" ของเรา = เขียน/query ด้วย BKK-midnight แต่ Teable คืนมาเป็น UTC ISO — 2 ทิศทางคนละ format!

3️⃣ ตัวอย่างโค้ด ถูก / ผิด (Python)

✅ เขียน date ลง Teable

fields["Date"] = "2026-08-04"  # Teable date field รับ bare date → เก็บเป็น BKK midnight อัตโนมัติ

✅ Query ด้วย TQL (BKK-midnight)

from urllib.parse import quote
tql = quote("{Date} = '2026-08-04T00:00:00.000Z'")
GET /api/table/{tid}/record?take=5&filterByTql={tql}

✅ อ่านกลับมาแล้วแปลงเป็น BKK ก่อน compare

from datetime import datetime, timezone, timedelta
bkk = timezone(timedelta(hours=7))
raw = rec["fields"]["Date"]                       # "2026-08-03T17:00:00.000Z"
bkk_date = datetime.strptime(raw[:19], "%Y-%m-%dT%H:%M:%S").replace(tzinfo=timezone.utc).astimezone(bkk)
print(bkk_date.strftime("%Y-%m-%d"))              # "2026-08-04" ✅

❌ ผิด — off-by-one

if rec["fields"]["Date"][:10] >= "2026-08-04":    # "2026-08-03" >= ... = False → ข้อมูลหาย!
    ...

4️⃣ JavaScript (Frontend) — ห้ามใช้ toISOString() หาวันที่

❌ ผิด: new Date().toISOString().split('T')[0] คืนเป็น UTC → หลังเที่ยงคืน BKK (00:00–06:59) ได้วันเมื่อวาน!
// ✅ ถูก — BKK local date helper (มีใน Dec* config.js แล้ว)
function todayBKK() {
  const d = new Date();
  const bkk = new Date(d.toLocaleString('en-US', { timeZone: 'Asia/Bangkok' }));
  return bkk.getFullYear() + '-' + String(bkk.getMonth()+1).padStart(2,'0') + '-' + String(bkk.getDate()).padStart(2,'0');
}
// ✅ สำหรับ Teable: dateToBKKISO(dateObj) = todayBKK-style + 'T00:00:00.000Z'

5️⃣ Python Backend

datetime.now() = เวลา local ของเครื่อง (ถ้าเครื่องตั้ง BKK → ได้ BKK ✓)

datetime.utcnow() = UTC — ถ้าใช้ ต้องแปลงกลับเป็น BKK เสมอ

6️⃣ Verify เสมอ — ห้ามเชื่อว่า "บันทึกแล้ว" โดยไม่ตรวจ

✅ Checklist ก่อน sync ข้อมูลข้ามระบบ

📚 กรณีศึกษาจริง (04/08/2026)

ระบบอาการต้นเหตุสถานะ
Gar* Health Pullข้อมูล 03/08 "หาย" หลัง pullTQL ใช้ bare date ('2026-08-03') → POST ซ้ำ → 400✅ แก้แล้ว
Gar* Verificationเห็น 02/08 แต่จริงคือ 03/08slice UTC ISO [:10]✅ แก้แล้ว
Dec* ERP (JS)ใบเสนอราคาวันที่เมื่อวาน (หลังเที่ยงคืน)toISOString().split('T')[0] = UTC✅ แก้แล้ว (4 จุด)
BP User (Aim)Link user ผิดตาราง → FK 500ใช้ record ID จาก table ผิด✅ แก้แล้ว

™ ชื่อแบรนด์ที่กล่าวถึง (Dec*, Gar*, Arb*, OMR*, Air*, G* Fit ฯลฯ) เป็นเครื่องหมายการค้าของเจ้าของ — เอกสารนี้เป็นคู่มือการใช้งานภายในองค์กร ไม่มีความเกี่ยวข้องหรือการรับรองจากเจ้าของแบรนด์

📚 เอกสารฉบับเต็มสำหรับ Agent: skill teable-rest-api-gotchasDATE/TIME GOLDEN RULES

มาตรฐานนี้บังคับใช้กับ agent ทั้งหมดในองค์กร + template enterprise delivery