Java Duration parts: แยกวัน ชั่วโมง นาที วินาทีโดยไม่คำนวณ modulo เอง
เมื่อต้องแสดง duration เป็นวัน ชั่วโมง นาที และวินาที การหารกับ modulo เองดูง่ายแต่พลาดเรื่องค่าติดลบและความหมายของ “ผลรวม” กับ “ส่วนย่อย” ได้ Java มีเมธอด toDaysPart, toHoursPart, toMinutesPart, toSecondsPart และ toMillisPart ให้ประกอบผลลัพธ์อย่างชัดเจนครับ
WHY: total กับ part ตอบคนละคำถาม
นึกถึงเงิน 2,750 บาท: ถ้าถาม “ทั้งหมดกี่ร้อย” กับ “หลังแยกพันแล้วเหลือกี่ร้อย” คำตอบคนละแบบ Duration.toHours คืนชั่วโมงรวมทั้งหมด ส่วน toHoursPart คืนส่วนชั่วโมงหลังหักวันออกแล้ว เมธอด part ช่วยให้โค้ดแสดงผลสอดคล้องกับภาษามนุษย์
import java.time.Duration;
public class Main {
static String compact(Duration duration) {
return duration.toDaysPart() + "d "
+ duration.toHoursPart() + "h "
+ duration.toMinutesPart() + "m "
+ duration.toSecondsPart() + "s";
}
public static void main(String[] args) {
Duration value = Duration.ofDays(2)
.plusHours(3)
.plusMinutes(4)
.plusSeconds(5);
assert value.toHours() == 51;
assert value.toHoursPart() == 3;
assert value.toMinutesPart() == 4;
assert compact(value).equals("2d 3h 4m 5s");
}
}
Duration เป็นช่วงเวลาบนเส้นวินาทีและนาโนวินาที ไม่ใช่ปฏิทิน “หนึ่งเดือน” หรือ “หนึ่งวันทำการ” ถ้าต้องบวกเดือน/ปีตาม calendar ใช้ Period หรือ ZonedDateTime ตาม domain เพราะวันที่มี daylight-saving transition อาจไม่ได้ยาว 24 ชั่วโมงทุกแห่ง
ระวังค่าน้อยกว่าศูนย์
part ของ duration ติดลบใช้เครื่องหมายตามองค์ประกอบของค่า ไม่ควรนำไปต่อข้อความโดยไม่ทดสอบรูปแบบที่ต้องการ หาก UI ต้องแสดงเครื่องหมายเดียวด้านหน้า ให้ normalize absolute duration แล้วเติมเครื่องหมายแยก และระวังกรณีค่าต่ำสุดที่ negate อาจ overflow ตามข้อจำกัด
สำหรับ machine format ใช้ Duration.toString ซึ่งเป็น ISO-8601 ดีกว่ารูปแบบแต่งเอง ส่วน compact formatter นี้เหมาะกับ UI ภายในที่มี contract ชัด ไม่ควรใช้เป็นข้อมูลแลกเปลี่ยน
Recap
- ใช้ toHours สำหรับยอดรวม ใช้ toHoursPart สำหรับส่วนย่อย
- ใช้ Period เมื่อต้องคิดเดือนหรือปีตามปฏิทิน
- ทดสอบ duration ติดลบก่อนแสดงใน UI
- ใช้ ISO-8601 สำหรับ machine-to-machine