Java Instant.truncatedTo: จัด event ลง bucket นาทีโดยไม่ปัดผิดเขตเวลา
dashboard ที่นับ event ต่อนาทีต้องตัดเวลา 10:02:59 ลงช่อง 10:02 ถ้าปัดเป็น 10:03 กราฟจะคลาดและ alert อาจยิงผิดช่วงครับ Instant.truncatedTo คืนสำเนาเวลาที่ตั้งหน่วยย่อยกว่าให้เป็นศูนย์ เหมือนวางลูกปัดทุกเม็ดที่เกิดในนาทีเดียวลงกล่องเดียวกัน โดยไม่แก้ event ต้นฉบับ
Instant คือจุดเวลาบน timeline แบบ UTC จึงเหมาะเป็น key สำหรับ bucket นาทีหรือชั่วโมงทั่วระบบ หากต้องสรุป วันที่ตามกรุงเทพฯ ควรแปลงด้วย ZoneId ก่อนหา LocalDate ไม่ใช่ truncate Instant เป็นวันแล้วเรียกว่าวันไทย เพราะขอบวัน UTC ต่างจากขอบวันท้องถิ่น
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
public class Main {
public static void main(String[] args) {
Instant event = Instant.parse("2026-09-20T17:02:59.999Z");
Instant minute = event.truncatedTo(ChronoUnit.MINUTES);
assert minute.equals(Instant.parse("2026-09-20T17:02:00Z"));
assert event.equals(Instant.parse("2026-09-20T17:02:59.999Z"));
LocalDate bangkokDay = event.atZone(ZoneId.of("Asia/Bangkok")).toLocalDate();
assert bangkokDay.equals(LocalDate.of(2026, 9, 21));
assert !bangkokDay.equals(event.atZone(ZoneId.of("UTC")).toLocalDate());
System.out.println("Instant bucket tests passed");
}
}
เลือก bucket ตามคำถามธุรกิจ
ถ้าถาม “มี request กี่ครั้งในนาทีเดียวกันทั่วโลก” ให้ key เป็น Instant.truncatedTo(MINUTES) แล้วแสดง label ใน zone ที่ผู้ใช้เลือกภายหลัง ถ้าถาม “ยอดขายของวันจันทร์ในไทย” ต้อง key เป็น LocalDate หลังแปลง Asia/Bangkok วิธีนี้ช่วยไม่ให้รายการหลังเที่ยงคืนไทยหล่นไปอยู่วันก่อนในรายงาน
การ truncate ไม่ใช่การปัดใกล้สุด; ค่า 59.999 วินาทีก็ยังลงนาทีก่อน และการเปลี่ยนเป็นหน่วยวันใน Instant ยึด UTC ไม่ได้รู้ปฏิทินของเขตเวลาใด ถ้ามี daylight saving ใน zone เป้าหมาย ยิ่งต้องใช้ชนิดเวลาแบบ zone-aware สำหรับวันท้องถิ่นครับ
Recap
- เก็บ event จริงเป็น
Instantแล้ว truncate สำหรับ bucket สั้น - ใช้
ZoneIdก่อนหาLocalDateของผู้ใช้ - ทดสอบค่าชิดขอบนาทีและขอบวัน
- ระบุว่า bucket ที่รายงานเป็น UTC หรือท้องถิ่น