一、一周中的第几天
1.题目
给你一个日期,请你设计一个算法来判断它是对应一周中的哪一天。
输入为三个整数:day、month 和 year,分别表示日、月、年。
您返回的结果必须是这几个值中的一个 {“Sunday”, “Monday”,
“Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday”}。
给出的日期一定是在 1971 到 2100 年之间的有效日期。
2.分析
这道题涉及到的知识点:
- 平闰年判断:一个年份,如果能被100整除且能被400整除,或者不能被100整除且能被4整除,那么这个年份就是闰年,否则为平年。
- 平年一年365天,2月有28天;闰年一年有366天,2月有29天。
- 这道题还有一个隐藏条件:1971年1月1日是星期五。
思路:
(1)因为结果需要返回星期几的英文字符串,所以可以定义一个星期英文字符串的数组。
(2)由于最后求出是给定日期的星期相对于1971年1月1日星期的差值,所以需要再通过 (1971年星期下标 + 差值 - 1)% 7 来得到指定日期的星期下标(对7取余是因为有可能加上差值会超出数组最大长度)。
- 定义星期字符串数组 String[] weeks
- 循环累加1971年到 year - 1 年的天数
- 循环累加 year 年 1 月到 month - 1 月的天数
- 再累加 day后对7取余,得到从1971年1月1日起经过了n个完整的星期后,多出了几天
- 再通过这个差值确定在数组 String[] weeks 中的下标值
3.代码
public String dayOfTheWeek(int day, int month, int year) {
String[] weeks = {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
//每个月的天数
int[] daysOfMonths = {0,31,28,31,30,31,30,31,31,30,31,30,31};
//计算给定日期离19710101经过了多少天
int dates = 0;
for(int i = 1971;i < year;i++){
//闰年
if(isLeapYear(i)){
dates += 366;
continue;
}
//平年
dates += 365;
}
for(int i = 1;i < month;i++){
//2月份闰年29天
if(i == 2){
dates += isLeapYear(year) ? 29 : 28;
continue;
}
dates += daysOfMonths[i];
}
dates = (dates + day) % 7;
//19710101是星期五,下标为4
return weeks[(4 + (dates - 1)) % 7];
}
private boolean isLeapYear(int i){
return (i % 400 == 0) || (i % 4 == 0 && i % 100 != 0);
}
二、一年中的第几天
1.题目
给你一个按 YYYY-MM-DD 格式表示日期的字符串 date,请你计算并返回该日期是当年的第几天。
通常情况下,我们认为 1 月 1 日是每年的第 1 天,1 月 2 日是每年的第 2 天,依此类推。每个月的天数与现行公元纪年法(格里高利历)一致。
date.length == 10
date[4] == date[7] == ‘-’,其他的 date[i] 都是数字。
date 表示的范围从 1900 年 1 月 1 日至 2019 年 12 月 31 日。
2.分析
思路:
(1)这道题其实就是累加当年1月到给定日期的天数,取二月份天数时注意平年闰年的判断即可。
3.代码
public int dayOfYear(String date) {
//每个月的天数
int[] daysOfMonths = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int year = Integer.parseInt(date.substring(0,4));
int month = Integer.parseInt(date.substring(5,7));
int day = Integer.parseInt(date.substring(8));
int i,dates = 0;
for(i = 1;i < month;i++){
//2月份闰年29天
if(i == 2){
dates += isLeapYear(year) ? 29 : 28;
continue;
}
dates += daysOfMonths[i];
}
return dates += day;
}
private boolean isLeapYear(int i){
return (i % 400 == 0) || (i % 4 == 0 && i % 100 != 0);
}
三、日期之间隔几天
1.题目
请你编写一个程序来计算两个日期之间隔了多少天。
日期以字符串形式给出,格式为 YYYY-MM-DD,如示例所示。
给定的日期是 1971 年到 2100 年之间的有效日期。
2.分析
思路:
(1)因为给定的两个日期 date1 和 date2 年份谁大谁小是不确定的,所以直接求两个日期之间的间隔天数会比较麻烦。
(2)所以转换一个思路:分别求两个日期相对于同一个日期的间隔天数,然后两个天数相减就是两个日期的间隔天数。
(3)因为这里给定的日期在1971年到2100年之间,所以只需要计算两个日期分别与1971年1月1日的间隔天数,再相减即可。
3.代码
public int daysBetweenDates(String date1, String date2) {
//每个月的天数
int[] daysOfMonths = {0,31,28,31,30,31,30,31,31,30,31,30,31};
//date1转换成数字
int year1 = Integer.parseInt(date1.substring(0,4));
int month1 = Integer.parseInt(date1.substring(5,7));
int day1 = Integer.parseInt(date1.substring(8));
//date2转换成数字
int year2 = Integer.parseInt(date2.substring(0,4));
int month2 = Integer.parseInt(date2.substring(5,7));
int day2 = Integer.parseInt(date2.substring(8));
//计算两个日期距离1971年1月1日有多少天
int dates1 = dayFrom1971(daysOfMonths,year1,month1,day1);
int dates2 = dayFrom1971(daysOfMonths,year2,month2,day2);
return Math.abs(dates1 - dates2);
}
private int dayFrom1971(int[] daysOfMonths,int year,int month,int day){
//计算指定日期离19710101经过了多少天
int i,dates = 0;
for(i = 1971;i < year;i++){
if(isLeapYear(i)){
dates += 366;
continue;
}
dates += 365;
}
for(i = 1;i < month;i++){
//2月份闰年29天
if(i == 2){
dates += isLeapYear(year) ? 29 : 28;
continue;
}
dates += daysOfMonths[i];
}
dates += (day - 1);
return dates;
}
private boolean isLeapYear(int i){
return (i % 400 == 0) || (i % 4 == 0 && i % 100 != 0);
}