everyday com-eat
작성일
2022. 11. 11. 14:51
작성자
갱수터
728x90
  1. 코드를 쓴 상황
    fullcalendar를 이용한 일정관리 시스템 개발 중 반복 일정에 대한 화면에 표시 될 날짜 구하기
  2. 에러메시지
    테스트코드에서는 모든 타입에 대한 반복일정 날짜들이 제대로 나오는데, 서비스단에서 DB연결하면 반복문 너무 돌아서 데이터 못불러옴
  3. 내 코드
    @Test
    @DisplayName("dateList 구하기")
    void getDateList() {
    	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    	
    	//매개변수로 받는거
    	VinatechCalendarDto dto = new VinatechCalendarDto();
    	ViewCalendarInfo viewCalendarInfo = new ViewCalendarInfo("2022-10-30", "2022-12-04");
    	
    	//정보 넣기
    	dto.setId("CALENDAR_20221103113427854001");
    	dto.setAllDay(true);
    	dto.setStart("2022-11-03");
    	dto.setEnd("2022-11-03");
    	dto.setColor("#E67C73");
    	dto.setTitle("반복일정");
    
    	VinatechCalendarReptDto reptInfo = new VinatechCalendarReptDto();
    
    	reptInfo.setCalendarReptStart("2021-11-02");
    	reptInfo.setCalendarReptEnd(null);
    	reptInfo.setCalendarReptType("Y");
    	reptInfo.setCalendarReptYear("1");
    	reptInfo.setCalendarReptMonth(null);
    	reptInfo.setCalendarReptWeek(null);
    	reptInfo.setCalendarReptWeekday(null);
    	reptInfo.setCalendarReptDay(null);
    	
    	dto.setCalendarRept(reptInfo);
    	
    	//공통 변수 빼기
    	List<String> dateList = new ArrayList<>();	//결과값 담을 List 생성
    	
    	String reptType = reptInfo.getCalendarReptType();
    	String reptStart = reptInfo.getCalendarReptStart();
    	String reptEnd = reptInfo.getCalendarReptEnd();
    	
    	String temp = null;
    	Date tempDate = null;
    	Date reptEndDate = null;
    	
    	
    	if(reptType.equals("Y")) {
    		int reptYear = Integer.parseInt(reptInfo.getCalendarReptYear());
    		temp =  ServerDateTime.addYearDate(reptStart, reptYear);
    		
    		try {
    			tempDate = dateFormat.parse(temp);
    			
    			while(tempDate.compareTo(viewCalendarInfo.getStartDate()) < 0) {
    				temp = ServerDateTime.addYearDate(temp, reptYear);
    				tempDate = dateFormat.parse(temp);
    			}
    			
    			if(tempDate.compareTo(viewCalendarInfo.getEndDate()) <= 0) {
    				if(reptInfo.getCalendarReptEnd() == null) {
    					dateList.add(temp);
    				}else {
    					reptEndDate = dateFormat.parse(reptInfo.getCalendarReptEnd());
    					if(tempDate.compareTo(reptEndDate) <= 0) dateList.add(temp);
    				}
    			}
    			
    			System.out.println(dateList);
    			
    		} catch (ParseException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	
    	if(reptType.equals("D")) {
    		int reptDay = Integer.parseInt(reptInfo.getCalendarReptDay());
    		temp = ServerDateTime.addDate(reptStart, reptDay);
    		
    		try {
    			tempDate = dateFormat.parse(temp);
    			
    			while(tempDate.compareTo(viewCalendarInfo.getStartDate()) < 0) {
    				temp = ServerDateTime.addDate(temp, reptDay);
    				tempDate = dateFormat.parse(temp);
    			}
    			
    			while(tempDate.compareTo(viewCalendarInfo.getEndDate()) <= 0) {
    				
    				if(reptInfo.getCalendarReptEnd() == null) {
    					dateList.add(temp);
    				}else {
    					reptEndDate = dateFormat.parse(reptInfo.getCalendarReptEnd());
    					if(tempDate.compareTo(reptEndDate) <= 0) dateList.add(temp);
    				}
    				
    				temp = ServerDateTime.addDate(temp, reptDay);
    				tempDate = dateFormat.parse(temp);  
    			}
    			
    			System.out.println(dateList);
    			
    			
    		} catch (ParseException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	if(reptType.equals("M")) {
    		int reptMonth = Integer.parseInt(reptInfo.getCalendarReptMonth());
    		temp = ServerDateTime.addMonthDate(reptStart, reptMonth);
    		
    		while(Integer.parseInt(ServerDateTime.month(temp)) < Integer.parseInt(ServerDateTime.month(viewCalendarInfo.getTargetStart()))) {
    			temp = ServerDateTime.addMonthDate(temp, reptMonth);
    		}
    		
    		try {
    			tempDate = dateFormat.parse(temp);
    			
    			if(tempDate.compareTo(viewCalendarInfo.getTargetStartDate()) >= 0 && tempDate.compareTo(viewCalendarInfo.getEndDate()) <= 0) {
    				
    				if(reptInfo.getCalendarReptDay() != null) {	//날짜 반복
    					temp = ServerDateTime.addDate(ServerDateTime.firstDate(temp), Integer.parseInt(reptInfo.getCalendarReptDay())-1);
    					tempDate = dateFormat.parse(temp);
    					
    				}else { //몇번째 요일 반복
    					
    					int reptWeekday = Integer.parseInt(reptInfo.getCalendarReptWeekday());
    					
    					List<List<String>> selectMonth = ServerDateTime.monthOfWeekList(viewCalendarInfo.getTargetStart(), viewCalendarInfo.getTargetEnd());
    					Map<Integer, List<String>> weekTypeMap = new HashMap<>();
    					
    					for(List<String> selectWeek : selectMonth) {
    						for(String selectDay : selectWeek) {
    							int weekday = ServerDateTime.week(selectDay);				
    							
    							if(weekTypeMap.get(weekday) == null)  weekTypeMap.put(weekday, new ArrayList<String>());
    							
    							List<String> weekList = weekTypeMap.get(weekday);
    							weekList.add(selectDay);
    						}
    					}
    					
    					List<String> targetWeekList = weekTypeMap.get(reptWeekday);
    					
    					if(reptInfo.getCalendarReptWeek().equals("last")) {
    						temp = targetWeekList.get(targetWeekList.size() - 1);
    					}else {
    						temp = targetWeekList.get(Integer.parseInt(reptInfo.getCalendarReptWeek()) - 1);
    					}
    					
    					tempDate = dateFormat.parse(temp);
    				}
    				
    				
    				if(reptInfo.getCalendarReptEnd() == null) {
    					dateList.add(temp);
    				}else {
    					reptEndDate = dateFormat.parse(reptInfo.getCalendarReptEnd());
    					if(tempDate.compareTo(reptEndDate) <= 0) dateList.add(temp);
    				}
    				
    				System.out.println(dateList);
    			}
    			
    		} catch (ParseException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	if(reptType.equals("W")) {
    		//요일 문자열 > list로 변환
    		List<Integer> reptWeekdayList = new ArrayList<>();
    		StringTokenizer st = new StringTokenizer(reptInfo.getCalendarReptWeekday(), ",");
    		while(st.hasMoreTokens()) {reptWeekdayList.add(Integer.parseInt(st.nextToken()));}
    		
    		//자주 쓰는 데이터 변수만들기
    		int reptWeek = Integer.parseInt(reptInfo.getCalendarReptWeek());
    		temp = ServerDateTime.addWeekDate(reptStart, reptWeek);	//n주 후 날짜 구하기
    		List<String> tempWeek = null;
    		
    		try {
    			//문자열 > Date 화
    			tempDate = dateFormat.parse(temp);
    			
    			//이달의 첫 반복일정 날짜 구하기
    			while(tempDate.compareTo(viewCalendarInfo.getStartDate()) < 0) {temp = ServerDateTime.addWeekDate(temp, reptWeek);}
    			tempDate = dateFormat.parse(temp);
    			
    			while(tempDate.compareTo(viewCalendarInfo.getEndDate()) <= 0) {
    				tempWeek = ServerDateTime.weekDateList(ServerDateTime.firstWeekDate(temp), 1);	//n주 후 날짜가 포함된 주 list 구하기
    				tempWeek.add(0, tempWeek.get(tempWeek.size() - 1));
    				tempWeek.remove(tempWeek.size() - 1);
    				
    				//구한 일주일 중 DB에 저장된 반복 요일 dateList에 추가하기
    				for(int weekday : reptWeekdayList) {
    					tempDate = dateFormat.parse(tempWeek.get(weekday));
    					
    					if(reptInfo.getCalendarReptEnd() == null) {
    						dateList.add(tempWeek.get(weekday));
    					}else {
    						reptEndDate = dateFormat.parse(reptInfo.getCalendarReptEnd());
    						if(tempDate.compareTo(reptEndDate) <= 0) dateList.add(tempWeek.get(weekday));
    					}
    				}
    				
    				temp = ServerDateTime.addWeekDate(temp, reptWeek);
    				tempDate = dateFormat.parse(temp);
    			}
    			
    			System.out.println(dateList);
    			return;
    			
    			
    		} catch (ParseException e) {
    			System.out.println("오류 : " + e);
    		}
    	}
    	
    	
    }
    
    @Getter
    @Setter
    @ToString
    class ViewCalendarInfo{	
    	String start;
    	String end;
    	String targetStart;
    	String targetEnd;
    	
    	Date startDate;
    	Date endDate;
    	Date targetStartDate;
    	Date targetEndDate;
    	
    	public ViewCalendarInfo(String start, String end){
    		this.start = start;
    		this.end = end;
    		this.targetStart = start;
    		this.targetEnd = end;
    		
    		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    		
    		// 달력 정보 String > Date
    		try {
    			startDate = dateFormat.parse(start);
    			endDate = dateFormat.parse(end);
    			Date tempDate = dateFormat.parse(ServerDateTime.addDate(start, 7));
    			
    			//월간, 주간 target Start,End 조정
    			if(!tempDate.equals(endDate) && ServerDateTime.firstDate(ServerDateTime.addMonthDate(start, 1)) != ServerDateTime.firstDate(end)) {
    				targetStart =  ServerDateTime.firstDate(ServerDateTime.addMonthDate(start, 1));
    				targetEnd = ServerDateTime.lastDate(targetStart);
    			}
    			
    			targetStartDate = dateFormat.parse(targetStart);
    			targetEndDate = dateFormat.parse(targetEnd);
    			
    		} catch (ParseException e) {
    			e.printStackTrace();
    		}
    		
    	}
    }
  4. 해결

    이번 달에 찍히는 첫번째 반복일정의 날짜를 반복문으로 돌려서 구했었는데 이 부분 때문에 반복문이 돌다가 오류가 난 것 같다. 팀장님의 도움을 받아 전체적인 코드를 수정하고, 반복 타입이 매주 반복일 때 반복일정 시작날과 이번 달 첫번째 주와의 전체 주 차이를 계산하여 반복 주기로 나눴을 때 나머지에 따라 0이면 첫째주, 1이면 둘째주로 반복문 사용하지 않고 첫번째 날짜 구함
List<String> dateList = new ArrayList<>();
String reptType = reptInfo.getCalendarReptType();
String reptStart = reptInfo.getCalendarReptStart();
String reptEnd = reptInfo.getCalendarReptEnd();

ChronoUnit type = null;

if(reptType.equals("W")) {
	type = ChronoUnit.WEEKS;
	
	int reptWeek = Integer.parseInt(reptInfo.getCalendarReptWeek());
	int[] reptWeekdayList = Arrays.stream(reptInfo.getCalendarReptWeekday().split(",")).mapToInt(Integer::parseInt).toArray();
	List<List<String>> monthOfWeekList = ServerDateTime.monthOfWeekList(viewCalendarInfo.getStart(), viewCalendarInfo.getEnd());
	
	for(int w : reptWeekdayList){
		
		for(List<String> weekList : monthOfWeekList) {
			for(String date : weekList) {
				
				int getWeek = ServerDateTime.week(date) == 7 ? 0 : ServerDateTime.week(date);
				if(w == getWeek && checkReptDate(reptStart, reptEnd, date, type, reptWeek)) dateList.add(date);
			}
		}
		
	}
	
	return dateList;
}

if(reptType.equals("M")) {
	type = ChronoUnit.MONTHS;
	
	int reptMonth = Integer.parseInt(reptInfo.getCalendarReptMonth());
	int monthDiff = (int) ChronoUnit.MONTHS.between(LocalDate.parse(reptStart), LocalDate.parse(viewCalendarInfo.getTargetStart())) + 1;
	String date = null;
	
	if(reptInfo.getCalendarReptDay() != null) {	//날짜 반복
		date = ServerDateTime.addMonthDate(reptStart, monthDiff);
		
	}else { //몇번째 요일 반복
		int reptWeekday = Integer.parseInt(reptInfo.getCalendarReptWeekday());
		
		List<List<String>> selectMonth = ServerDateTime.monthOfWeekList(viewCalendarInfo.getTargetStart(), viewCalendarInfo.getTargetEnd());
		Map<Integer, List<String>> weekTypeMap = new HashMap<>();
		
		for(List<String> selectWeek : selectMonth) {
			for(String selectDay : selectWeek) {
				int weekday = ServerDateTime.week(selectDay);				
				
				if(weekTypeMap.get(weekday) == null)  weekTypeMap.put(weekday, new ArrayList<String>());
				
				List<String> weekList = weekTypeMap.get(weekday);
				weekList.add(selectDay);
			}
		}
		
		List<String> targetWeekList = weekTypeMap.get(reptWeekday);
		System.out.println("targetWeekList : " + targetWeekList);
		
		if(reptInfo.getCalendarReptWeek().equals("last")) {
			date = targetWeekList.get(targetWeekList.size() - 1);
		}else {
			date = targetWeekList.get(Integer.parseInt(reptInfo.getCalendarReptWeek()) - 1);
		}
	}
	
	if(checkReptDate(reptStart, reptEnd, date, type, reptMonth)) dateList.add(date);
	return dateList;
}

 

728x90