นากกายวางแถบเวลาระหว่างนาฬิกาทรายกับไม้กั้นเพื่อตรวจว่าระยะเวลาไม่ยาวเกินขอบเขต

Java Duration.parse: รับ timeout แบบมีหน่วยโดยไม่เดาว่าเลขคืออะไร

พี่โชว์Engineering

config อย่าง timeout: 30 ชวนให้ถามว่า 30 วินาที นาที หรือมิลลิวินาที Duration.parse รับข้อความ ISO-8601 ที่มีหน่วยในตัว เช่น PT30S และคืนชนิดเวลาที่นำไปตรวจขอบเขตต่อได้ครับ

WHY: ใส่หน่วยบนกล่องก่อนส่ง

ตัวเลขเปล่าเหมือนพัสดุที่เขียนน้ำหนักแต่ไม่บอกหน่วย คนละทีมเดาไม่เหมือนกันและ bug อาจมากกว่าพันเท่า Duration ทำให้หน่วยเป็นส่วนหนึ่งของค่า ลดการส่ง long ที่ความหมายซ่อนอยู่ในชื่อแปร

import java.time.Duration;
import java.time.format.DateTimeParseException;

public class Main {
    static Duration parseTimeout(String raw) {
        Duration value = Duration.parse(raw);
        if (value.isNegative() || value.isZero() || value.compareTo(Duration.ofMinutes(5)) > 0) {
            throw new IllegalArgumentException("timeout must be within (0, 5m]");
        }
        return value;
    }

    public static void main(String[] args) {
        assert parseTimeout("PT30S").equals(Duration.ofSeconds(30));
        assert parseTimeout("PT1M30S").equals(Duration.ofSeconds(90));

        try {
            parseTimeout("30 seconds");
            throw new AssertionError("invalid syntax must fail");
        } catch (DateTimeParseException expected) {
            // expected
        }

        try {
            parseTimeout("PT10M");
            throw new AssertionError("over-budget timeout must fail");
        } catch (IllegalArgumentException expected) {
            // expected
        }
        System.out.println("duration parsing verified");
    }
}

HOW: parse syntax แล้วต้อง validate policy ต่อ

การ parse สำเร็จเพียงบอกว่ารูปแบบถูก ไม่ได้บอกว่าค่าเหมาะกับระบบ Duration รองรับค่าติดลบ ศูนย์ และช่วงใหญ่มาก เราจึงตรวจ budget หลัง parse อีกชั้น เมื่อนำไปใช้กับ API ที่รับ millisecond ให้ใช้ toMillis() หลังจำกัดช่วง เพื่อหลีกเลี่ยง overflow หรือ timeout ที่ยาวเกินจริง

ISO-8601 duration ไม่เท่ากับเวลาปฏิทิน “หนึ่งเดือน” เพราะจำนวนวันเปลี่ยนไป หาก config เป็นรอบบิลหรือวันนัด ใช้ Period/วันที่ตาม timezone แทน ส่วน timeout และ latency budget เป็นเวลาต่อเนื่องจึงเหมาะกับ Duration

Recap

  • ใช้ข้อความที่มีหน่วย เช่น PT30S
  • ตรวจค่าบวกและเพดานหลัง parse
  • แปลงเป็น millisecond หลังจำกัดช่วง
  • ใช้ Period สำหรับเดือน/ปีเชิงปฏิทิน
  • ทดสอบ syntax ผิด ศูนย์ ค่าติดลบ และเกิน budget