Topic Collection: American Holidays


Bull Link: American Holidays

1. Introduction to the topic

Unlike Chinese festivals, American holidays usually take the form of choosing the first few weeks of a certain month, so the holiday dates are different every year. The specific rules are as follows:

  • January 1: New Year's Day
  • Third Monday in January: Martin Luther King Day
  • Third Monday in February: President's Day
  • Last Monday in May: Memorial Day
  • July 4: American National Day
  • First Monday in September: Labor Day
  • Fourth Thursday in November: Thanksgiving
  • December 25: Christmas

Now given a year, please help generate the date of the festival in that year.

Enter description:

输入包含多组数据,每组数据包含一个正整数year(2000≤year≤9999)

Output description:

对应每一组数据,以“YYYY-MM-DD”格式输出当年所有的节日日期,每个日期占一行。
每组数据之后输出一个空行作为分隔。

2. Overview of ideas

There are two types of festivals in the title: 固定日期the festivals and 非固定日期the festivals

直接输出(1) For the former

(2) For the latter, we need to find a reference time to find the day of the week of a certain month. The reference time here is set to the 1st of the month.

For example, today is March 1, 2022. If you want to ask for the date of the third Monday in March 2022, you can infer the date of the third Monday in March based on the day of the week on March 1. No

Then, the question asked now is the day of the week on March 1, 2022. If I clearly know that February 21, 2022 is Monday, then according to the difference between February 21 and March 1, the result is % previous 7, you can know the day of the week on March 1 (the difference is 8 days, then 1+8%7=2, March 1 is Tuesday). Here, in order to find out the difference of a few days more conveniently and concisely, the reference time used is 公元前1年12月31日,该日为星期天.

In the process of calculating the difference of a few days between December 31, 1 BC, it is necessary to pay attention to one extra day in leap years.

3. Detailed process

(1) How many days is the difference between the given year, month and day (YMD) and December 31, 1 BC

总公式:days = (YMD)-(0000-12-31) = the number of days in the past complete year + the number of days in the last year (Yth year)

分公式1: The total number of days in the past full year = (Y-1) * 365 + the number of leap years in these full years * 1

分公式2: Leap year number = (Y - 1) / 4 - (Y - 1) / 100 + (Y - 1) / 400

分公式3: The number of days passed in the last year = the sum of the number of days in a complete month + D + is it a leap year? 1 : 0 (the premise of February has passed, otherwise the last item will not be added)

分公式4:闰年 = (Y % 400 == 0)||(Y % 4 == 0 && Y % 100 != 0)

insert image description here

From the above formula it can be deduced

days = (Y-M-D)-(0000-12-31)=(Y-1)*365 + (Y-1)/4 - (Y-1)/100 + 
		(Y-1)/400 +  完整月的天数 + D + 是否是闰年?1:0

At this point, the difference in days can be calculated, (YMD) is the week ( days % 7 == 0 ? 7 : days%7 )

Since the result of days requires %7, and 365 equals 364 + 1,364 equals 52 * 7, the days formula can be simplified to:

days = (Y-1) + (Y-1)/4 - (Y-1)/100 + (Y-1)/400 + 完整月的天数 + D + 是否是闰年?1:0

(2) According to the week X on the 1st of a certain month (already found), to know the date of the Wth week Q of the month

According to the above analysis, we can ask for the day of the week on the 1st of a month. For example, if January 1st has been found to be a Saturday, if we want to ask for the third Monday in January: Martin Luther King Day, we can pass Find the rules to draw conclusions:

insert image description here

Introducing the conclusion: when the 1st is week X, the date of the third Monday is 1 + 2 * 7 + (7-X+1)% 7

Let's analyze the fourth Thursday in November: Thanksgiving. Knowing that November 1st is Tuesday, then you can find the pattern:

insert image description here

结论: When the 1st is week X, the date of the Wth week Q is 1 + (W-1) * 7 + (7-X+Q) % 7

There is one more special of all dates, which is the last Monday in May: Memorial Day

June 1st can be regarded as May 32nd, and it is known that June 1st is week X, then the last Monday of May can be launched:

insert image description here

结论: When June 1 is week X, the date of the last Monday in May is 32 - (X == 1 ? 7 : X - 1)

Fourth, code writing

import java.util.*;
public class Main {
    
    
    //来判断是否是闰年
    public static boolean isYear(int Y) {
    
    
        return ((Y % 400 == 0)||(Y % 4 == 0 && Y % 100 != 0));
    }
    //来算算第Y年已经过了多少天了
    private static final int[] mouth = {
    
    31,28,31,30,31,30,31,31,30,31,30,31};//按照平年的来算
    public static int yDay(int Y,int M,int D) {
    
    
        int ret = 0;
        for(int i = 0;i < M-1;i ++) {
    
    
            ret += mouth[i];
        }
        //如果月份过了2月就来判断一下是否是闰年,是的话加一
        if(M > 2 && isYear(Y)) {
    
    
            ret ++;
        }
        return ret + D;
    }
    //来算算从0000-12-31到Y-M-D一共隔的天数(简化过的结果)
    public static int count(int Y,int M,int D) {
    
    
        return (Y - 1) + (Y - 1)/ 4 - (Y - 1) / 100 + (Y - 1) / 400 + yDay(Y,M,D);
    }
    //来算算某年某月的一号是星期几
    public static int One(int Y,int M,int D) {
    
    
        int X = count(Y,M,D)%7;
        if(X == 0){
    
    
            X = 7;
        }
        return X;
    }
    //来算算第W个星期Q的日期
    public static int m1(int X,int W,int Q) {
    
    
        return 1 + (W-1) * 7 + (7-X+Q) % 7;
    }
    //来算算5月的最后一个星期一的日期
    public static int m2(int X) {
    
    
        int d = (X == 1? 7:X-1);
        return 32 - d;
    }
    
    public static void main(String[] args) {
    
    
        Scanner scan = new Scanner(System.in);
        while(scan.hasNextInt()) {
    
    
            int Y = scan.nextInt();
            System.out.printf("%d-01-01\n",Y);//1月1日
            int X = 0;
            X = One(Y,1,1);
            System.out.printf("%d-01-%02d\n",Y,m1(X,3,1));//1月的第三个星期一
            X = One(Y,2,1);
            System.out.printf("%d-02-%02d\n",Y,m1(X,3,1));//2月的第三个星期一
            X = One(Y,6,1);
            System.out.printf("%d-05-%02d\n",Y,m2(X));//5月的最后一个星期一
            System.out.printf("%d-07-04\n",Y);//7月4日
            X = One(Y,9,1);
            System.out.printf("%d-09-%02d\n",Y,m1(X,1,1));//9月的第一个星期一
            X = One(Y,11,1);
            System.out.printf("%d-11-%02d\n",Y,m1(X,4,4));//11月的第四个星期四
            System.out.printf("%d-12-25\n",Y);
            System.out.println();//12月25日
        }
    }
}

Finish!

Guess you like

Origin blog.csdn.net/weixin_46103589/article/details/123870962