Skip to content

Instantly share code, notes, and snippets.

@hendisantika
Created March 26, 2022 08:22
Show Gist options
  • Save hendisantika/1f337a0643b01800a08f193b424cbb78 to your computer and use it in GitHub Desktop.
Save hendisantika/1f337a0643b01800a08f193b424cbb78 to your computer and use it in GitHub Desktop.
Count Business Day
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