ไทย

คู่มือเชิงลึกเกี่ยวกับ JavaScript Temporal API ซึ่งเป็นโซลูชันสมัยใหม่สำหรับการจัดการวันและเวลาอย่างมีประสิทธิภาพในบริบทนานาชาติที่หลากหลาย

JavaScript Temporal API: การจัดการวันและเวลาสมัยใหม่สำหรับผู้ชมทั่วโลก

อ็อบเจกต์ `Date` ของ JavaScript เป็นสิ่งที่สร้างความหงุดหงิดให้กับนักพัฒนามาอย่างยาวนาน คุณสมบัติที่เปลี่ยนแปลงได้ (mutability) API ที่ไม่สอดคล้องกัน และการรองรับไทม์โซนที่ไม่ดี ทำให้เกิดไลบรารีจำนวนมาก เช่น Moment.js และ date-fns เพื่อมาเติมเต็มช่องว่างเหล่านี้ แต่ตอนนี้ ด้วย Temporal API ทำให้ JavaScript มีโซลูชันสมัยใหม่ในตัวสำหรับการจัดการวันและเวลาด้วยความชัดเจนและความแม่นยำที่ดียิ่งขึ้น บทความนี้จะให้ภาพรวมที่ครอบคลุมของ Temporal API โดยเน้นที่คุณสมบัติ ประโยชน์ และการใช้งานในบริบทนานาชาติที่หลากหลาย

Temporal API คืออะไร?

Temporal API คืออ็อบเจกต์ส่วนกลาง (global object) ใหม่ใน JavaScript ที่ออกแบบมาเพื่อแก้ไขข้อบกพร่องของอ็อบเจกต์ `Date` โดยมี API ที่สะอาดและไม่เปลี่ยนรูป (immutable) สำหรับการทำงานกับวัน เวลา ไทม์โซน และระบบปฏิทิน ที่สำคัญคือ มีเป้าหมายเพื่อแสดงแนวคิดเกี่ยวกับวันและเวลาในลักษณะที่สอดคล้องกับการใช้งานและความคาดหวังในโลกแห่งความเป็นจริงมากขึ้น ทำให้การทำให้เป็นสากล (internationalization) ตรงไปตรงมามากขึ้น

คุณสมบัติหลัก:

อ็อบเจกต์พื้นฐานของ Temporal

Temporal API แนะนำอ็อบเจกต์ประเภทใหม่ๆ หลายอย่าง นี่คือส่วนสำคัญบางส่วน:

การทำงานกับวันที่

การสร้าง `Temporal.PlainDate`

ในการสร้าง `Temporal.PlainDate` คุณสามารถใช้ constructor:

const plainDate = new Temporal.PlainDate(2024, 10, 27); // ปี, เดือน (1-12), วัน
console.log(plainDate.toString()); // ผลลัพธ์: 2024-10-27

คุณยังสามารถใช้เมธอด `from` ซึ่งรับสตริงในรูปแบบ ISO 8601:

const plainDateFromString = Temporal.PlainDate.from('2024-10-27');
console.log(plainDateFromString.toString()); // ผลลัพธ์: 2024-10-27

การเข้าถึงส่วนประกอบของวันที่

คุณสามารถเข้าถึงส่วนประกอบแต่ละส่วนของวันที่ได้โดยใช้คุณสมบัติ เช่น `year`, `month` และ `day`:

console.log(plainDate.year); // ผลลัพธ์: 2024
console.log(plainDate.month); // ผลลัพธ์: 10
console.log(plainDate.day); // ผลลัพธ์: 27

การคำนวณทางคณิตศาสตร์กับวันที่

หากต้องการบวกหรือลบวัน สัปดาห์ เดือน หรือปี ให้ใช้เมธอด `plus` และ `minus` เมธอดเหล่านี้จะส่งคืนอ็อบเจกต์ `Temporal.PlainDate` ใหม่:

const nextWeek = plainDate.plus({ days: 7 });
console.log(nextWeek.toString()); // ผลลัพธ์: 2024-11-03

const lastMonth = plainDate.minus({ months: 1 });
console.log(lastMonth.toString()); // ผลลัพธ์: 2024-09-27

การเปรียบเทียบวันที่

คุณสามารถเปรียบเทียบวันที่ได้โดยใช้เมธอด `compare`:

const date1 = new Temporal.PlainDate(2024, 10, 27);
const date2 = new Temporal.PlainDate(2024, 11, 15);

console.log(Temporal.PlainDate.compare(date1, date2)); // ผลลัพธ์: -1 (date1 มาก่อน date2)

การทำงานกับเวลา

