สูตรที่ทุกคนรู้คือ ค.ศ. = พ.ศ. − 543 ปี 2569 คือ 2026 ฟังดูจบในบรรทัดเดียว แต่พอเอาไปใช้กับข้อมูลจริงที่กรอกมาจากหลายคนหลายระบบ ปัญหาจะโผล่มาเยอะกว่าที่คิด ค่าบางแถวเป็น พ.ศ. บางแถวเป็น ค.ศ. บางช่องพิมพ์ด้วยเลขไทย บางช่องมีปีแค่สองหลัก และ Excel ก็แสดงปีไม่ตรงกับที่เก็บจริง บทความนี้อธิบายว่าปฏิทินสองแบบนี้ต่างกันอย่างไร วิธีตรวจว่าค่าที่รับมาเป็นแบบไหน และโค้ดที่ใช้ได้จริงใน JavaScript, Excel และผ่าน API
พ.ศ. กับ ค.ศ. ต่างกันแค่เลขปีจริงหรือ
พุทธศักราชที่ไทยใช้ในราชการนับจากปีปรินิพพาน ซึ่งห่างจากคริสต์ศักราช 543 ปี วัน เดือน และกฎปีอธิกสุรทินเหมือนกันทุกประการ เพราะไทยใช้ปฏิทินเกรกอเรียนกับเลขปีแบบพุทธศักราชมาตั้งแต่ปี 2484 (ก่อนหน้านั้นปีไทยเริ่ม 1 เมษายน ซึ่งเป็นเหตุผลที่ข้อมูลประวัติศาสตร์ก่อนปีนั้นต้องระวังเป็นพิเศษ) สำหรับข้อมูลทั่วไปในระบบธุรกิจ การแปลงจึงเป็นเรื่องของเลขปีล้วนๆ ไม่ต้องเลื่อนวันหรือเดือน
ปัญหาจริงจึงไม่ได้อยู่ที่เลข 543 แต่อยู่ที่ จะรู้ได้อย่างไรว่าค่าที่รับมาเป็น พ.ศ. หรือ ค.ศ. ฟอร์มหนึ่งให้กรอก 3/10/2569 อีกระบบส่ง 2026-10-03 มา ถ้าลบ 543 ทุกค่า ค่าที่เป็น ค.ศ. อยู่แล้วจะกลายเป็นปี 1483 เงียบๆ โดยไม่มี error
กฎเส้นแบ่ง 2400
วิธีที่ใช้ได้ดีในทางปฏิบัติคือดูขนาดของปี ปีที่มากกว่าหรือเท่ากับ 2400 ถือเป็น พ.ศ. ปีที่น้อยกว่าถือเป็น ค.ศ. เพราะไม่มีใครกรอกข้อมูลธุรกิจของปี ค.ศ. 2400 จริงๆ และ พ.ศ. ปัจจุบันอยู่แถว 2500 กว่า เส้นแบ่งนี้ปลอดภัยสำหรับข้อมูลทั่วไป แต่ไม่เหมาะกับงานประวัติศาสตร์ที่มีปี ค.ศ. ต่ำกว่า 1857 (ซึ่งคือ พ.ศ. 2400) ปนอยู่ API ที่พูดถึงท้ายบทความใช้กฎเดียวกันนี้
ใน JavaScript
อย่าใช้ new Date("3/10/2569") เพราะ JavaScript จะตีความแบบอเมริกันว่าเดือนมาก่อน (10 มีนาคม) และไม่รู้จัก พ.ศ. ให้แยกส่วนเองเสมอ และสร้างวันที่ด้วย UTC เพื่อกันปัญหาวันเลื่อนตามโซนเวลา
function toGregorian(d, m, y) {
const year = y >= 2400 ? y - 543 : y;
return new Date(Date.UTC(year, m - 1, d));
}
toGregorian(3, 10, 2569).toISOString().slice(0, 10); // "2026-10-03"ถ้าต้องการแสดงผลเป็นภาษาไทย Intl.DateTimeFormat รู้จักปฏิทินไทยอยู่แล้ว locale th-TH ให้ปี พ.ศ. มาเองโดยไม่ต้องบวก 543
const date = new Date(Date.UTC(2026, 9, 3));
new Intl.DateTimeFormat("th-TH", {dateStyle: "long", timeZone: "UTC"}).format(date);
// "3 ตุลาคม 2569"
new Intl.DateTimeFormat("th-TH-u-ca-gregory", {dateStyle: "long", timeZone: "UTC"}).format(date);
// "3 ตุลาคม 2026"ส่วนขยาย -u-ca-gregory บังคับให้ใช้เลขปี ค.ศ. กับชื่อเดือนไทย ซึ่งมีประโยชน์เมื่อหน้าจอต้องแสดงภาษาไทยแต่ระบบหลังบ้านตกลงกันว่าใช้ ค.ศ.
ใน Excel
Excel มีสองสถานการณ์ที่หน้าตาเหมือนกันแต่ต้องแก้คนละวิธี
กรณีที่ 1: เซลล์เป็นวันที่จริง ถ้า Excel แสดงปีเป็น พ.ศ. เพราะตั้งค่า locale ไทย ค่าที่เก็บในเซลล์จริงๆ เป็นเลขลำดับวัน (serial) ที่อิง ค.ศ. อยู่แล้ว แค่เปลี่ยนรูปแบบตัวเลขเป็น d/m/yyyy ก็เห็นเป็น ค.ศ. และถ้าต้องการให้แสดง พ.ศ. โดยไม่แตะค่า ใช้รูปแบบ d/m/bbbb (ตัว b คือรหัสปีพุทธศักราชใน Excel ภาษาไทย) ห้ามเอา 543 ไปบวกลบกับเซลล์วันที่โดยตรง เพราะจะได้วันที่เลื่อนไป 543 วัน ไม่ใช่ 543 ปี
กรณีที่ 2: เซลล์เป็นข้อความ เช่นมีคนพิมพ์ 3/10/2569 มาในไฟล์ที่ import จากระบบอื่น ต้องแยกส่วนเอง สมมติข้อความอยู่ใน A1 และรูปแบบเป็น วัน/เดือน/ปี 4 หลัก
=DATE(VALUE(RIGHT(A1,4))-543,
VALUE(MID(A1,FIND("/",A1)+1,FIND("/",A1,FIND("/",A1)+1)-FIND("/",A1)-1)),
VALUE(LEFT(A1,FIND("/",A1)-1)))สูตรยาวแต่ตรงไปตรงมา: ปีลบ 543 เดือนอยู่ตรงกลาง วันอยู่ข้างหน้า ถ้าไฟล์มีหลายรูปแบบปนกัน (บางแถวมีขีด บางแถวเป็นเลขไทย) การแปลงด้วยสคริปต์หรือ API ก่อนนำเข้า Excel จะง่ายกว่าและตรวจสอบได้ดีกว่า
กับดักที่เจอบ่อย
- ปีสองหลัก
3/10/69ไม่มีทางรู้ว่า 2569 หรือ 1969 ควรบังคับให้กรอก 4 หลักตั้งแต่ต้นแทนที่จะเดาทีหลัง - เลขไทย
๓/๑๐/๒๕๖๙โค้ดส่วนใหญ่ parse ไม่ได้ ต้องแปลง ๐–๙ เป็น 0–9 ก่อน (text.replace(/[๐-๙]/g, d => "๐๑๒๓๔๕๖๗๘๙".indexOf(d))) - 29 กุมภาพันธ์ ปี 2567 คือ 2024 ซึ่งเป็นปีอธิกสุรทิน ถ้าตรวจความถูกต้องของวันที่ก่อนลบ 543 โค้ดจะเช็กกับปี 2567 (ซึ่งหารด้วย 4 ไม่ลงตัว) แล้วปฏิเสธวันที่ที่ถูกต้อง ให้แปลงปีก่อนเสมอแล้วค่อยตรวจ
- วันที่ไม่มีจริง
31/2/2569บางไลบรารีปัดไปเป็น 3 มีนาคมเงียบๆ (เช่นnew Date(2026, 1, 31)ใน JavaScript) ควรปฏิเสธและแจ้งผู้ใช้แทน - Timezone
2026-10-03T00:00:00Zคือ 7 โมงเช้าวันเดียวกันในไทย แต่2026-10-02T17:00:00Zก็คือเที่ยงคืนวันที่ 3 ในไทยเช่นกัน ถ้า parse ในโซนหนึ่งแล้ว format ในอีกโซนหนึ่ง วันอาจเลื่อนไปหนึ่งวัน การเก็บเฉพาะวันที่ (ไม่มีเวลา) ด้วย UTC เที่ยงคืนช่วยตัดปัญหานี้
ให้ API ช่วยเมื่อไม่อยากเขียนเองทุกภาษา
endpoint GET /api/v1/tools/thai/date รับ YYYY-MM-DD, D/M/YYYY และ D-M-YYYY ทั้งเลขไทยและอารบิก ใช้กฎ 2400 ตัดสินว่าเป็น พ.ศ. หรือ ค.ศ. และคืนทุกรูปแบบในครั้งเดียว ไม่ต้องมี key ไม่จำกัดจำนวนครั้ง
curl "https://reefsight.tech/api/v1/tools/thai/date?date=3/10/2569"{
"data": {
"iso": "2026-10-03",
"year": 2026,
"buddhistYear": 2569,
"weekday": "เสาร์",
"thaiLong": "วันเสาร์ที่ 3 ตุลาคม พ.ศ. 2569",
"thaiShort": "3 ต.ค. 2569",
"thaiDigits": "วันเสาร์ที่ ๓ ตุลาคม พ.ศ. ๒๕๖๙"
}
}ส่ง 2026-10-05 (ค.ศ.) ก็ได้ buddhistYear: 2569 กลับมา ส่ง ๕/๑๐/๒๕๖๙ ก็อ่านได้ ส่ง 29/2/2567 ได้ 2024-02-29 ถูกต้องเพราะแปลงปีก่อนตรวจ และส่ง 31/2/2569 จะได้ 422 that day does not exist ไม่ปัดให้
จาก JavaScript บนเว็บไซต์ของคุณเรียกตรงได้ เพราะ API ส่ง CORS header
const url = new URL("https://reefsight.tech/api/v1/tools/thai/date");
url.searchParams.set("date", "๕/๑๐/๒๕๖๙");
const {data} = await fetch(url).then((r) => r.json());
console.log(data.iso, data.thaiShort); // "2026-10-05" "5 ต.ค. 2569"ของที่มักต้องใช้คู่กันในฟอร์มไทย
หน้าเดียวกันรวม endpoint เล็กๆ ที่นักพัฒนาไทยต้องเขียนเองบ่อยไว้ด้วย
/thai/baht-text?amount=1234.50อ่านจำนวนเงินเป็นตัวอักษรแบบใบเสร็จและเช็ค ได้หนึ่งพันสองร้อยสามสิบสี่บาทห้าสิบสตางค์และformatted: "1,234.50"จำนวนเต็มลงท้ายถ้วนมีแต่สตางค์ไม่ใส่คำว่าศูนย์บาท ติดลบขึ้นต้นด้วยลบ/thai/digits?text=ปี 2569 ราคา 1,250 บาทแปลงเลขอารบิกเป็นเลขไทย (ปี ๒๕๖๙ ราคา ๑,๒๕๐ บาท) และกลับทางด้วยto=arabic/thai/id?value=1-2345-67890-12-1ตรวจ checksum เลขบัตรประชาชนและเลขนิติบุคคล ขีดและช่องว่างถูกตัดให้ ได้valid,normalizedและtypeเป็นpersonหรือjuristic(ขึ้นต้นด้วย 0) ถ้าผิดยังตอบ 200 แต่valid: falseพร้อมreason/thai/speak.mp3?text=...อ่านข้อความเป็นเสียง เช่นเอาคำอ่านจำนวนเงินหรือthaiLongไปอ่านให้ฟัง
ส่วนการตัดคำและนับคำภาษาไทยไม่ต้องเรียก API เลย เพราะ Intl.Segmenter ในเบราว์เซอร์และ Node 16 ขึ้นไปทำได้บนเครื่อง
ข้อควรระวัง
- กฎ 2400 มีขอบ ค.ศ. 2400 ขึ้นไปจะถูกตีความเป็น พ.ศ. จึงใส่ ค.ศ. ตั้งแต่ 2400 ไม่ได้ (ซึ่งไม่น่ามีใครใช้) และปี ค.ศ. ต่ำกว่า 1857 ที่กรอกเป็น พ.ศ. จะถูกมองเป็น ค.ศ.
- ไม่รองรับปฏิทินจันทรคติหรือเวลา
dateรับเฉพาะวันที่ ไม่รับชั่วโมงนาที และไม่แปลงวันทางจันทรคติ - baht-text รับตัวเลขน้อยกว่า 1e15 ทศนิยมไม่เกิน 2 ตำแหน่ง
1.234ได้ 422 ส่วนdigitsรับข้อความไม่เกิน 10,000 ไบต์ ซึ่งผ่าน URL จึงราว 1,700 ตัวอักษรไทย - ตรวจเลขบัตรบอกได้แค่ checksum ถูก ไม่ได้ยืนยันว่ามีบุคคลนี้จริง และไม่เชื่อมฐานข้อมูลราชการ
- เสียงอ่านมีโควตา
speak.mp3ใช้บริการ neural TTS ภายนอก จำกัด 30 ครั้งต่อ IP ทุก 15 นาที ข้อความไม่เกิน 300 ตัวอักษร ถ้าบริการไม่ตอบจะได้ 503 ส่วน endpoint อื่นไม่จำกัดและไม่เก็บอะไร
คำถามที่พบบ่อย
แปลงวันที่ย้อนหลังได้ถึงปีไหน ทุกปีในปฏิทินเกรกอเรียน ตราบใดที่เลขปีเข้ากฎ 2400 คือ ค.ศ. ต่ำกว่า 2400 และ พ.ศ. ตั้งแต่ 2400 ขึ้นไป
คำอ่านจำนวนเงินตรงกับที่ธนาคารใช้ไหม ใช้แบบเดียวกับใบเสร็จและเช็ค คือหน่วยล้าน ยี่สิบ เอ็ด และลงท้ายด้วย ถ้วน เมื่อไม่มีสตางค์ ถ้าเจอกรณีที่ต่างจากที่คุณใช้ ส่งความเห็นมาพร้อมตัวเลขได้
เลขผู้เสียภาษีของบริษัทตรวจได้ไหม
ได้ เลขนิติบุคคล 13 หลักขึ้นต้นด้วย 0 ใช้ checksum เดียวกับเลขบัตรประชาชน ผลจะได้ type: "juristic"
ลองพิมพ์แล้วเห็นผลทุกฟังก์ชันพร้อมกัน
หน้า reefsight.tech › thai-text มีช่องเดียวที่พิมพ์แล้วเห็นผลตัดคำ เลขไทย วันที่ จำนวนเงิน และตรวจเลขบัตรพร้อมกันเป็นการ์ด ฟังคำอ่านเป็นเสียงและดาวน์โหลด MP3 ได้ พร้อมเอกสาร API ที่ตัวอย่างทุกตัวถูกรันตรวจกับระบบจริง ใช้ฟรี ไม่ต้องสมัคร และไม่เก็บข้อความที่พิมพ์
