μλ°μμ μ°λμ μ λ€λ£¨κΈ°
μλ°μμ λ μ§ λ° μκ°μ λ€λ£¨λ κ²½μ° Instant, OffsetDateTime λλ ZonedDateTimeκ³Ό κ°μ΄ νμμ‘΄ μ€νμ μ΄ ν¬ν¨λλ κ²μ νμ©νλ κ²μ΄ μ’μ΅λλ€. κ·Έλ°λ°, κ°λμ μ°,μ,μΌ ν΅κ³μ κ°μ μꡬμ¬νμΌλ‘ μΈν΄ YearMonth λλ LocalDateλ₯Ό μ¬μ©ν΄μΌνλ κ²½μ°κ° μμ΅λλ€. μλ₯Ό λ€μ΄, 2025λ 2μμ λν ν΅κ³λ₯Ό μν΄μ 2025λ 2μμ 첫λ²μ§Έ λ μ§μ λ§μ§λ§ λ μ§μ λ²μλ₯Ό μμμΌ ν©λλ€. 첫λ²μ§Έ λ μ§λ λͺ ννλ―λ‘ κ°λ¨νμ§λ§ λ§μ§λ§ λ μ§λ μλ§λ€ λ€λ₯Έλ° νΉνλ, 2μμ λ§μ§λ§ λ μ§λ 28μΌμ΄κΈ°λ ν©λλ€.
μλ°μμ μ° λλ μμ λν λ§μ§λ§ λ μ§λ₯Ό κ°μ Έμ€λ λ°©λ²μ μ¬λ¬κ°μ§κ° μμ΅λλ€. Year λλ YearMonthμ lengthXXX ν¨μλ₯Ό ν΅ν΄ λ§μ§λ§ λ μ§λ₯Ό κ°μ Έμμ μ§μ ν μ μμΌλ©° YearMonth μλ λ μ§κ΄μ μΈ atEndOfMonth ν¨μλ₯Ό ν¬ν¨νκ³ μμ΅λλ€. λν, TemporalAdjustersλ₯Ό ν΅ν΄ λ μ§λ₯Ό λ³ννλ κ²λ κ°λ₯νμ£ .
μ λμ μ μν 첫λ²μ§Έ λ μ§μ λ§μ§λ§ λ μ§ κ°μ Έμ€κΈ°
YearMonth yearMonth = YearMonth.of(2025, 2);
LocalDate startDate = yearMonth.atDay(1);
LocalDate endDate = yearMonth.atEndOfMonth();
λ§μ§λ§ λ μ§λ₯Ό ꡬνκΈ° μν΄μ YearMonth.lengthOfMonth λλ TemporalAdjusters.lastDayOfMonth ν¨μλ₯Ό μ΄μ©ν μλ μμ΅λλ€.
μ° λμ μ μν 첫λ²μ§Έ λ μ§μ λ§μ§λ§ λ μ§ κ°μ Έμ€κΈ°
Year year = Year.of(2025);
LocalDate firstDate = year.atDay(1);
LocalDate lastDate = year.atDay(year.length());
λ§μ§λ§ λ μ§λ₯Ό ꡬνκΈ° μν΄μ TemporalAdjusters.lastDayOfYear ν¨μλ₯Ό μ΄μ©ν μλ μμ΅λλ€.
μ€νλ§ μ»¨νΈλ‘€λ¬ νΈλ€λ¬ ν¨μ νλΌλ―Έν°
@RestController
@RequestMapping("/api")
public class SampleApi {
private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy.MM.dd");
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Month.class, new MonthPropertyEditor());
}
@GetMapping("/stat/{year:[0-9]{4}}")
public ResponseEntity<?> getStatOfYear(@PathVariable("year") Year year) {
LocalDate fromDate = year.atDay(1);
LocalDate toDate = year.atDay(year.length());
return ResponseEntity.ok(Map.of(
"from", fromDate.format(DATE_FORMAT),
"to", toDate.format(DATE_FORMAT)));
}
@GetMapping("/stat/{yearMonth:[0-9]{4}\\-[0-9]{2}}")
public ResponseEntity<?> getStatOfYearMonth(
@DateTimeFormat(pattern = "yyyy-MM")
@PathVariable("yearMonth") YearMonth yearMonth) {
LocalDate fromDate = yearMonth.atDay(1);
LocalDate toDate = yearMonth.atEndOfMonth();
return ResponseEntity.ok(Map.of(
"from", fromDate.format(DATE_FORMAT),
"to", toDate.format(DATE_FORMAT)));
}
@GetMapping("/stat/{year}/{month}")
public ResponseEntity<?> getStatOfYearMonth(@PathVariable("year") Year year,
@PathVariable("month") Month month) {
return getStatOfYearMonth(YearMonth.of(year.getValue(), month));
}
private static class MonthPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (text.matches("\\d+")) {
setValue(Month.of(Integer.parseInt(text)));
return;
}
setValue(Month.valueOf(text.toUpperCase()));
}
}
}
μ€νλ§ μ»¨νΈλ‘€λ¬μ νΈλ€λ¬ ν¨μλ₯Ό μμ±ν λ μ°λμ μμ λν νλΌλ―Έν°λ₯Ό int κ° μλ Yearμ YearMonthλ₯Ό κ·Έλλ‘ νμ©ν μ μλλ‘ λ°μΈλ©μ΄ κ°λ₯ν©λλ€. λ¨, Monthμ κ²½μ° ν΄λμ€κ° μλ Enum μ΄κΈ° λλ¬Έμ λ³λμ PropertyEditorλ₯Ό μμ±νμ¬ WebDataBinderμ λ±λ‘ν΄μΌν©λλ€. νλΌλ―Έν° λ°μΈλ©μΌλ‘ λ³ννλ κ³Όμ μ 곡ν΅μ μΌλ‘ μ μ©νλ―λ‘ λ ν¨μ¨μ μ΄κ³ μ§κ΄μ μΈ μ½λλ₯Ό μμ±ν μ μμμ μμμ΅λλ€.