การสร้าง `Temporal.PlainTime`

ในการสร้าง `Temporal.PlainTime` ให้ใช้ constructor:

const plainTime = new Temporal.PlainTime(10, 30, 0); // ชั่วโมง, นาที, วินาที
console.log(plainTime.toString()); // ผลลัพธ์: 10:30:00

หรือใช้เมธอด `from` กับสตริงเวลาในรูปแบบ ISO 8601:

const plainTimeFromString = Temporal.PlainTime.from('10:30:00');
console.log(plainTimeFromString.toString()); // ผลลัพธ์: 10:30:00

การเข้าถึงส่วนประกอบของเวลา

console.log(plainTime.hour); // ผลลัพธ์: 10
console.log(plainTime.minute); // ผลลัพธ์: 30
console.log(plainTime.second); // ผลลัพธ์: 0

การคำนวณทางคณิตศาสตร์กับเวลา

const later = plainTime.plus({ minutes: 15 });
console.log(later.toString()); // ผลลัพธ์: 10:45:00

การทำงานกับวันและเวลาร่วมกัน

การสร้าง `Temporal.PlainDateTime`

คุณสามารถสร้าง `Temporal.PlainDateTime` ได้โดยตรงหรือโดยการรวม `Temporal.PlainDate` และ `Temporal.PlainTime` เข้าด้วยกัน:

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
console.log(plainDateTime.toString()); // ผลลัพธ์: 2024-10-27T10:30:00

const date = new Temporal.PlainDate(2024, 10, 27);
const time = new Temporal.PlainTime(10, 30, 0);
const combinedDateTime = date.toPlainDateTime(time);
console.log(combinedDateTime.toString()); // ผลลัพธ์: 2024-10-27T10:30:00

ไทม์โซน (Time Zones)

การจัดการไทม์โซนอย่างถูกต้องเป็นสิ่งสำคัญสำหรับแอปพลิเคชันที่ต้องติดต่อกับผู้ใช้ในสถานที่ต่างๆ Temporal API รองรับไทม์โซนอย่างแข็งแกร่งผ่านอ็อบเจกต์ `Temporal.ZonedDateTime` และ `Temporal.TimeZone`

การสร้าง `Temporal.ZonedDateTime`

ในการสร้าง `Temporal.ZonedDateTime` คุณต้องมี `Temporal.PlainDateTime` และตัวระบุไทม์โซน ตัวระบุไทม์โซนจะอิงตามฐานข้อมูลไทม์โซนของ IANA (เช่น `America/Los_Angeles`, `Europe/London`, `Asia/Tokyo`)

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
console.log(zonedDateTime.toString()); // ผลลัพธ์: 2024-10-27T10:30:00-07:00[America/Los_Angeles] (ค่า offset จะขึ้นอยู่กับกฎ DST)

อีกทางเลือกหนึ่งคือการสร้าง `Temporal.ZonedDateTime` จาก `Instant`

const instant = Temporal.Instant.fromEpochSeconds(1666866600); // ตัวอย่าง timestamp
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO(timeZone); // ไทม์โซนเช่น 'America/Los_Angeles'
console.log(zonedDateTimeFromInstant.toString());

การแปลงระหว่างไทม์โซน

คุณสามารถแปลง `Temporal.ZonedDateTime` เป็นไทม์โซนอื่นได้โดยใช้เมธอด `withTimeZone`:

const newTimeZone = 'Europe/London';
const zonedDateTimeInLondon = zonedDateTime.withTimeZone(newTimeZone);
console.log(zonedDateTimeInLondon.toString()); // ผลลัพธ์: 2024-10-27T18:30:00+01:00[Europe/London]

การทำงานกับค่า Offset ของไทม์โซน

เมธอด `getOffsetStringFor` ของอ็อบเจกต์ `Temporal.TimeZone` จะให้ค่าสตริง offset สำหรับ `Temporal.Instant` ที่กำหนด:

const timeZoneObject = new Temporal.TimeZone(timeZone);
const offsetString = timeZoneObject.getOffsetStringFor(zonedDateTime.toInstant());
console.log(offsetString); // ผลลัพธ์: -07:00 (ขึ้นอยู่กับกฎ DST)

สิ่งสำคัญคือต้องใช้ตัวระบุไทม์โซนของ IANA ที่ถูกต้องเพื่อการคำนวณที่แม่นยำ ตัวระบุเหล่านี้ได้รับการดูแลและอัปเดตเป็นประจำเพื่อสะท้อนการเปลี่ยนแปลงของเวลาออมแสง (daylight saving time) และขอบเขตของไทม์โซน

ช่วงเวลา (Durations)

