Created
March 26, 2022 08:22
-
-
Save hendisantika/1f337a0643b01800a08f193b424cbb78 to your computer and use it in GitHub Desktop.
Count Business Day
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package id.co.tirta.backend.command.impl; | |
import id.co.tirta.backend.repository.BranchHolidayRepository; | |
import id.co.tirta.backend.repository.BranchRepository; | |
import id.co.tirta.backend.repository.BranchWorkingHourRepository; | |
import lombok.extern.slf4j.Slf4j; | |
import org.junit.jupiter.api.AfterEach; | |
import org.junit.jupiter.api.BeforeEach; | |
import org.junit.jupiter.api.DisplayName; | |
import org.junit.jupiter.api.Test; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.test.context.SpringBootTest; | |
import java.time.DayOfWeek; | |
import java.time.Instant; | |
import java.time.LocalDate; | |
import java.time.MonthDay; | |
import java.time.ZoneId; | |
import java.time.temporal.ChronoUnit; | |
import java.util.ArrayList; | |
import java.util.Date; | |
import java.util.List; | |
import java.util.Set; | |
import java.util.stream.Collectors; | |
import static java.time.DayOfWeek.FRIDAY; | |
import static java.time.DayOfWeek.MONDAY; | |
import static java.time.DayOfWeek.SATURDAY; | |
import static java.time.DayOfWeek.SUNDAY; | |
import static java.time.DayOfWeek.THURSDAY; | |
import static java.time.DayOfWeek.TUESDAY; | |
import static java.time.DayOfWeek.WEDNESDAY; | |
import static org.junit.jupiter.api.Assertions.assertEquals; | |
import static org.junit.jupiter.api.Assertions.assertNotNull; | |
/** | |
* Created by IntelliJ IDEA. | |
* Project : tirta-backend | |
* User: hendisantika | |
* Email: [email protected] | |
* Telegram : @hendisantika34 | |
* Date: 22/03/22 | |
* Time: 14.08 | |
*/ | |
@Slf4j | |
@SpringBootTest | |
class GetBranchWorkingTimeCommandImplTest { | |
final static Set<LocalDate> holidays = Set.of( | |
LocalDate.of(2022, 4, 15), | |
LocalDate.of(2022, 4, 16), | |
LocalDate.of(2022, 4, 30), | |
LocalDate.of(2022, 5, 1), | |
LocalDate.of(2022, 5, 2), | |
LocalDate.of(2022, 5, 3), | |
LocalDate.of(2022, 5, 16), | |
LocalDate.of(2022, 5, 26) | |
); | |
private final int RANGE_DAYS = 14; | |
@Autowired | |
private BranchRepository branchRepository; | |
@Autowired | |
private BranchHolidayRepository branchHolidayRepository; | |
@Autowired | |
private BranchWorkingHourRepository branchWorkingHourRepository; | |
@BeforeEach | |
void setUp() { | |
} | |
@AfterEach | |
void tearDown() { | |
} | |
@Test | |
void countBusinessDaysBetweenTest() { | |
LocalDate today = LocalDate.now(); | |
log.info("Current date: " + today); | |
//add 2 week to the current date | |
LocalDate next2Week = today.plus(2, ChronoUnit.WEEKS); | |
log.info("next2Week: " + next2Week); | |
//Next 2 week from current date without public holiday | |
LocalDate result = next2Week; | |
log.info("Next 2 week from current date without public holiday: " + next2Week); | |
Long date = System.currentTimeMillis() + 14 * 24 * 3600 * 1000; | |
Date newDate = new Date(date); | |
log.info("newDate Long: " + date); | |
log.info("newDate: " + newDate); | |
log.info("================================================================="); | |
LocalDate specificDate = LocalDate.of(2022, 4, 14); | |
log.info("SpecificDate date: " + specificDate); | |
MonthDay md = MonthDay.from(specificDate); | |
log.info("MonthDay: " + md); | |
//add 2 week to the current date | |
LocalDate next2Week2 = today.plus(2, ChronoUnit.WEEKS); | |
log.info("next2Week: " + next2Week); | |
} | |
@Test | |
void countBusinessDaysBetweenTest2() { | |
LocalDate startDate = LocalDate.of(2022, 4, 14); | |
LocalDate endDate = startDate.plusWeeks(2); | |
final Set<LocalDate> holidays = Set.of( | |
LocalDate.of(2022, 4, 15), | |
LocalDate.of(2022, 4, 16), | |
LocalDate.of(2022, 4, 30) | |
); | |
List<Long> holidaysMS = holidays.stream() | |
.map(date -> date.atStartOfDay(ZoneId.systemDefault()).toEpochSecond() * 1000) | |
.collect(Collectors.toList()); | |
final Set<DayOfWeek> businessDays = Set.of( | |
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY | |
); | |
List<LocalDate> allDates = startDate.datesUntil(endDate) | |
.collect(Collectors.toList()); | |
List<Long> dateMS = | |
allDates.stream().map(localDate -> localDate.atStartOfDay(ZoneId.systemDefault()).toEpochSecond() * 1000) | |
.collect(Collectors.toList()); | |
List<Long> ms = new ArrayList<>(dateMS); | |
ms.retainAll(holidaysMS); | |
long count = ms.stream().count(); | |
LocalDate tempDate = endDate.plusDays(count); | |
List<LocalDate> allDates2 = endDate.datesUntil(tempDate) | |
.collect(Collectors.toList()); | |
List<Long> dateMS2 = | |
allDates.stream().map(localDate -> localDate.atStartOfDay(ZoneId.systemDefault()).toEpochSecond() * 1000) | |
.collect(Collectors.toList()); | |
List<Long> ms2 = new ArrayList<>(dateMS2); | |
ms2.retainAll(holidaysMS); | |
long count2 = ms.stream().count(); | |
allDates.remove(startDate); | |
log.info("===== Start Date ===== " + startDate); | |
log.info("===== allDates ===== "); | |
// allDates.forEach(System.out::println); | |
log.info("===== endDate ===== " + endDate); | |
log.info("===== Holiday MS ===== " + endDate); | |
// holidaysMS.forEach(System.out::println); | |
log.info("===== Date MS ===== " + endDate); | |
// dateMS.forEach(System.out::println); | |
log.info("===== Match Count ===== " + count); | |
log.info("===== newDate ===== " + tempDate); | |
} | |
@Test | |
@DisplayName("Count Business Day with no holiday on the range days Case") | |
void countBusinessDaysWithNoHolidayTest() { | |
LocalDate startDate = LocalDate.of(2022, 3, 1); | |
List<LocalDate> yearHolidays = new ArrayList<>(holidays); | |
List<LocalDate> localDateList = countWorkingDays2(startDate, RANGE_DAYS, yearHolidays); | |
countWorkingDays2(startDate, 14, yearHolidays).forEach(System.out::println); | |
List<Long> workingDays = | |
localDateList.stream().map(localDate -> localDate.atStartOfDay(ZoneId.systemDefault()).toEpochSecond() * 1000) | |
.collect(Collectors.toList()); | |
workingDays.forEach(System.out::println); | |
log.info("===== convertLocalDateToLong ===== "); | |
List<Long> longs = convertLocalDateToLong(yearHolidays); | |
longs.forEach(System.out::println); | |
log.info("===== convertLongToLocalDate ===== "); | |
List<LocalDate> dates = convertLongToLocalDate(longs); | |
dates.forEach(System.out::println); | |
assertNotNull(localDateList); | |
assertEquals(LocalDate.of(2022, 3, 15), localDateList.get(localDateList.size() - 1)); | |
} | |
@Test | |
@DisplayName("Count Business Day with holiday on the range days Case") | |
void countBusinessDaysWithHolidaysTest() { | |
LocalDate startDate = LocalDate.of(2022, 4, 14); | |
List<LocalDate> yearHolidays = new ArrayList<>(holidays); | |
List<LocalDate> localDateList = countWorkingDays2(startDate, RANGE_DAYS, yearHolidays); | |
countWorkingDays2(startDate, 14, yearHolidays).forEach(System.out::println); | |
List<Long> workingDays = | |
localDateList.stream().map(localDate -> localDate.atStartOfDay(ZoneId.systemDefault()).toEpochSecond() * 1000) | |
.collect(Collectors.toList()); | |
workingDays.forEach(System.out::println); | |
log.info("===== convertLocalDateToLong ===== "); | |
List<Long> longs = convertLocalDateToLong(yearHolidays); | |
longs.forEach(System.out::println); | |
log.info("===== convertLongToLocalDate ===== "); | |
List<LocalDate> dates = convertLongToLocalDate(longs); | |
dates.forEach(System.out::println); | |
assertNotNull(localDateList); | |
assertEquals(LocalDate.of(2022, 5, 4), localDateList.get(localDateList.size() - 1)); | |
} | |
private List<LocalDate> countWorkingDays2(LocalDate startDate, int rangeDays, List<LocalDate> yearHolidays) { | |
log.info("countWorkingDays ..."); | |
List<LocalDate> periodDates = new ArrayList<>(); | |
LocalDate workingDay = startDate.plusDays(0); | |
for (int day = 1; day <= rangeDays; day++) { | |
workingDay = workingDay.plusDays(1); | |
periodDates.add(workingDay); | |
checkHolidayOnLastPeriod(yearHolidays, periodDates); | |
workingDay = periodDates.get(periodDates.size() - 1); | |
} | |
return periodDates; | |
} | |
private List<LocalDate> countWorkingDays(LocalDate startDate, int rangeDays, List<LocalDate> yearHolidays) { | |
log.info("countWorkingDays ..."); | |
startDate = startDate.plusDays(1); | |
LocalDate endDate = startDate.plusDays(rangeDays); | |
List<LocalDate> periodDates = startDate.datesUntil(endDate) | |
.collect(Collectors.toList()); | |
List<LocalDate> periodHolidays = new ArrayList<>(periodDates); | |
periodHolidays.retainAll(yearHolidays); | |
int plusDay = periodHolidays.size(); | |
for (int extraDays = 0; extraDays < plusDay; extraDays++) { | |
periodDates.add(endDate.plusDays(extraDays)); | |
} | |
checkHolidayOnLastPeriod(yearHolidays, periodDates); | |
periodDates.removeAll(yearHolidays); | |
return periodDates; | |
} | |
private void checkHolidayOnLastPeriod(List<LocalDate> yearHolidays, List<LocalDate> periodDates) { | |
LocalDate lastDate = periodDates.get(periodDates.size() - 1); | |
if (yearHolidays.contains(lastDate)) { | |
periodDates.remove(lastDate); | |
periodDates.add(lastDate.plusDays(1)); | |
} | |
lastDate = periodDates.get(periodDates.size() - 1); | |
if (yearHolidays.contains(lastDate)) { | |
checkHolidayOnLastPeriod(yearHolidays, periodDates); | |
} | |
} | |
public List<Long> convertLocalDateToLong(List<LocalDate> localDateList) { | |
return localDateList.stream().map(localDate -> localDate.atStartOfDay(ZoneId.systemDefault()).toEpochSecond() * 1000) | |
.collect(Collectors.toList()); | |
} | |
public List<LocalDate> convertLongToLocalDate(List<Long> longList) { | |
return longList.stream().map(l -> { | |
return Instant.ofEpochMilli(l).atZone(ZoneId.systemDefault()).toLocalDate(); | |
}).collect(Collectors.toList()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment