안녕하세요 티친분들🙋♀️
그동안 포스팅이 많이 뜸(?)했습니다.
회사 적응기간이다 보니 티스토리에 포스팅하는 날이 많이 적어졌었어요.
그만큼 제가 열심히 적응했다고 생각해 주세요 🥺
오늘 작성할 내용은 날짜계산에 대한 것을 적어보려고 합니다.
학원 프로젝트때도 만져봤지만 현재 저는 Java7 버전에서 개발을 하고 있어 조금 다르더라고요.
다음에 또 사용할 수 있을 것 같아 잊어먹지 않게 한번 정리를 해보려고요. 시작해 보겠습니다.
날짜 계산이 필요하게 된 이유
업무를 하면서 기존 서비스 중인 사이트에 보안 개선건으로 요청이 왔다.
해당 기능은 날짜와 검색할 조건을 선택하고 🔍검색 버튼을 클릭하게 되면 해당 조건이 일치한 데이터를 DB에서 가져와
화면에 보여주는 기능이었다.
사용자의 이력을 조회하는 기능인데 보안 이슈로 받은 메일 사항은 이러했다.
클라이언트에서 날짜 선택이 가능한 날짜는 당일로부터 35일 전부터 당일까지 이지만
사용자가 직접 Parameter로 입력해 전송 시(-35일 이전보다 더 이전 일정으로 선택) 검색이 되어 response 된다는 것이었다.
Parameter조작으로 인한 보안 취약점이 있으니 개선하라는 메일이었다.
개발 테스트 준비
필요한 데이터
1. 현재 서버의 날짜 : today
2. 입력받은 날짜 데이터 2개(시작일 : startDate , 종료일: endDate)
3. 현재 서버의 날짜(today) - 35일 , 조회 시작 가능한 날짜 : maxStartDate
검증을 해야 하는 부분
현재 날짜로부터 최대 5주 이전부터 현재까지의 데이터를 가져와야 하므로 최대 5주(35일) 이내의 데이터를 요구하는지 검증
검증을 위한 예상 처리로직
1. startDate가 maxStartDate보다 이전이면 조회 시작 날짜를 maxStartDate로 설정
2. startDate가 today보다 이후라면 조회 시작 날짜를 maxStartDate 설정
3. startDate가 maxStartDate 이후라면 startDate 값은 그대로 유지
4. endDate와 today가 동일하면 endDate를 today로 설정
5. endDate와 today를 비교하여 today보다 이전이라면 endData 값은 그대로 유지
6. endDate와 today를 비교하여 today보다 이후라면 endDate를 today로 설정
7. startDate와 endDate가 정상범주라면 그대로 유지
Java 8 이전 버전과 이후 버전의 날짜 계산
Date는 자바에서 제공하는 날짜 클래스이다.
java.util.Date를 import 하여 사용한다.
예전에 했던 사이드 프로젝트에선 LocalDate로 날짜 계산을 했는데 현재 만지고 있는 소스는 Java 7 버전이다 보니 사용할 수 없었다.
Java 8 이후 버전은 LocalDate , LocalDateTime , ZonedDateTime 을 사용할 수 있다.
하지만 이전 버전에선 사용할 수 없기 때문에 Date, Calendar, SimpleDateFormat를 사용하여 날짜 계산을 한다.
Date 클래스
Date 클래스는 자바에서 날짜와 시간을 다루기 위해 사용되는 클래스이다. 날짜와 시간을 간단하게 표현할 수 있다.
java.util 패키지에 속해 있고 주된 특징은 자바 초기 버전부터 존재했다(엄청난 레거시..)
Date 클래스는 가변적이고(Immutable 하지 않음), java.time 패키지처럼 세밀한 시간 연산을 지원하지 않는다.
Deprecated 메서드: Date 클래스의 일부 메서드는 현재 더 이상 사용되지 않는다(Deprecated).
public class Test_DateCalCode {
public static void main(String[] args) throws ParseException {
Date today = new Date();
System.out.println("오늘의 날짜 입니다 : " + today);
}
}
Date 주요 메서드 - toString();
- 문자열 형식으로 반환
Date now = new Date();
System.out.println(now.toString());
출력 : Fri Aug 16 03:36:37 KST 2024
Date 주요 메서드 - befor(Date when);
- 인자로 들어오는 Date객체보다 이전 날짜인지 비교하여 boolean으로 반환
Date date1 = new Date();
Date date2 = new Date(date1.getTime() - 10000); // 10초 전
boolean isBefore = date2.before(date1); // true
Date 주요 메서드 - afer(Date when);
- 인자로 들어오는 Date객체보다 이후 날짜인지 비교하여 boolean으로 반환
boolean isAfter = date1.after(date2); // true
Date 주요 메서드 - compareTo(Date anotherDate);
- 인자로 들어오는 Date객체와 같은지 이전인지 이후 인지 비교하여 정수로 반환
- 현재 객체가 'anotherDate' 보다 이전이면 음수, 같으면 0, 이후면 양수를 반환
int comparison = date1.compareTo(date2); // 양수
Date 주요 메서드 - equals(Date);
- 인자로 들어오는 Date객체와 같은지 확인 후 boolean으로 반환
boolean isEqual = date1.equals(date2); // false
Date 주요 메서드 - 사용 불가 메서드
getYear(), getMonth(), getDate(), getHours(), getMinutes(), getSeconds()
Calendar 클래스
Calendar 클래스는 자바에서 날짜와 시간을 다루기 위해 사용되는 추상 클래스이다.
다양한 필드(예: 연도, 월, 일, 시간 등)를 제공해 주고, 날짜와 시간 관련 연산을 수행할 수 있는 메서드를 사용할 수 있다.
Calendar 클래스는 추상 클래스이기 때문에 직접 객체를 생성할 수 없다. (new Calendar 사용 불가)
Calendar 주요 메서드 - getInstance();
- Calendar 객체 생성
- 현재 날짜와 시간, 기본 시간대 및 로케일로 초기화된 Calendar 객체 반환
Calendar calendar = Calendar.getInstance();
Calendar 주요 메서드 - get(int field);
- 필드 값 반환하는 메서드, 예를 들어 연, 월, 시간 등을 가져올때(get) 사용한다
- 필드는 Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH 등으로 지정할 수 있다.
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH); // 0 = January, 11 = December
int day = calendar.get(Calendar.DAY_OF_MONTH);
Calendar 주요 메서드 - set(int field, int value);
- 특정 필드 값 설정하는 메서드 , 예를 들어 연,월,시간 등을 대입할 때(set) 사용한다
calendar.set(Calendar.YEAR, 2024);
calendar.set(Calendar.MONTH, Calendar.AUGUST); // 8월로 설정
calendar.set(Calendar.DAY_OF_MONTH, 16);
Calendar 주요 메서드 - add(int field, int amount);
- 특정 필드 값을 더하거나 뺄 때 사용함
calendar.add(Calendar.DAY_OF_MONTH, 1); // 하루 더하기
calendar.add(Calendar.MONTH, -1); // 한 달 빼기
Calendar 주요 메서드 : setTime(Date date);
- Date 객체를 이용하여 Calendar 객체의 날짜와 시간을 설정
calendar.setTime(new Date());
SimpleDateFormat 클래스
날짜와 시간을 특정 형식의 문자열로 변환하거나, 특정 형식의 문자열을 날짜 객체로 변환하기 위해 사용되는 클래스이다.
SimpleDateFormat은 java.text 패키지에 속해 있고, 날짜 및 시간의 형식을 정의할 수 있는 다양한 패턴을 제공한다.
날짜와 시간을 원하는 형식으로 표현, 입력된 문자열을 날짜 객체로 파싱 할 수 있게 해 준다.
Formatting : Date객체를 특정 패턴에 따라 문자열로 변환한다
Parsing : 특정 패턴의 문자열을 Date객체로 변환
SimpleDateFormat 주요 메서드 : SimpleDateFormat() 생성자
- 기본 생성자로, 기본적인 형식의 SimpleDateFormat 객체를 생성한다
- 주로 특정 패턴을 지정하여 생성하는 방식으로 사용하고 보통 인자로 포맷형식을 전달하여 사용한다.
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat 주요 메서드 : format(Date date)
- Date객체를 지정한 포맷에 따라 문자열로 반환
Date now = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate = formatter.format(now);
System.out.println("Formatted Date: " + formattedDate);
SimpleDateFormat 주요 메서드 : parse(String source)
- 문자열을 Date 객체로 변환
- 문자열 형식이 패턴과 맞지 않을 경우 ParseException 발생
String dateString = "2023-08-16 15:30:00";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date parsedDate = formatter.parse(dateString);
System.out.println("Parsed Date: " + parsedDate);
} catch (ParseException e) {
e.printStackTrace();
}
SimpleDateFormat 주요 메서드 : applyPattern(String pattern)
- 기존 SimpleDateFormat 객체에 새로운 패턴을 적용
formatter.applyPattern("dd/MM/yyyy");
String newFormattedDate = formatter.format(now);
System.out.println("New Formatted Date: " + newFormattedDate);
SimpleDateFormat 주요 메서드 : setLenient(boolean lenient)
- 날짜와 시간을 해석할 때 엄격하게(false) 또는 관대하게(true) 처리할지를 설정한다.
- 관대 모드에는 "February 30"과 같은 잘못된 날짜도 자동으로 올바른 날짜로 수정할 수 있다.
formatter.setLenient(false);
SimpleDateFormat 패턴 예시
yyyy: 연도 (예: 2024)
MM: 월 (예: 08)
dd: 일 (예: 16)
HH: 24시간 형식의 시 (예: 15)
mm: 분 (예: 30)
ss: 초 (예: 00)
EEE: 요일 축약형 (예: Wed)
MMM: 월 축약형 (예: Aug)
z: 타임존 (예: PST, GMT)
간단히 설명하자면 Date는 말 그대로 날짜 객체이고
Calendar 클래스는 Date날짜를 계산하는 클래스라고 보면 된다.
SimpleDateFormat 클래스는 날짜 포맷형식을 만들어 준다.
SimpleDateFormat클래스를 통해 Date ➡️ String , String ➡️ Date로 전환을 한다고 생각하면 된다.
Date ➡️ String : SimpleDateFormat.format
String ➡️ Date : SimpleDateFormat.parse
테스트코드
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test_DateCalCode {
public static void main(String[] args) throws ParseException {
Date today = new Date();
System.out.println("오늘의 날짜 입니다 : " + today);
SimpleDateFormat numberDateFormat = new SimpleDateFormat("yyyyMMdd");
SimpleDateFormat dashDateFormat = new SimpleDateFormat("yyyy-MM-dd");
System.out.println("------------------------------");
System.out.println("today : " + numberDateFormat.format(today));
System.out.println("today : " + dashDateFormat.format(today));
System.out.println("------------------------------");
}
}
포맷형식을 지정했을 때 이렇게 출력이 된다.
날짜 포맷을 지정하는 것과 자료형을 변환하는 것은 자주 사용할 것 같아 메서드를 만들어 분리해 준비했다.
// Date 포멧 지정 후 String으로 리턴 함
private static String dateToStr(Date paramDate) throws ParseException {
SimpleDateFormat dashDateFormat = new SimpleDateFormat("yyyy-MM-dd");
return dashDateFormat.format(paramDate);
}
// String 에서 Date로 리턴
private static Date strToDate(String strDate) throws ParseException {
SimpleDateFormat dashDateFormat = new SimpleDateFormat("yyyy-MM-dd");
return dashDateFormat.parse(strDate);
}
다음 포스팅은 이걸 가지고 어떻게 검증하는 로직을 구현하는지 작성해 보겠습니다🫡
'👩🏻💻 𝐋𝐚𝐧𝐠𝐮𝐚𝐠𝐞 > ⠀⠀⠀⠀ Jᴀᴠᴀ' 카테고리의 다른 글
Java7의 날짜계산 : Date, Calendar, SimpleDateFormat(2) (0) | 2024.08.16 |
---|---|
Java의 상수, 매직넘버란 ? (0) | 2024.04.28 |
일급 컬렉션 (First Class Collection) (0) | 2024.04.28 |
2023/11/30🤘 디자인패턴 - State Pattern & SingleTon Pattern (1) | 2023.12.05 |
2023/11/27 ~ 2023/11/29🤘 JAVA GUI Swing (0) | 2023.12.04 |