อ็อบเจกต์ `Temporal.Duration` แทนช่วงของเวลา สามารถใช้เพื่อบวกหรือลบออกจากวันและเวลาได้

การสร้าง `Temporal.Duration`

คุณสามารถสร้าง `Temporal.Duration` โดยใช้ constructor โดยระบุปี เดือน วัน ชั่วโมง นาที วินาที มิลลิวินาที ไมโครวินาที และนาโนวินาที:

const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9); // ปี, เดือน, วัน, ชั่วโมง, นาที, วินาที, มิลลิวินาที, ไมโครวินาที, นาโนวินาที
console.log(duration.toString()); // ผลลัพธ์: P1Y2M3DT4H5M6.007008009S

หรือโดยใช้สตริงช่วงเวลาในรูปแบบ ISO 8601:

const durationFromString = Temporal.Duration.from('P1Y2M3DT4H5M6S');
console.log(durationFromString.toString()); // ผลลัพธ์: P1Y2M3DT4H5M6S

การบวกช่วงเวลาเข้ากับวันและเวลา

const plainDate = new Temporal.PlainDate(2024, 10, 27);
const duration = new Temporal.Duration(0, 0, 7); // 7 วัน
const newDate = plainDate.plus(duration);
console.log(newDate.toString()); // ผลลัพธ์: 2024-11-03

โปรดทราบว่าการบวกช่วงเวลาที่เกี่ยวข้องกับเดือนหรือปีเข้ากับวันที่ต้องพิจารณาอย่างรอบคอบ เนื่องจากจำนวนวันในหนึ่งเดือนหรือหนึ่งปีอาจแตกต่างกันไป

ระบบปฏิทิน (Calendar Systems)

Temporal API รองรับระบบปฏิทินที่แตกต่างกันนอกเหนือจากปฏิทินเกรกอเรียน ซึ่งเป็นสิ่งสำคัญสำหรับแอปพลิเคชันที่ต้องการจัดการวันที่ในบริบททางวัฒนธรรมที่หลากหลาย แม้ว่าการรองรับยังคงมีการพัฒนาอยู่ แต่ก็เป็นพื้นฐานสำหรับการขยายในอนาคต

การใช้ปฏิทินทางเลือก

หากต้องการใช้ปฏิทินที่เฉพาะเจาะจง คุณสามารถระบุได้เมื่อสร้างอ็อบเจกต์ Temporal:

const hebrewDate = new Temporal.PlainDate(5785, 1, 1, { calendar: 'hebrew' });
console.log(hebrewDate.toString()); // ผลลัพธ์ที่เฉพาะเจาะจงอาจแตกต่างกันไปขึ้นอยู่กับการใช้งานและการจัดรูปแบบ ณ เวลาที่เขียนบทความนี้ต้องใช้ polyfill ในหลายสภาพแวดล้อม

สำคัญ: การรองรับปฏิทินที่ไม่ใช่เกรกอเรียนอาจต้องใช้ polyfills หรือการรองรับจากเบราว์เซอร์/สภาพแวดล้อมที่เฉพาะเจาะจง โปรดตรวจสอบเอกสาร Temporal API และตารางความเข้ากันได้ของเบราว์เซอร์สำหรับข้อมูลล่าสุด

การจัดรูปแบบวันและเวลา

ในขณะที่ Temporal API มุ่งเน้นไปที่การจัดการวันและเวลา การจัดรูปแบบมักจะถูกจัดการโดยอ็อบเจกต์ `Intl.DateTimeFormat` ซึ่งเป็นส่วนหนึ่งของ Internationalization API อ็อบเจกต์ Temporal ทำงานร่วมกับ `Intl.DateTimeFormat` ได้อย่างราบรื่น

การใช้ `Intl.DateTimeFormat`

นี่คือวิธีจัดรูปแบบ `Temporal.PlainDate` โดยใช้ `Intl.DateTimeFormat`:

const plainDate = new Temporal.PlainDate(2024, 10, 27);
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatter.format(plainDate)); // ผลลัพธ์: October 27, 2024

const formatterGerman = new Intl.DateTimeFormat('de-DE', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatterGerman.format(plainDate)); // ผลลัพธ์: 27. Oktober 2024

คุณสามารถปรับแต่งตัวเลือกรูปแบบให้เหมาะกับความต้องการของคุณได้ อาร์กิวเมนต์แรกของ `Intl.DateTimeFormat` คือ locale ซึ่งจะกำหนดภาษาและธรรมเนียมของภูมิภาคที่ใช้ในการจัดรูปแบบ การใช้ locales ที่แตกต่างกัน (เช่น 'en-US', 'de-DE', 'fr-FR', 'ja-JP') จะให้ผลลัพธ์ในรูปแบบที่แตกต่างกัน

