偏复杂的日期系列题,但明晰思路后并不难。

思考我们人类是如何根据这些输入参数推算未来日期的——我们都知道每个月份对应有多少天,之后根据这个未来日数推算过这么多天一共相当于过了多少个月零几日。而一年又只有12个月,这意味着可能需要对超过一年的部分进行额外的处理。基于这个结论,就可以实现这道题的算法。

import java.util.Scanner;

public class Main {
    public static boolean isLunarYear(int year) {
        return year % 4 == 0 && !(year % 100 == 0 && year % 400 != 0);
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int m = in.nextInt();
        while (m-- > 0) {
            // 解
            int year, month, day, dayComingUpCount;
            year = in.nextInt();
            month = in.nextInt();
            day = in.nextInt();
            dayComingUpCount = in.nextInt();
            // 输入日期是其对应上个月底之后的第几天
            dayComingUpCount = day + dayComingUpCount;
            // 节点表
            int[] lunarYearDayCount = new int[] {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
            int[] normalYearDayCount = new int[13];
            for (int i = 0; i <= 12; i++) {
                normalYearDayCount[i] = lunarYearDayCount[i];
            }
            normalYearDayCount[2]--;
            while (true) {
                // 查表
                // 闰年
                if (isLunarYear(year)) {
                    // 如果剩余需要运算的日数不满一个月,那么输出就行,并且结束这一输入案例的查表
                    if (dayComingUpCount <= lunarYearDayCount[month]) {
                        System.out.println(String.format("%04d-%02d-%02d", year, month,
                                                         dayComingUpCount));
                        break;
                    } else {
                        // 如果剩余需要运算的日数还超过一个月,就继续减去这个月的天数运算
                        dayComingUpCount -= lunarYearDayCount[month];
                        // 对应月份数加一。特别地,如果加一后已经到第十三个月,那么新开一年,月份恢复至1
                        if (++month == 13) {
                            year++;
                            month = 1;
                        }
                        continue;
                    }
                } else {
                    // 平年原理与闰年一致
                    if (dayComingUpCount <= normalYearDayCount[month]) {
                        System.out.println(String.format("%04d-%02d-%02d", year, month,
                                                         dayComingUpCount));
                        break;
                    } else {
                        dayComingUpCount -= normalYearDayCount[month];
                        if (++month == 13) {
                            year++;
                            month = 1;
                        }
                        continue;
                    }
                }
            }
        }
    }
}

思考为什么代码块第39、53两行使用的是++month而不是month++。这是因为,前者是先增1后计算,而后者是先计算后增1;在上方代码中,采用month++会造成对应条件语句不执行的情况。