การบวกลบเวลาใน Java8 ใช้คลาสที่ชื่อว่า java.time.Duration และ java.time.Instant ซึ่งแตกต่างจาก Java2 ที่ใช้ java.util.Calendar รูปแบบการเขียนคาบเวลาเป็นไปตาม ISO8601 https://en.wikipedia.org/wiki/ISO_8601
1. รูปแบบคาบเวลาของ ISO8601
โดยมีรูปแบบคาบเวลาเป็น P(n)Y(n)M(n)DT(n)H(n)M(n)S โดยมีคำอธิบายดังนี้
- P บอกให้รู้ว่าหลังจากตัว P นี้คือคาบเวลา ใช้นำหน้าให้รู้ว่าคือข้อมูลคาบเวลาเท่านั้น
- Y บอกให้รู้ว่า (n)Y คือ จำนวน n ปี
- M บอกให้รู้ว่า (n)M คือ จำนวน n เดือน
- W บอกให้รู้ว่า (n)W คือ จำนวน n สัปดาห์
- D บอกให้รู้ว่า (n)D คือ จำนวน n วัน
- T เป็นแค่ตัวอักษร T ที่บอกให้รู้ว่าหลังจากตัวอักษรนี้เป็นคาบเวลาแบบ ชม. นาที และ วินาที จะขึ้นต้นด้วย T ไม่ได้ต้องมี P นำหน้ามาก่อนเสมอ
- H บอกให้รู้ว่า (n)H คือ จำนวน n ชม.
- M บอกให้รู้ว่า (n)M คือ จำนวน n นาที
- S บอกให้รู้ว่า (n)S คือ จำนวนวินาที สามารถเขียนเป็น ทศนิยมได้เช่น 5.100200300 คือ 5 วินาที กับ 100 มิลิวินาที และ 200 ไมโครวินาที และ 300 นาโนวินาที เป็นต้น
จะเห็นว่าถ้าเขียน P1Y จะหมายถึง คาบเวลา 1 ปี แต่ถ้าเขียนเป็น P1Y1M1DT1H1M1.1S แยกส่วนออกมาเป็นดังนี้ P คือบอกให้รู้ว่าเป็น period คือคาบเวลา 1Y คือ 1 ปี และ 1M คือ 1 เดือน และ 1D คือ 1 เดือน และ T บอกให้รู้ว่านี่คือตัวบอกเวลาหลังจาก T จะเป็น ชม. นาที ในที่นี้ 1H คือ 1 ชม. และ 1M คือ 1 นาที (สังเกตว่า 1M ที่อยู่หลัง P คือ 1 เดือน แต่ถ้า 1M อยู่หลัง T คือ 1 นาที) และ 1.1S คือ 1 วินาที กับ 0.1 วินาทีก็คือ 100 มิลิวินาที
2. การคำนวณ
การคำนวณใช้วิธีการเรียกใช้เมธอด parse จากคลาส java.time.Duration และนำไปบวกหรือลบกับเวลาด้วยเมธอด Instant.plus(…) หรือ Instant.mius(…) ตัวอย่างโค้ดที่ใช้ในการบวกเวลาเพิ่มเป็นเช่นนี้
public class Utils {
public static Date addDuration(Date original, String period) {
Instant inst = original.toInstant();
java.time.Duration du = java.time.Duration.parse(period);
Date next = Date.from(inst.plus(du));
return next;
}
public static Date minusDuration(Date original, String period) {
Instant inst = original.toInstant();
java.time.Duration du = java.time.Duration.parse(period);
Date next = Date.from(inst.minus(du));
return next;
}
}
ซึ่งหากต้องการบวกหรือลบเวลาสามารถเรียกใช้ addDuration() ได้ดังนี้
Date now = new Date();
Date next = Utils.addDuration(now, "P1Y15DT6H");
ค่า next จะเป็นวันเวลาจากปัจจุบันนับไปอีก 1 ปี 5 วัน 6 ชม. เป็นต้น
3. ข้อจำกัด
ใน Java8 ใช้งานได้แค่ PnDTnHnMn.nS เท่านั้น ไม่ถึงระดับเดือนและปี ดังนั้น ถ้าใช้รูปแบบเป็น P3Y หรือ P60M จะเกิดข้อผิดพลาด java.time.format.DateTimeParseException: Text cannot be parsed to a Duration แต่ถ้าใช้แค่ระดับ D (Day) จะไม่มีปัญหา เช่น P30D ไม่มีปัญหา
