คู่มือฉบับสมบูรณ์สำหรับการใช้ Temporal API ของ JavaScript เพื่อการคำนวณช่วงเวลาที่แม่นยำและเข้าใจง่าย ครอบคลุมตั้งแต่การสร้าง duration พื้นฐานไปจนถึงการคำนวณและการจัดรูปแบบขั้นสูง
JavaScript Temporal Duration: การคำนวณช่วงเวลาอย่างเชี่ยวชาญ
Temporal API ของ JavaScript นำเสนอวิธีที่ทันสมัยและทรงพลังในการจัดการกับวันที่ เวลา และช่วงเวลา อ็อบเจกต์ Temporal.Duration
แทนความยาวของเวลา ซึ่งเป็นแนวทางที่ชัดเจนและเข้าใจง่ายในการคำนวณกับช่วงเวลา บทความนี้จะเจาะลึกรายละเอียดของ Temporal.Duration
โดยสาธิตวิธีการสร้าง จัดการ และจัดรูปแบบระยะเวลาสำหรับการใช้งานในกรณีต่างๆ
Temporal.Duration คืออะไร?
Temporal.Duration
แทนช่วงของเวลา โดยแสดงในรูปของปี เดือน วัน ชั่วโมง นาที วินาที และเศษส่วนของวินาที (มิลลิวินาที ไมโครวินาที นาโนวินาที) ซึ่งแตกต่างจากอ็อบเจกต์ Date
ที่แทนจุดเวลาที่เฉพาะเจาะจง Temporal.Duration
จะแทนจำนวนของเวลา โดยยึดตามรูปแบบระยะเวลาของ ISO 8601 (เช่น P1Y2M10DT2H30M
แทน 1 ปี 2 เดือน 10 วัน 2 ชั่วโมง และ 30 นาที) Temporal API ถูกออกแบบมาให้ใช้งานง่ายและมีโอกาสเกิดข้อผิดพลาดน้อยกว่าอ็อบเจกต์ Date
แบบดั้งเดิม
การสร้างอ็อบเจกต์ Temporal.Duration
มีหลายวิธีในการสร้างอ็อบเจกต์ Temporal.Duration
:
1. จาก Plain Object
คุณสามารถสร้าง duration ได้โดยการส่งผ่านอ็อบเจกต์ที่มีคุณสมบัติตามที่ต้องการ:
const duration = new Temporal.Duration(1, 2, 10, 2, 30, 0, 0, 0);
console.log(duration.toString()); // ผลลัพธ์: P1Y2M10DT2H30M
โค้ดนี้จะสร้าง duration ที่มีระยะเวลา 1 ปี 2 เดือน 10 วัน 2 ชั่วโมง และ 30 นาที โปรดทราบว่าอาร์กิวเมนต์จะเรียงตามลำดับต่อไปนี้: years
, months
, weeks
, days
, hours
, minutes
, seconds
, milliseconds
, microseconds
, nanoseconds
.
2. จากสตริง ISO 8601
คุณยังสามารถสร้าง duration จากสตริงระยะเวลาตามมาตรฐาน ISO 8601 โดยใช้ Temporal.Duration.from()
:
const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
console.log(duration.toString()); // ผลลัพธ์: P1Y2M10DT2H30M
วิธีนี้มีประโยชน์อย่างยิ่งเมื่อต้องจัดการกับ duration ที่เก็บอยู่ในรูปแบบสตริงหรือได้รับมาจากแหล่งข้อมูลภายนอก
3. การใช้เมธอด add()
และ subtract()
กับ Temporal.Instant
, Temporal.ZonedDateTime
เป็นต้น
เมื่อคุณบวกหรือลบ Temporal.Duration
จากประเภท Temporal อื่นๆ (เช่น Temporal.Instant
หรือ Temporal.ZonedDateTime
) และจากนั้นนำค่าทั้งสองมาลบกัน จะได้ผลลัพธ์เป็น Temporal.Duration
ที่แสดงถึงความแตกต่างระหว่างจุดเวลาทั้งสอง ตัวอย่างเช่น:
const now = Temporal.Now.zonedDateTimeISO();
const later = now.add({ hours: 5 });
const duration = later.since(now);
console.log(duration.toString()); // ผลลัพธ์: PT5H
การเข้าถึงส่วนประกอบของ Duration
คุณสามารถเข้าถึงส่วนประกอบแต่ละส่วนของอ็อบเจกต์ Temporal.Duration
ได้โดยใช้คุณสมบัติต่างๆ ของมัน:
const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
console.log(duration.years); // ผลลัพธ์: 1
console.log(duration.months); // ผลลัพธ์: 2
console.log(duration.days); // ผลลัพธ์: 10
console.log(duration.hours); // ผลลัพธ์: 2
console.log(duration.minutes); // ผลลัพธ์: 30
console.log(duration.seconds); // ผลลัพธ์: 0
console.log(duration.milliseconds); // ผลลัพธ์: 0
console.log(duration.microseconds); // ผลลัพธ์: 0
console.log(duration.nanoseconds); // ผลลัพธ์: 0
การคำนวณทางคณิตศาสตร์กับ Durations
อ็อบเจกต์ Temporal.Duration
รองรับการบวกและการลบโดยใช้เมธอด add()
และ subtract()
เมธอดเหล่านี้จะคืนค่าอ็อบเจกต์ Temporal.Duration
ใหม่ซึ่งเป็นผลลัพธ์ของการดำเนินการ
const duration1 = Temporal.Duration.from("P1Y2M");
const duration2 = Temporal.Duration.from("P3M4D");
const addedDuration = duration1.add(duration2);
console.log(addedDuration.toString()); // ผลลัพธ์: P1Y5M4D
const subtractedDuration = duration1.subtract(duration2);
console.log(subtractedDuration.toString()); // ผลลัพธ์: P10M26D
คุณยังสามารถเชื่อมต่อเมธอดเหล่านี้เพื่อการคำนวณที่ซับซ้อนยิ่งขึ้นได้:
const duration = Temporal.Duration.from("P1D").add({ hours: 12 }).subtract({ minutes: 30 });
console.log(duration.toString()); // ผลลัพธ์: P1DT11H30M
เมธอด negated()
จะคืนค่าอ็อบเจกต์ Temporal.Duration
ใหม่โดยที่ส่วนประกอบทั้งหมดมีค่าเป็นลบ:
const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const negatedDuration = duration.negated();
console.log(negatedDuration.toString()); // ผลลัพธ์: -P1Y2M10DT2H30M
เมธอด abs()
จะคืนค่าอ็อบเจกต์ Temporal.Duration
ใหม่โดยที่ส่วนประกอบทั้งหมดมีค่าเป็นบวก (ค่าสัมบูรณ์):
const duration = Temporal.Duration.from("-P1Y2M10DT2H30M");
const absoluteDuration = duration.abs();
console.log(absoluteDuration.toString()); // ผลลัพธ์: P1Y2M10DT2H30M
เมธอด with()
ช่วยให้คุณสร้างอินสแตนซ์ Temporal.Duration
ใหม่โดยเปลี่ยนคุณสมบัติบางส่วนหรือทั้งหมดเป็นค่าใหม่ หากไม่ได้ระบุค่าใดในอ็อบเจกต์อาร์กิวเมนต์ ค่าดั้งเดิมของ duration จะถูกนำมาใช้แทน ตัวอย่างเช่น:
const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const newDuration = duration.with({ years: 2, days: 5 });
console.log(newDuration.toString()); // ผลลัพธ์: P2Y2M5DT2H30M
การปรับมาตรฐาน (Normalizing) Durations
บางครั้ง Durations อาจแสดงในรูปแบบที่ยังไม่ได้ปรับมาตรฐาน (เช่น P1Y12M
ซึ่งสามารถทำให้ง่ายขึ้นเป็น P2Y
) เมธอด normalized()
จะพยายามลดรูป duration ให้อยู่ในรูปแบบที่กระชับที่สุด อย่างไรก็ตาม เมธอดนี้ต้องการวันที่อ้างอิงเพื่อจัดการกับความซับซ้อนของจำนวนวันที่แตกต่างกันในแต่ละเดือน ในการปรับมาตรฐานอย่างถูกต้อง คุณจะต้องมีอินสแตนซ์ของ Temporal.PlainDate
, Temporal.ZonedDateTime
, หรือ Temporal.Instant
ตัวอย่างเช่น การปรับมาตรฐาน duration ที่เกี่ยวข้องกับเดือนและวันจำเป็นต้องมีวันที่อ้างอิง:
const duration = Temporal.Duration.from("P1M32D");
const referenceDate = Temporal.PlainDate.from("2024-01-01");
const normalizedDuration = duration.normalized({ relativeTo: referenceDate });
console.log(normalizedDuration.toString()); // ผลลัพธ์: P2M1D
ในตัวอย่างนี้ duration P1M32D
ถูกปรับมาตรฐานโดยอ้างอิงกับวันที่ 1 มกราคม 2024 ทำให้ได้ผลลัพธ์เป็น P2M1D
เนื่องจากเดือนมกราคมมี 31 วัน
หากคุณจัดการเฉพาะส่วนประกอบของเวลา (ชั่วโมง, นาที, วินาที, ฯลฯ) คุณสามารถปรับมาตรฐานได้โดยไม่ต้องใช้วันที่อ้างอิง:
const duration = Temporal.Duration.from("PT25H61M");
const normalizedDuration = duration.normalized({ relativeTo: null }); //หรือละเว้นอาร์กิวเมนต์ relativeTo
console.log(normalizedDuration.toString()); // ผลลัพธ์: P1DT2H1M
การเปรียบเทียบ Durations
คุณสามารถเปรียบเทียบ duration โดยใช้เมธอด compare()
เมธอดนี้จะคืนค่า:
- -1 หาก duration แรกสั้นกว่า duration ที่สอง
- 0 หาก duration ทั้งสองเท่ากัน
- 1 หาก duration แรกยาวกว่า duration ที่สอง
const duration1 = Temporal.Duration.from("P1Y");
const duration2 = Temporal.Duration.from("P6M");
const comparisonResult = Temporal.Duration.compare(duration1, duration2);
console.log(comparisonResult); // ผลลัพธ์: 1
ตัวอย่างการใช้งานจริง
1. การคำนวณเวลาจนกว่าจะถึงกิจกรรม
สมมติว่าคุณต้องการคำนวณเวลาที่เหลือก่อนจะถึงกิจกรรมที่กำหนด โดยใช้ Temporal.Now.zonedDateTimeISO()
เพื่อรับเวลาปัจจุบัน และลบด้วยวันที่ของกิจกรรม หากวันที่ของกิจกรรมผ่านไปแล้ว ผลลัพธ์ที่ได้จะเป็นค่าลบ
const eventDate = Temporal.ZonedDateTime.from({ timeZone: 'America/Los_Angeles', year: 2024, month: 12, day: 25, hour: 9, minute: 0, second: 0 });
const now = Temporal.Now.zonedDateTimeISO('America/Los_Angeles');
const durationUntilEvent = eventDate.since(now);
console.log(durationUntilEvent.toString()); // ผลลัพธ์: เช่น P262DT14H30M (ขึ้นอยู่กับวันและเวลาปัจจุบัน)
2. การติดตามระยะเวลาของงานในโปรเจกต์
ในการบริหารจัดการโครงการ คุณสามารถใช้ Temporal.Duration
เพื่อติดตามระยะเวลาที่ประเมินไว้หรือระยะเวลาที่ใช้จริงของงานต่างๆ
const task1EstimatedDuration = Temporal.Duration.from("PT8H"); // 8 ชั่วโมง
const task2EstimatedDuration = Temporal.Duration.from("PT16H"); // 16 ชั่วโมง
const totalEstimatedDuration = task1EstimatedDuration.add(task2EstimatedDuration);
console.log(`ระยะเวลาที่ประเมินทั้งหมด: ${totalEstimatedDuration.toString()}`); // ผลลัพธ์: ระยะเวลาที่ประเมินทั้งหมด: P1DT
3. การคำนวณอายุ
แม้ว่าการคำนวณอายุที่แม่นยำจะต้องคำนึงถึงปีอธิกสุรทินและเขตเวลา แต่ Temporal.Duration
ก็สามารถให้ค่าประมาณที่สมเหตุสมผลได้:
const birthDate = Temporal.PlainDate.from("1990-05-15");
const currentDate = Temporal.PlainDate.from("2024-01-20");
const ageDuration = currentDate.since(birthDate, { smallestUnit: 'years' });
console.log(`อายุโดยประมาณ: ${ageDuration.years} ปี`); // ผลลัพธ์: อายุโดยประมาณ: 33 ปี
4. การแสดงผล Duration ในรูปแบบที่มนุษย์อ่านได้
บ่อยครั้งที่คุณจำเป็นต้องแสดงผล duration ในรูปแบบที่มนุษย์สามารถอ่านเข้าใจได้ แม้ว่า Temporal.Duration
จะไม่มีฟังก์ชันการจัดรูปแบบในตัว แต่คุณสามารถสร้างตรรกะการจัดรูปแบบเองได้:
function formatDuration(duration) {
const parts = [];
if (duration.years) parts.push(`${duration.years} ปี`);
if (duration.months) parts.push(`${duration.months} เดือน`);
if (duration.days) parts.push(`${duration.days} วัน`);
if (duration.hours) parts.push(`${duration.hours} ชั่วโมง`);
if (duration.minutes) parts.push(`${duration.minutes} นาที`);
if (duration.seconds) parts.push(`${duration.seconds} วินาที`);
return parts.join(', ');
}
const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const formattedDuration = formatDuration(duration);
console.log(formattedDuration); // ผลลัพธ์: 1 ปี, 2 เดือน, 10 วัน, 2 ชั่วโมง, 30 นาที
การใช้งานขั้นสูงและข้อควรพิจารณา
1. การจัดการเขตเวลา (Time Zone)
เมื่อต้องจัดการกับช่วงเวลาที่ข้ามขอบเขตของเขตเวลาหรือการเปลี่ยนเวลาตามฤดูกาล (Daylight Saving Time) สิ่งสำคัญคือต้องใช้ Temporal.ZonedDateTime
เพื่อให้แน่ใจว่าการคำนวณถูกต้อง การใช้ Temporal.PlainDate
และ Temporal.PlainTime
จะหลีกเลี่ยงการแปลงเขตเวลาใดๆ
2. หน่วยที่เล็กที่สุดและการปัดเศษ
เมธอด `since()` และ `until()` มักจะยอมรับอ็อพชันเพื่อกำหนดหน่วยที่เล็กที่สุดสำหรับ duration ที่เป็นผลลัพธ์ ตัวอย่างเช่น การคำนวณเวลา *จนกว่า* จะถึงกิจกรรมและจำกัดผลลัพธ์ให้แสดงถึงแค่วัน
const eventDate = Temporal.PlainDate.from("2024-12-25");
const now = Temporal.PlainDate.from("2024-01-20");
const durationUntilEvent = now.until(eventDate, { smallestUnit: 'days' });
console.log(durationUntilEvent.toString()); //ตัวอย่างผลลัพธ์ PT340D
3. อธิกวินาที (Leap Seconds)
Temporal ไม่ได้คำนึงถึงอธิกวินาทีโดยกำเนิด หากคุณต้องการความแม่นยำสูงมาก คุณจะต้องจัดการกับอธิกวินาทีแยกต่างหาก
4. เขตเวลา IANA
Temporal API อาศัยฐานข้อมูลเขตเวลาของ IANA (Internet Assigned Numbers Authority) โปรดตรวจสอบให้แน่ใจว่าสภาพแวดล้อมของคุณมีฐานข้อมูล IANA เวอร์ชันล่าสุดเพื่อจัดการการแปลงเขตเวลาได้อย่างถูกต้อง
แนวทางปฏิบัติที่ดีที่สุด
- ใช้รูปแบบ ISO 8601 สำหรับสตริง duration: เพื่อให้แน่ใจถึงความสอดคล้องและการทำงานร่วมกัน
- เลือกประเภท Temporal ที่เหมาะสม: ใช้
Temporal.PlainDate
,Temporal.PlainTime
,Temporal.ZonedDateTime
, หรือTemporal.Instant
ขึ้นอยู่กับว่าคุณต้องการการรองรับเขตเวลาหรือไม่ - ปรับมาตรฐาน durations เมื่อจำเป็น: การปรับมาตรฐานจะช่วยให้ durations ง่ายขึ้นและเปรียบเทียบได้ง่ายขึ้น
- จัดการเขตเวลาอย่างระมัดระวัง: การแปลงเขตเวลาอาจมีความซับซ้อน ดังนั้นควรใช้
Temporal.ZonedDateTime
และตระหนักถึงการเปลี่ยนเวลาตามฤดูกาล - พิจารณาหน่วยที่เล็กที่สุด: เมื่อคำนวณ durations ให้ระบุหน่วยที่เล็กที่สุดเพื่อให้ได้ระดับความแม่นยำที่ต้องการ
- เขียน unit tests: ทดสอบโค้ดของคุณอย่างละเอียดเพื่อให้แน่ใจว่าการคำนวณ duration มีความถูกต้อง
ข้อผิดพลาดที่พบบ่อย
- การละเลยเขตเวลา: การไม่คำนึงถึงเขตเวลาอาจนำไปสู่การคำนวณ duration ที่ไม่ถูกต้อง โดยเฉพาะอย่างยิ่งเมื่อต้องจัดการกับกิจกรรมในสถานที่ต่างกัน
- การใช้อ็อบเจกต์ Date แบบดั้งเดิม: อ็อบเจกต์
Date
แบบดั้งเดิมเป็นที่รู้จักกันดีในเรื่องความแปลกและความไม่สอดคล้องกัน ควรเลือกใช้ Temporal API เพื่อการจัดการวันที่และเวลาที่น่าเชื่อถือกว่า - การไม่ปรับมาตรฐาน durations: การไม่ปรับมาตรฐาน duration อาจทำให้การเปรียบเทียบและการคำนวณซับซ้อนยิ่งขึ้น
- รูปแบบ ISO 8601 ที่ไม่ถูกต้อง: การใช้สตริง duration ISO 8601 ที่ไม่ถูกต้องอาจทำให้เกิดข้อผิดพลาดได้
กรณีการใช้งานจริงในวัฒนธรรมที่แตกต่างกัน
Temporal API มีประโยชน์อย่างยิ่งในแอปพลิเคชันระดับโลกที่ความแตกต่างของเขตเวลาและรายละเอียดทางวัฒนธรรมมีความสำคัญ นี่คือตัวอย่างบางส่วน:
- การจัดตารางกิจกรรมระดับโลก: การจัดตารางกิจกรรมข้ามเขตเวลาหลายแห่งอย่างแม่นยำ โดยคำนึงถึงการเปลี่ยนเวลาตามฤดูกาล ตัวอย่างเช่น การจัด вебинар ที่เริ่มเวลา 9:00 AM PST และแสดงเวลาเริ่มต้นที่สอดคล้องกันในเขตเวลาต่างๆ เช่น CET, JST และ AEDT
- การวางแผนการเดินทางระหว่างประเทศ: การคำนวณระยะเวลาการเดินทาง รวมถึงการหยุดพักและการเปลี่ยนแปลงเขตเวลา สิ่งนี้มีประโยชน์สำหรับการสร้างกำหนดการเดินทางและจัดการตารางเที่ยวบิน ตัวอย่างเช่น การคำนวณเวลาเดินทางทั้งหมดจากนิวยอร์กไปโตเกียว รวมถึงการหยุดพักในลอนดอนและปรับตามความแตกต่างของเขตเวลา
- อีคอมเมิร์ซระดับโลก: การแสดงเวลาจัดส่งโดยประมาณในเขตเวลาท้องถิ่นของผู้ใช้ ซึ่งต้องพิจารณาเขตเวลาต้นทาง ระยะเวลาการจัดส่ง และเขตเวลาปลายทาง ตัวอย่างเช่น สินค้าที่จัดส่งจากคลังสินค้าในเยอรมนีไปยังลูกค้าในออสเตรเลีย โดยมีเวลาจัดส่งโดยประมาณ 7 วัน ซึ่งแสดงผลตามเวลาท้องถิ่นของลูกค้า
- ธุรกรรมทางการเงินข้ามพรมแดน: การคำนวณดอกเบี้ยสะสมหรือกำหนดเวลาชำระเงินข้ามภูมิภาคต่างๆ อย่างแม่นยำ ซึ่งมักจะเกี่ยวข้องกับการพิจารณาวันทำการและวันหยุดที่แตกต่างกันในแต่ละประเทศ ตัวอย่างเช่น การคำนวณดอกเบี้ยที่เกิดขึ้นจากเงินกู้ในสิงคโปร์ โดยคำนึงถึงวันหยุดราชการของสิงคโปร์
- แอปพลิเคชันปฏิทินหลายวัฒนธรรม: การสนับสนุนระบบปฏิทินต่างๆ เช่น ปฏิทินอิสลามหรือฮีบรู และการคำนวณระยะเวลากิจกรรมและการแจ้งเตือนตามปฏิทินเหล่านี้อย่างแม่นยำ
- การจัดการโครงการระดับโลก: การติดตามระยะเวลางานของโครงการและกำหนดส่งงานของทีมที่กระจายอยู่ทั่วโลก โดยคำนึงถึงตารางการทำงานและเขตเวลาที่แตกต่างกัน
สรุป
Temporal.Duration
มอบวิธีที่แข็งแกร่งและใช้งานง่ายในการทำงานกับช่วงเวลาใน JavaScript ด้วยการทำความเข้าใจคุณสมบัติและแนวทางปฏิบัติที่ดีที่สุด คุณจะสามารถทำการคำนวณ duration ที่แม่นยำและเชื่อถือได้ในแอปพลิเคชันของคุณ การนำ Temporal API มาใช้จะนำไปสู่โค้ดที่สะอาดและบำรุงรักษาง่ายขึ้น และลดความเสี่ยงของข้อผิดพลาดที่เกี่ยวข้องกับการจัดการวันที่และเวลาแบบดั้งเดิม
เมื่อคุณเจาะลึกลงไปใน Temporal API อย่าลืมศึกษาเอกสารอย่างเป็นทางการและทดลองกับสถานการณ์ต่างๆ เพื่อให้เข้าใจความสามารถของมันอย่างถ่องแท้ ด้วยการออกแบบที่ทันสมัยและคุณสมบัติที่ครอบคลุม Temporal พร้อมที่จะปฏิวัติวิธีที่เราจัดการกับวันที่ เวลา และ duration ใน JavaScript