국비교육/국비교육 복습
day15_regex_Test04 : 정규 표현식 + 윤년 판정 (★★)
Luver Duck
2022. 8. 15. 20:51
(Q) 날짜 형식 검사
1) 사용자에게 생년월일을 YYYY-MM-DD 형식으로 입력받아 올바른 날짜 형식인지 검사하세요
- 연도는 1900년부터 2099년까지 가능합니다
- 최초 검사식을 만들 때는 모든 달은 31일까지 있다고 가정하고 만듭니다
2) 큰달(31일)과 작은달(30일)을 구분해서 만듭니다(2월은 28일로 가정)
3) 윤년을 고려하도록 만듭니다(정규표현식만으로 불가능합니다)
1) 모든 달을 31일까지 있다고 가정
- 정규 표현식 시각화
- 메인 메소드
package day15_regex;
import java.util.Scanner;
import java.util.regex.Pattern;
public class Test04 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 생년월일의 정규 표현식
String regex = "^(19[0-9]{2}|20[0-9]{2})-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[01])$";
// 생년월일 입력
System.out.print("생년월일 : ");
String birth = sc.next();
// 판정
boolean check = Pattern.matches(regex, birth);
// 출력
System.out.println("결과 : " + check);
sc.close();
}
}
2) 큰 달(31일), 작은 달(30일), 2월(28일)로 구분
- 정규 표현식 시각화
- 메인 메소드
package day15_regex;
import java.util.Scanner;
import java.util.regex.Pattern;
public class Test04_1 {
public static void main(String[] args) {
// 생년월일 입력
Scanner sc = new Scanner(System.in);
System.out.print("생년월일 : ");
String birth = sc.next();
sc.close();
// 생년월일의 정규 표현식
// 큰 달(31일까지 있는 달), 작은 달(30일까지 있는 달), 2월(28일까지 있는 달)로 구분
String regex = "^(19[0-9]{2}|20[0-9]{2})-((0[13578]|1[02])-(0[1-9]|1[0-9]|2[0-9]|3[01])|(0[469]|11)-(0[1-9]|1[0-9]|2[0-9]|30)|02-(0[1-9]|1[0-9]|2[0-8]))$";
// 판정
boolean check = Pattern.matches(regex, birth);
// 출력
System.out.println("결과 : " + check);
}
}
** 2)를 switch ~ case로 작성한 경우
- 생년월일에서 월에 해당하는 값을 추출해서 switch 각 case의 String 값과 비교
package day15_regex;
import java.util.Scanner;
import java.util.regex.Pattern;
public class Test04_etc {
public static void main(String[] args) {
// 생년월일 입력
Scanner sc = new Scanner(System.in);
System.out.print("생년월일 : ");
String birth = sc.next();
sc.close();
// 생년월일의 정규 표현식
String regex = null;
switch(birth.substring(5, 7)) {
case "02":
regex = "^(19[0-9]{2}|20[0-9]{2})-(02)-(0[1-9]|1[0-9]|2[0-8])$";
break;
case "04": case "06": case "09": case "11":
regex = "^(19[0-9]{2}|20[0-9]{2})-(0[469]|11)-(0[1-9]|1[0-9]|2[0-9]|30)$";
break;
case "01": case "03": case "05": case "07": case "08": case "10": case "12":
regex = "^(19[0-9]{2}|20[0-9]{2})-(0[13578]|1[02])-(0[1-9]|1[0-9]|2[0-9]|3[01])$";
break;
}
// 판정
boolean check = Pattern.matches(regex, birth);
// 출력
System.out.println("결과 : " + check);
}
}
3) 2)에서 윤년을 고려하는 경우
- 정규 표현식 시각화
i) 윤년인 경우 (2월이 29일까지 존재)
ii) 윤년이 아닌 경우 (2월이 28일까지 존재)
- 메인 메소드
package day15_regex;
import java.util.Scanner;
import java.util.regex.Pattern;
public class Test04_2 {
public static void main(String[] args) {
// 생년월일 입력
Scanner sc = new Scanner(System.in);
System.out.print("생년월일 : ");
String birth = sc.next();
sc.close();
// 생년월일의 정규 표현식 - 윤년을 고려하는 경우
// 입력에서 년도만 추출 : (birth.substring(0, 4)
// 추출한 년도를 숫자로 변환 : Integer.parseInt(birth.substring(0, 4))
int yearValue = Integer.parseInt(birth.substring(0, 4));
// 윤년 판정
// 년도가 4의 배수이면 윤년 O
// 년도가 4의 배수이면서 100의 배수이면 윤년 X
// -> 년도가 4의 배수이면서(&&) 100의 배수가 아니면 윤년 O
// 년도가 4의 배수이면서 100의 배수이지만 400의 배수이면(||) 윤년 O
boolean leap = yearValue % 4 == 0 && yearValue % 100 != 0 || yearValue % 400 == 0;
// 윤년일 때와 윤년이 아닐 때의 정규 표현식
String regex;
if(leap) {
regex = "^(19[0-9]{2}|20[0-9]{2})-((0[13578]|1[02])-(0[1-9]|1[0-9]|2[0-9]|3[01])|(0[469]|11)-(0[1-9]|1[0-9]|2[0-9]|30)|02-(0[1-9]|1[0-9]|2[0-9]))$";
}
else {
regex = "^(19[0-9]{2}|20[0-9]{2})-((0[13578]|1[02])-(0[1-9]|1[0-9]|2[0-9]|3[01])|(0[469]|11)-(0[1-9]|1[0-9]|2[0-9]|30)|02-(0[1-9]|1[0-9]|2[0-8]))$";
}
// 판정
boolean check = Pattern.matches(regex, birth);
// 출력
System.out.println("결과 : " + check);
}
}
- 윤년 판정
1) 년도가 4의 배수이면 윤년 O
2) 년도가 4의 배수이면서 100의 배수이면 윤년 X
-> 년도가 4의 배수이면서(&&) 100의 배수가 아니면 윤년 O
3) 년도가 4의 배수이면서 100의 배수이지만 400의 배수이면(||) 윤년 O