カレンダー4


今日は難易度が高くて、授業が1時間しかありません.何日か考えて、やっと欲しい結果が出たのに、また最初からやり直そうとしても、できないかもしれない.歩きながら頭を整理するとにかく、TIL開始

1.正確なカレンダ出力を得るには、年と月のみを入力します(曜日)。

//Prompt

import java.util.Scanner;

public class Prompt {
	public void runPrompt() {
    	Scanner scanner = new Scanner(System.in);
        Calendar cal = new Calendar();
        
        while(true) {
        	System.out.println("년을 입력하세요.");
            int year = scanner.nextInt();
            if (year < 1) {
            	System.out.println("bye");
                break;
            }
            
            System.out.println("월을 입력하세요.");
            int month = scanner.nextInt();
			if (month < 1 || month > 12) {
            	System.out.println("잘못 입력하셨습니다.");
                continue;
            }
            
            cal.printCalendar(year, month);
        }
    }
    
    public static void main(String[] args) {
    	Prompt p = new Prompt();
        p.runPrompt();
    } 
}
// Calendar

public class Calendar {
	public static final int[] MAX_DAYS = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    public static final int[] LEAP_MAX_DAYS = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    public int maxDaysOfMonth(int year, int month) {
    	if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
        	return LEAP_MAX_DAYS[month];
        }
        
        else {
        	return MAX_DAYS[month];
        }
    }
    
    public void printCalendar(int year, int month) {
    	System.out.printf("\t\t<<%d년 %d월>>\n", year, month);
        System.out.println("\tSU\tMO\tTU\tWE\tTH\tFR\tSA");
        System.out.println("\t--------------------------");
        
        
        int maxDay = maxDaysOfMonth(year, month);
        int weekday = getWeekdays(year, month);
        
        for (int i=0; i<weekday; i++) {
        	System.out.print("\t");
        }
        
        for (int j=1; j<7-weekday; j++) {
        	System.out.printf("\t%d", j);
        }
        System.out.println();
        
        int cnt = 7 - weekday;
        if (cnt == 7) {
        	cnt = 0;
        }
        
        for (int k=8-weekday; k<maxDay; k++) {
        	System.out.printf("\t%d",k);
       		if (k % 7 == cnt) {
            	System.out.println();
            }       
        }
        System.out.println();
       	System.out.println();        
    }
	
    public int getWeekdays(int year, int month) {
        int initialDay = 1; // 1년 1월 1일이 월요일 기준 잡음

		// 년
        int yearSum = 0;
        for (int i=1; i<year; i++) {
        	for (int j=1; j<=12; j++) {
            	yearSum += maxDaysOfMonth(i,j);
            }
        }
        
        // 월
        int monthSum = 0;
        for (int k=1; k<month; k++) {
        	monthSum += maxDaysOfMonth(year, k);
        }
        
        return (initialDay + yearSum + monthSum) % 7;
    }
}

(1)getWeekday関数


年、月の入出力実績カレンダーのみを受け入れ、ある日を基準点として、その基準日から日付を追加して減算し、欲しい日付のカレンダーを出力するのが最も重要な論理です.もっと簡単な説明は、1年1月1日を月曜日とするのが目安です.それでも基準点だけを置くという事実はたくさんあります.月が31日、31%7=3日の場合、来月1日は先月1日の週から3日後の週になります.1月1日は月曜日、2月1日は木曜日です.一ヶ月三十日は二日後の週で、二十八日は前の日の週です.そして、うるう年をもう1年考えて、今年が平年なら、今年の1月1日曜日の次の週が次の年の週です.1年1月1日は月曜日、2年2月1日は火曜日です.365%7=1日なので.今年が閏年なら366%7=2日なので、来年の1月1日が来週になります.これらを一般化した論理解を行えば,1年1月1日を基準として入力した年に日付を付けて7の残り時間で割って曜日を計算し,さらに月を加えることで毎月の曜日を計算することができる.