การจัดรูปแบบ `Temporal.ZonedDateTime`

การจัดรูปแบบ `Temporal.ZonedDateTime` ก็คล้ายกัน แต่คุณยังสามารถรวมข้อมูลไทม์โซนไว้ในผลลัพธ์ได้ด้วย:

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);

const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'short' });
console.log(formatter.format(zonedDateTime)); // ผลลัพธ์: October 27, 2024, 10:30 AM PDT (ตัวย่อไทม์โซนขึ้นอยู่กับกฎ DST)

แนวทางปฏิบัติที่ดีที่สุดสำหรับการทำให้เป็นสากล

เมื่อทำงานกับวันและเวลาในบริบทสากล ควรคำนึงถึงแนวทางปฏิบัติที่ดีที่สุดต่อไปนี้:

การเปรียบเทียบ Temporal API กับอ็อบเจกต์ Date แบบดั้งเดิม

นี่คือตารางที่เน้นความแตกต่างที่สำคัญและข้อดีของ Temporal API เมื่อเทียบกับอ็อบเจกต์ `Date` แบบดั้งเดิม:

คุณสมบัติ อ็อบเจกต์ `Date` แบบดั้งเดิม Temporal API
การเปลี่ยนแปลงค่า (Mutability) เปลี่ยนแปลงได้ (แก้ไขอ็อบเจกต์เดิม) ไม่เปลี่ยนรูป (ส่งคืนอ็อบเจกต์ใหม่)
การรองรับไทม์โซน จำกัดและมักมีปัญหา แข็งแกร่งและแม่นยำ อิงตามฐานข้อมูลไทม์โซนของ IANA
API ไม่สอดคล้องและใช้งานยาก ชัดเจน สอดคล้อง และใช้งานง่าย
ความแม่นยำ มิลลิวินาที (Millisecond) นาโนวินาที (Nanosecond)
ระบบปฏิทิน จำกัดเฉพาะเกรกอเรียน รองรับระบบปฏิทินทางเลือก (พร้อมการสนับสนุนที่กำลังพัฒนา)
การทำให้เป็นสากล ต้องใช้ไลบรารีภายนอกเพื่อการทำให้เป็นสากลที่แข็งแกร่ง รองรับในตัวและทำงานร่วมกับ `Intl.DateTimeFormat` ได้อย่างราบรื่น

การรองรับของเบราว์เซอร์และ Polyfills

เนื่องจากเป็น API ที่ค่อนข้างใหม่ การรองรับ Temporal API ของเบราว์เซอร์ยังคงมีการพัฒนาอยู่ โปรดตรวจสอบตารางความเข้ากันได้ของเบราว์เซอร์ล่าสุด (เช่น บน MDN Web Docs) เพื่อดูว่าเบราว์เซอร์และสภาพแวดล้อมใดที่รองรับโดยกำเนิด สำหรับเบราว์เซอร์รุ่นเก่าหรือสภาพแวดล้อมที่ไม่มีการรองรับโดยกำเนิด คุณสามารถใช้ polyfills เพื่อให้มีฟังก์ชันการทำงานของ Temporal API ได้ ค้นหา "Temporal API polyfill" บนเว็บเพื่อหาตัวเลือกที่เหมาะสม

บทสรุป

JavaScript Temporal API แสดงถึงก้าวสำคัญในการจัดการวันและเวลาใน JavaScript คุณสมบัติความไม่เปลี่ยนรูป, API ที่ชัดเจน, การรองรับไทม์โซนที่แข็งแกร่ง และความสามารถของระบบปฏิทิน ทำให้เป็นเครื่องมือที่ทรงพลังสำหรับนักพัฒนาที่สร้างแอปพลิเคชันที่ต้องการทำงานกับวันและเวลาอย่างถูกต้องและเชื่อถือได้ในบริบทนานาชาติที่หลากหลาย แม้ว่าการรองรับของเบราว์เซอร์ยังคงมีการพัฒนาอยู่ แต่ประโยชน์ของ Temporal API ทำให้คุ้มค่าแก่การเรียนรู้และนำไปใช้สำหรับโครงการใหม่ๆ การนำ Temporal API มาใช้และปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดในการทำให้เป็นสากล จะช่วยให้คุณสร้างแอปพลิเคชันที่มอบประสบการณ์ด้านวันและเวลาที่ราบรื่นและแม่นยำสำหรับผู้ใช้ทั่วโลกได้

แหล่งข้อมูลเพิ่มเติม