[Java] Date between 여부 반환 : DateUtil.isStdDateBetween()

Jinbro·2023년 1월 21일
0

Java

목록 보기
5/7

배경설명

  • 기준 Date시작 Date종료 Date 사이에 있는지 판단 필요!
    • ex)
      • 이벤트진행가능여부 (이벤트시작일시~이벤트종료일시)
      • 이벤트응모여부 (이벤트응모시작일자~이벤트응모종료일자)
  • 날짜 관련 util 함수 추가
    • 모든 업무에서 공통적으로 사용할 수 있는 날짜 관련 기능
    • 일시(yyyyMMddHHmmss) 뿐 아니라 날짜(yyyyMMdd) 등 custom Date format 지원 가능하도록 구현

솔루션

  1. 날짜 문자열을 숫자로 변환하여 비교 연산자로 비교
    • Integer.parseInt(String)
    • 이슈 : "yyyyMMddHHmmss" 형식 int 자료형 변환시 할당 공간 범위 초과 (The literal 20230121110000 of type int is out of range)
  2. Date 클래스의 compareTo() 활용
    • 날짜 문자열 -> Date 클래스 변환 필요 -> SimpleDateFormat 활용

소스코드 (DateUtil.java)

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.text.ParseException;

/**
 * 기준날짜가 시작날짜, 종료날짜 사이에 있는지 여부 반환
 * parse error 방지를 위해 파라미터 문자열 길이는 모두 동일해야 함
 * @param stdDateStr 기준날짜 문자열
 * @param startDateStr 시작날짜 문자열
 * @param endDateStr 종료날짜 문자열
 * @param datefrmt 날짜형식 문자열 (특수문자 포함 불가, 숫자만)
 * @return
 */
public static boolean isStdDateBetween(String stdDateStr, String startDateStr, String endDateStr, String datefrmt) {
	SimpleDateFormat sdf = new SimpleDateFormat(datefrmt, Locale.getDefault());
	Date stdDate = new Date();
	Date startDate = new Date();
	Date endDate = new Date();
	int frmtLen = 0;
		
	if (StringUtil.isEmptyTrim(datefrmt)) {
		log.info("[isStdDateBetween] datefrmt is empty.");
		return false;
	} else {
		frmtLen = datefrmt.length();
	}
		
	if (StringUtil.isEmptyTrim(stdDateStr)
		|| StringUtil.isEmptyTrim(startDateStr)
		|| StringUtil.isEmptyTrim(endDateStr)
		|| StringUtil.isEmptyTrim(datefrmt)
		|| stdDateStr.length() != frmtLen
		|| startDateStr.length() != frmtLen
		|| endDateStr.length() != frmtLen
	) {
		log.info("[isStdDateBetween] one of params is empty or params length is different.");
		return false;
	}
		
	try {
		stdDate = sdf.parse(stdDateStr);
		startDate = sdf.parse(startDateStr);
		endDate = sdf.parse(endDateStr);
	} catch (ParseException e) {
		log.error("[isStdDateBetween] parse error!" + startDateStr + "/" + endDateStr + "/" + datefrmt);
		return false;
	}
		
	return stdDate.compareTo(startDate) >= 0 && stdDate.compareTo(endDate) <= 0;
}

테스트 (JUnit5)

String stdDateyyyyMMdd = "20230121";
String stdDateyyyyMMddHHmmdd = "20230121110000";
...
@Test
@DisplayName("yyyyMMdd (정상)")
void isDayBetween_true_20230121() {
	assertTrue(DateUtil.isStdDateBetween(stdDateyyyyMMdd, "20230121", "20230123", "yyyyMMdd"));
}
	
@Test
@DisplayName("yyyyMMdd (시작날짜 == 기준날짜)")
void isDayBetween_true_20230121_start_same() {
	assertTrue(DateUtil.isStdDateBetween(stdDateyyyyMMdd, "20230121", "20230123", "yyyyMMdd"));
}
	
@Test
@DisplayName("yyyyMMdd 종료날짜 == 기준날짜)")
void isDayBetween_true_20230121_end_same() {
	assertTrue(DateUtil.isStdDateBetween(stdDateyyyyMMdd, "20230119", "20230121", "yyyyMMdd"));
}
	
@Test
@DisplayName("yyyyMMdd (시작일자 느림)")
void isDayBetween_false_20230121_start_later() {
	assertFalse(DateUtil.isStdDateBetween(stdDateyyyyMMdd, "20230129", "20230123", "yyyyMMdd"));
}
	
@Test
@DisplayName("yyyyMMdd (종료일자 빠름)")
void isDayBetween_false_20230121_end_first() {
	assertFalse(DateUtil.isStdDateBetween(stdDateyyyyMMdd, "20230120", "20230119", "yyyyMMdd"));
}
	
@Test
@DisplayName("yyyyMMdd (공백)")
void isDayBetween_false_empty() {
	assertFalse(DateUtil.isStdDateBetween(stdDateyyyyMMdd, "20230120", "", "yyyyMMdd"));
}
	
@Test
@DisplayName("yyyyMMdd (null)")
void isDayBetween_false_null() {
	assertFalse(DateUtil.isStdDateBetween(stdDateyyyyMMdd, null, "20230123", "yyyyMMdd"));
}
	
@Test
@DisplayName("yyyyMMddHHmmss (정상)")
void isDtmBetween_true_20230121110000() {
assertTrue(DateUtil.isStdDateBetween(stdDateyyyyMMddHHmmdd, "20230121100000", "20230121120000", "yyyyMMddHHmmss"));
}

...

예외

  • datefrmt == "yyyyMMdd" && compareDate (startDateStr or endDateStr) 가 당일 case
    • 기준날짜 문자열 (stdDateStr) 파라미터 추가
      • Date stdDate = new Date() 선언 -> Sat Jan 21 12:57:45 KST 2023
      • Date compareDate = new SimpleDateFormat("yyyyMMdd").parse("20230121") -> Sat Jan 21 00:00:00 KST 2023
      • stdDate 가 compareDate 보다 무조건 미래가 되는 현상 발생
      • yyyyMMdd case는 시간(HHmmss) 비교 필요 없음!

결론

  • 중복 작성될 가능성이 있는 기능은 공통 함수로 모듈화하기 😊

참고

profile
자기 개발 기록 저장소

0개의 댓글