4.2 pandas Datetime & NaT
ข้อมูลวันที่จริงมาเป็น text เสมอ — “2026-04-24”, “April 24, 2026”, “24/04/2026” — pandas ต้องแปลงให้หมด และเมื่อแปลงไม่ได้ มันให้ NaT
pd.to_datetime() — เครื่องมือหลัก
Section titled “pd.to_datetime() — เครื่องมือหลัก”pd.to_datetime() คือฟังก์ชันที่ pandas ใช้แปลง text (หรือ number) ให้เป็น Timestamp — object ที่เก็บวันที่+เวลา พร้อมคำนวณได้
import pandas as pd
pd.to_datetime("2026-04-24")# Timestamp('2026-04-24 00:00:00')NaT — Not a Time
Section titled “NaT — Not a Time”เหมือน NaN สำหรับ numbers — NaT คือ “missing date”
NaN= Not a NumberNaT= Not a Time
NaT แพร่กระจาย ผ่านการคำนวณ เหมือน NaN:
pd.NaT + pd.Timedelta(days=7) # NaT — ไม่มีวันที่ + 7 วัน = ยังไม่มีวันที่pd.NaT > pd.Timestamp("2026-01-01") # False (ทุก comparison = False)Sheets ไม่มี concept “NaT” โดยตรง — แต่มีปัญหาที่คล้ายกัน:
สร้างข้อมูลใน A1:B5:
| name | join_date |
|---|---|
| Alice | 2024-01-15 |
| Bob | (ว่าง) |
| Carol | 2024-03-20 |
| Dave | hello |
=DATEDIF(B2, TODAY(), "D") → จำนวนวัน (Alice = ตัวเลข)=DATEDIF(B3, TODAY(), "D") → #VALUE! error (Bob = ว่าง)=DATEDIF(B5, TODAY(), "D") → #VALUE! error (Dave = ไม่ใช่วันที่)วิธี handle: ใช้ IFERROR
=IFERROR(DATEDIF(B2, TODAY(), "D"), "missing")Sheets ไม่มี NaT — ต้องจัดการ error เองทุกครั้ง
#include <stdio.h>#include <time.h>#include <string.h>
int main() { // C ไม่มี NaT — ใช้ค่าพิเศษเอง (เช่น -1 หรือ 0) time_t dates[] = {1705276800, -1, 1710892800}; // 2024-01-15 missing 2024-03-20
time_t now = time(NULL);
for (int i = 0; i < 3; i++) { if (dates[i] == -1) { printf("Record %d: MISSING DATE\n", i); continue; }
double diff_days = difftime(now, dates[i]) / 86400.0; struct tm *t = localtime(&dates[i]); printf("Record %d: %d-%02d-%02d (%.0f days ago)\n", i, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, diff_days); }
return 0;}C ไม่มี built-in “missing date” — programmer ต้องกำหนดค่าพิเศษ (sentinel value) เอง เช่น -1 หรือ 0 แล้วเช็คทุกครั้ง
import pandas as pd
# แปลง text → datetimedates = pd.Series(["2024-01-15", "2024-03-20", "not-a-date", None, "2024-06-01"])
# errors="raise" (default) → crash ถ้ามี bad value# pd.to_datetime(dates) # ValueError!
# errors="coerce" → bad values กลายเป็น NaTresult = pd.to_datetime(dates, errors="coerce")print(result)# 0 2024-01-15# 1 2024-03-20# 2 NaT ← "not-a-date" กลายเป็น NaT# 3 NaT ← None กลายเป็น NaT# 4 2024-06-01# dtype: datetime64[ns]
# NaT propagationtoday = pd.Timestamp("2026-04-24")days_since = today - resultprint(days_since)# 0 830 days# 1 766 days# 2 NaT ← NaT แพร่กระจาย!# 3 NaT ← NaT แพร่กระจาย!# 4 693 days
# หา missing datesprint(f"Missing dates: {result.isna().sum()}") # 2
# เฉพาะ rows ที่มีวันที่valid = result.dropna()print(f"Valid dates: {len(valid)}") # 3
# dt accessor — ดึงส่วนประกอบprint(result.dt.year)# 0 2024.0# 1 2024.0# 2 NaN ← NaT → NaN เมื่อดึง year# 3 NaN# 4 2024.0
print(result.dt.month_name())# 0 January# 1 March# 2 NaN# 3 NaN# 4 JuneCREATE TABLE members ( name VARCHAR(50), join_date DATE);
INSERT INTO members VALUES ('Alice', '2024-01-15');INSERT INTO members VALUES ('Bob', NULL);INSERT INTO members VALUES ('Carol', '2024-03-20');
-- คำนวณจำนวนวันSELECT name, join_date, CURRENT_DATE - join_date AS days_sinceFROM members;-- Alice | 2024-01-15 | 830-- Bob | NULL | NULL ← NULL propagation (เหมือน NaT)-- Carol | 2024-03-20 | 766
-- หา missingSELECT COUNT(*) FROM members WHERE join_date IS NULL;-- 1
-- handle missing ด้วย COALESCESELECT name, COALESCE(join_date, CURRENT_DATE) AS join_date_clean, CURRENT_DATE - COALESCE(join_date, CURRENT_DATE) AS days_sinceFROM members;-- Bob → 0 days (ใช้วันนี้แทน)NaT vs NaN vs NULL vs Empty
Section titled “NaT vs NaN vs NULL vs Empty”| เครื่องมือ | Missing Date |
|---|---|
| Google Sheets | empty cell หรือ #VALUE! error |
| C | ไม่มี — ต้องใช้ sentinel value เอง |
| pandas | NaT (Not a Time) |
| SQL | NULL |
ทุกตัว propagate ผ่านการคำนวณ: missing + 7 days = missing