在编程竞赛中,日期和时间计算是常见考点,涉及 闰年判断、星期计算、日期间隔计算 等问题。本日的学习目标:
闰年(Leap Year)是 一个额外的 2 月 29 日,用来调整公历与天文年的误差。
判断规则
规则:
能被4整除但不能被100整除的年份是闰年。
能被400整除的年份也是闰年。
例子:2000年是闰年,1900年不是闰年。
例如:
import java.util.Scanner;
public class LeapYear {
public static boolean isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入年份:");
int year = scanner.nextInt();
if (isLeapYear(year)) {
System.out.println(year + " 是闰年");
} else {
System.out.println(year + " 不是闰年");
}
}
}
✅ 时间复杂度 O(1),只进行几次取模计算,速度非常快。
public static int getDaysOfMonth(int year, int month) {
int[] days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month == 2 && isLeapYear(year)) return 29; // 闰年2月
return days[month - 1]; // 月份从1开始,数组下标从0开始
}
蔡勒公式(Zeller's Congruence)
W=(y+y/4−y/100+y/400+(13(m+1))/5+d)W = (y + y/4 - y/100 + y/400 + (13(m+1))/5 + d) % 7
参数解释
0 - 星期六, 1 - 星期日, 2 - 星期一, 3 - 星期二, 4 - 星期三, 5 - 星期四, 6 - 星期五
import java.util.Scanner;
public class DayOfWeek {
public static String getDayOfWeek(int year, int month, int day) {
if (month == 1 || month == 2) {
month += 12; // 1月和2月看作前一年 13、14 月
year--;
}
int w = (year + year / 4 - year / 100 + year / 400 + (13 * (month + 1)) / 5 + day) % 7;
String[] days = {"星期六", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五"};
return days[w];
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入年份、月份、日期(用空格分隔):");
int year = scanner.nextInt();
int month = scanner.nextInt();
int day = scanner.nextInt();
System.out.println(year + "年" + month + "月" + day + "日 是 " + getDayOfWeek(year, month, day));
}
}
✅ 时间复杂度 O(1),直接计算,不用循环。
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Scanner;
public class DateDifference {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入第一个日期(格式:yyyy mm dd):");
int year1 = scanner.nextInt();
int month1 = scanner.nextInt();
int day1 = scanner.nextInt();
System.out.println("请输入第二个日期(格式:yyyy mm dd):");
int year2 = scanner.nextInt();
int month2 = scanner.nextInt();
int day2 = scanner.nextInt();
LocalDate date1 = LocalDate.of(year1, month1, day1);
LocalDate date2 = LocalDate.of(year2, month2, day2);
long daysBetween = ChronoUnit.DAYS.between(date1, date2);
System.out.println("两个日期相差 " + Math.abs(daysBetween) + " 天");
}
}
✅ 时间复杂度 O(1),使用 Java 8 LocalDate 处理日期,避免手动计算。
考点 |
典型题目 |
优化技巧 |
闰年判断 |
判断某年是否为闰年 |
直接使用 `if ((year % 4 == 0 && year % 100 != 0) |
星期计算 |
给定年月日,计算星期几 |
使用 蔡勒公式 |
日期间隔 |
计算两个日期间隔天数 |
LocalDate 计算更高效 |
自定义日历 |
模拟日历程序 |
Java Calendar 或 LocalDateTime |
❌ 1. 忘记 1 月 和 2 月 的特殊处理
if (month == 1 || month == 2) {
month += 12;
year--;
}
❌ 2. 日期范围错误
LocalDate date1 = LocalDate.of(2022, 13, 15); // ❌ 错误,月份超出范围
✅ 正确做法
LocalDate date1 = LocalDate.of(2022, 12, 15); // ✅ 正确
❌ 3. ChronoUnit.DAYS.between() 使用错误
long days = ChronoUnit.DAYS.between(date2, date1); // ❌ 可能得到负值
✅ 正确做法
long days = Math.abs(ChronoUnit.DAYS.between(date1, date2)); // ✅ 取绝对值