# **[JAVA] 假日查詢API Calendar型別運用** ###### tags: `Java` `Restful API` `工作筆記` ## [實作目的] 專案需求,需要開一個假日查詢的API,給各個部屬於不同AP的服務call ## ## [前情提要] 後台有假日管理功能,可以手動加入補班日/颱風假/彈性放假 ![](https://i.imgur.com/rbemmln.png) #### DTO #### ```java= package gov.pcc.pwc.service.dto; public class HolidayApiDTO { private String calendarDay; private String workingDay; private String dateStart; private String dateEnd; private String date; private Integer days; private Boolean isWorkingDay; public String getCalendarDay() { return calendarDay; } public void setCalendarDay(String calendarDay) { this.calendarDay = calendarDay; } public String getWorkingDay() { return workingDay; } public void setWorkingDay(Boolean workingDay) { isWorkingDay = workingDay; } public void setWorkingDay(String workingDay) { this.workingDay = workingDay; } public String getDateStart() { return dateStart; } public void setDateStart(String dateStart) { this.dateStart = dateStart; } public String getDateEnd() { return dateEnd; } public void setDateEnd(String dateEnd) { this.dateEnd = dateEnd; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public Integer getDays() { return days; } public void setDays(Integer days) { this.days = days; } public Boolean getIsWorkingDay() { return isWorkingDay; } public void setIsWorkingDay(Boolean isWorkingDay) { this.isWorkingDay = isWorkingDay; } } ``` #### controller類別 #### ```java= package gov.pcc.pwc.pwb.rest; /** * REST controller for managing {@link HolidayApiDTO}. */ @RestController @RequestMapping("/api") public class HolidayApiResource { private final Logger log = LoggerFactory.getLogger(HolidayApiResource.class); private static final String ENTITY_NAME = "HolidayApiDAO"; @Value("${jhipster.clientApp.name}") private String applicationName; private final AdmHolidayService admHolidayService; private final AdmHolidayRepository admHolidayRepository; private final HolidayApiService holidayApiService; public HolidayApiResource(AdmHolidayService admHolidayService, AdmHolidayRepository admHolidayRepository, HolidayApiService holidayApiService) { this.admHolidayService = admHolidayService; this.admHolidayRepository = admHolidayRepository; this.holidayApiService = holidayApiService; } @PostMapping("/holiday-api/is-holiday") public boolean isHoliday(@Valid @RequestBody HolidayApiDTO holidayApiDTO) throws ParseException { log.debug("REST request to get isHoliday : date:{}", holidayApiDTO.getDate()); return holidayApiService.isHoliday(holidayApiDTO.getDate()); } @PostMapping("/holiday-api/getDate") public String getCalendarDayOrWorkingDay(@Valid @RequestBody HolidayApiDTO holidayApiDTO) throws ParseException { log.debug("REST request to get calendarDay Or workingDay : date:{}, days:{} ,isWorkingDay:{}", holidayApiDTO.getDate(), holidayApiDTO.getDays(), holidayApiDTO.getIsWorkingDay()); return holidayApiService.getCalendarDayOrWorkingDay(holidayApiDTO.getDate(), holidayApiDTO.getDays(), holidayApiDTO.getIsWorkingDay()); } @PostMapping("/holiday-api/getDays") public HolidayApiDTO getCalendarDayAndWorkingDay(@Valid @RequestBody HolidayApiDTO holidayApiDTO) throws ParseException { log.debug("REST request to get calendarDay And workingDay : dateStart:{}, dateEnd:{}", holidayApiDTO.getDateStart(), holidayApiDTO.getDateEnd()); return holidayApiService.getCalendarDayAndWorkingDay(holidayApiDTO.getDateStart(), holidayApiDTO.getDateEnd()); } } ``` #### service類別 #### ```java= package gov.pcc.pwc.service; @Service public class HolidayApiService { private final Logger log = LoggerFactory.getLogger(HolidayApiService.class); private final AdmHolidayRepository admHolidayRepository; public HolidayApiService(AdmHolidayRepository admHolidayRepository) { this.admHolidayRepository = admHolidayRepository; } /** * 判斷是否為假日: * 輸入111/02/28,於ADM_HOLIDAY找到二二八,回傳true * 輸入111/03/05,為星期六,回傳true * 輸入111/01/22,為星期六,但在ADM_HOLIDAY找到圍捕般日,回傳false * @param date * @return boolean * @throws ParseException */ public Boolean isHoliday(String date) throws ParseException { String addDate = transferMinguoDateToADDate(date); Calendar calendarDate = transferADDateStringToCalendar(addDate); LocalDate localDate = LocalDate.ofInstant(calendarDate.toInstant(), ZoneId.systemDefault()); //查詢AMD_HOLIDAY判斷是否是節日、補班日 if (!admHolidayRepository.existsByHolidayDate(localDate)) { //如果不是,繼續判斷是否為星期六、星期日 switch (calendarDate.get(Calendar.DAY_OF_WEEK)) { case Calendar.SATURDAY: case Calendar.SUNDAY: return true; default: return false; } } else { return true; } } /** * 回傳以當日日期開始的工作日or日曆日 * 輸入111/03/01、5、false,回傳111/03/05 * 輸入111/03/01、5、true,回傳111/03/07 * @param date * @param days * @param isWorkingDay * @return * @throws ParseException */ public String getCalendarDayOrWorkingDay(String date, Integer days, Boolean isWorkingDay) throws ParseException { String adDate = transferMinguoDateToADDate(date); Calendar calendarDate = transferADDateStringToCalendar(adDate); if (isWorkingDay) { try { if (isHoliday(transferADDateToMinguoDate(transferCalendarToADDateString(calendarDate)))) { days++; } for (int i = 0; i < days-1 ; i++) { calendarDate.add(Calendar.DAY_OF_MONTH, 1); if(isHoliday(transferADDateToMinguoDate(transferCalendarToADDateString(calendarDate)))){ i--; } } return transferADDateToMinguoDate(transferCalendarToADDateString(calendarDate)); } catch (Exception e) { log.error(e.getMessage()); } } else { calendarDate.add(Calendar.DAY_OF_MONTH, days-1); String adDateString = transferCalendarToADDateString(calendarDate); String minguoDateString = transferADDateToMinguoDate(adDateString); return minguoDateString; } return null; } public HolidayApiDTO getCalendarDayAndWorkingDay(String dateStart, String dateEnd) throws ParseException { String adDateStart = transferMinguoDateToADDate(dateStart); Calendar calendarDateStart = transferADDateStringToCalendar(adDateStart); long timeStart = calendarDateStart.getTimeInMillis(); String adDateEnd = transferMinguoDateToADDate(dateEnd); Calendar calendarDateEnd = transferADDateStringToCalendar(adDateEnd); long timeEnd = calendarDateEnd.getTimeInMillis(); int betweenDays = Integer.parseInt(String.valueOf((timeEnd - timeStart) / (1000 * 60 * 60 * 24))); //日曆日 String calendarDays = String.valueOf(betweenDays + 1); //工作日 int workingDaysCount = 0; if (!isHoliday(transferADDateToMinguoDate(transferCalendarToADDateString(calendarDateStart)))) { workingDaysCount++; } for (int i = 0; i < betweenDays; i++) { calendarDateStart.add(Calendar.DAY_OF_MONTH, 1); workingDaysCount++; if (isHoliday(transferADDateToMinguoDate(transferCalendarToADDateString(calendarDateStart)))) { workingDaysCount--; } } String workingDays = String.valueOf(workingDaysCount); HolidayApiDTO holidayApiDTO = new HolidayApiDTO(); holidayApiDTO.setCalendarDay(calendarDays); holidayApiDTO.setWorkingDay(workingDays); return holidayApiDTO; } ``` #### 日期Util #### ```java= /** * Transfer AD date to minguo date. * 西元年 yyyyMMdd 轉 民國年 yyy/MM/dd * * @param dateString the String dateString * @return the string */ public static String transferADDateToMinguoDate(String dateString) { LocalDate localDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyyMMdd")); return MinguoDate.from(localDate).format(DateTimeFormatter.ofPattern("yyy/MM/dd")); } /** * Transfer minguo date to AD date. * 民國年 yyy/MM/dd 轉 西元年 yyyyMMdd * * @param dateString the String dateString * @return the string */ public static String transferMinguoDateToADDate(String dateString) { Chronology chrono = MinguoChronology.INSTANCE; DateTimeFormatter df = new DateTimeFormatterBuilder().parseLenient() .appendPattern("yyy/MM/dd") .toFormatter() .withChronology(chrono) .withDecimalStyle(DecimalStyle.of(Locale.getDefault())); ChronoLocalDate chDate = chrono.date(df.parse(dateString)); return LocalDate.from(chDate).format(DateTimeFormatter.ofPattern("yyyyMMdd")); } public static Calendar transferADDateStringToCalendar(String dateString) throws ParseException { Calendar cal = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.TAIWAN); cal.setTime(sdf.parse(dateString)); return cal; } public static String transferCalendarToADDateString(Calendar calendar) { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.TAIWAN); return sdf.format(calendar.getTime()); } } ```