问题描述
该问题主要解决已知起始时间和延续时长求总天数。
比如:起始日期为2019.9.1,已知期限为三个月,那么终止时间为2019.12.1。根据以上来求这三个月到底有多长时间。
解决思路
这道题的本质在于平年闰年的判断和日期循环规律的掌握和应用。以三个月为例,我们需要注意的关键点有一下几点:
1、这三个月是否是同一年份的三个月;
2、如果不是同一年的三个月需要判断改日期的下一年是平年还是闰年;
3、在月份数加三的时候,会产生超过12的月份数,此时应该如何处理;
4、虽然说是一共三个月,但是实际计算的时候需要考虑四个月每一个月具体有多少天;
根据以上关键点,可以得出以下的思维导图(以三个月为例):
具体过程
1、在类中定义两个数组分别表示平年表和闰年表
public int[] a={0,31,29,31,30,31,30,31,31,30,31,30,31}; //闰年月份表 a[i]=x表示i月有x天(其中a[0]和b[0]没有使用)
public int[] b={0,31,28,31,30,31,30,31,31,30,31,30,31}; //平年月份表
(其实这里a[i]表示第i+1月会在后面省去很多不必要的麻烦,但是这里我为了逻辑清晰就直接用a[i]表示第i月)
2、后续就是用if_else语句判断年月的类型,然后根据年月类型进行相应计算了。具体条件判断分支可参考我上面那张思维导图。
该类对应的接口如下:
public interface CalendarInterface {
int getYear();
void setYear(int year);
int getMonth();
void setMonth(int month);
int getDay();
void setDay(int day);
int getMyDays(int category);
String getEndDate(int category);
具体代码如下:
public class MyCalendar implements CalendarInterface {
public static int THREE_MONTH=3;
public static int SIX_MONTH=6;
public static int ONE_YEAR=12;
public int[] a={0,31,29,31,30,31,30,31,31,30,31,30,31}; //闰年月份表 a[i]=x表示i月有x天(其中a[0]和b[0]没有使用)
public int[] b={0,31,28,31,30,31,30,31,31,30,31,30,31}; //平年月份表
private int year;
private int month;
private int day;
public MyCalendar() {
}
public MyCalendar(Calendar now) {
this.year=now.get(Calendar.YEAR);
this.month=now.get(Calendar.MONTH)+1;
this.day=now.get(Calendar.DAY_OF_MONTH);
}
@Override
public int getYear() {
return year;
}
@Override
public void setYear(int year) {
this.year = year;
}
@Override
public int getMonth() {
return month;
}
@Override
public void setMonth(int month) {
this.month = month;
}
@Override
public int getDay() {
return day;
}
@Override
public void setDay(int day) {
this.day = day;
}
@Override
public int getMyDays(int category) { //已知下单时间计算出总天数
int num;
//System.out.println(year+"-"+month+"-"+day);
if(category==THREE_MONTH) {
num=getThDays(year,month,day);//三个月产品
}else {
if(category==SIX_MONTH) {
num=getSiDays(year, month, day);//六个月产品
}else {
num=getOnyDays(year, month, day);//一年产品
}
}
return num;
}
@Override
public String getEndDate(int category) {
String endDate="";
if(category==THREE_MONTH) {
endDate+=getThDate(year, month, day);
}else {
if(category==SIX_MONTH) {
endDate+=getSiDate(year, month, day);
}else {
endDate+=getOnyDate(year, month, day);
}
}
return endDate;
}
private int getThDays(int year,int month,int day) {//形参为起始日期
int num=0;
if(year%4==0&&year%100!=0) { //普通闰年
if(month<=9) { //四个月都包含在当前年份;9=12-3
for(int i=month;i<=month+3;i++) {
num+=getEveDay(i, month, month+3, a);
// System.out.println("eve:"+getEveDay(i, month, month+3, a));
}
}else { //四个月跨越两个年份,那么闰年的第二年一定是平年
for(int i=month;i<=month+3;i++) {
if(i<=12) {
num+=getEveDay(i, month, month+3, a);
// System.out.println("eve:"+getEveDay(i, month, month+3, a));
}else {
num+=getEveDay(i%12, month, (month+3)%12, b);
// System.out.println("eve:"+getEveDay(i%12, month, (month+3)%12, b));
}
}
}
}else { //平年
if(month<=9) { //四个月都包含在当前年份
for(int i=month;i<=month+3;i++) {
num+=getEveDay(i, month, month+3, b);
// System.out.println("eve:"+getEveDay(i, month, month+3, b));
}
}else { //四个月跨越两个年份,那么平年的第二年可能是平年也可能是闰年
if((year+1)%4==0&&(year+1)%100!=0) { //第二年为闰年
for(int i=month;i<=month+3;i++) {
if(i<=12) {
num+=getEveDay(i, month, month+3, b);
// System.out.println("eve:"+getEveDay(i, month, month+3, b));
}else {
num+=getEveDay(i%12, month, (month+3)%12, a);
// System.out.println("eve:"+getEveDay(i%12, month, (month+3)%12, a));
}
}
}else { //第二年还为平年
for(int i=month;i<=month+3;i++) {
if(i<=12) {
num+=getEveDay(i, month, month+3, b);
// System.out.println("eve:"+getEveDay(i, month, month+3, b));
}else {
num+=getEveDay(i%12, month, (month+3)%12, b);
// System.out.println("eve:"+getEveDay(i%12, month, (month+3)%12, b));
}
}
}
}
}
return num;
}
private int getSiDays(int year,int month,int day) {//六个月
int num=0;
if(year%4==0&&year%100!=0) { //普通闰年
if(month<=6) { //六个月都包含在当前年份
for(int i=month;i<=month+6;i++) {
num+=getEveDay(i, month, month+6, a);
// System.out.println("eve:"+getEveDay(i, month, (month+6)%12, a));
}
}else { //六个月跨越两个年份,那么闰年的第二年一定是平年
for(int i=month;i<=month+6;i++) {
if(i<=12) {
num+=getEveDay(i, month, month+6, a);
// System.out.println("eve:"+getEveDay(i, month, month+6, a));
}else {
num+=getEveDay(i%12, month, (month+6)%12, b);
// System.out.println("eve:"+getEveDay(i%12, month, (month+6)%12, b));
}
}
}
}else { //平年
if(month<=6) { //六个月都包含在当前年份
for(int i=month;i<=month+6;i++) {
num+=getEveDay(i, month, month+6, b);
// System.out.println("eve:"+getEveDay(i, month, month+6, b));
}
}else { //六个月跨越两个年份,那么平年的第二年可能是平年也可能是闰年
if((year+1)%4==0&&(year+1)%100!=0) { //第二年为闰年
for(int i=month;i<=month+6;i++) {
if(i<=12) {
num+=getEveDay(i, month, month+6, b);
// System.out.println("eve:"+getEveDay(i, month, month+6, b));
}else {
num+=getEveDay(i, month, (month+6)%12, a);
// System.out.println("eve:"+getEveDay(i, month, (month+6)%12, a));
}
}
}else { //第二年为平年
for(int i=month;i<=month+6;i++) {
if(month<=12) {
num+=getEveDay(i, month, month+6, b);
// System.out.println("eve:"+getEveDay(i, month, month+6, b));
}else {
num+=getEveDay(i%12, month, (month+6)%12, b);
// System.out.println("eve:"+getEveDay(i%12, month, (month+6)%12, b));
}
}
}
}
}
return num;
}
private int getOnyDays(int year,int month,int day) {//一年
int num=0;
if(year%4==0&&year%100!=0) {//起始年份为闰年,第二年一定是平年
for(int i=month;i<=month+12;i++) {
if(i<=12) {
num+=getEveDayplus(i, month, a, 0);
System.out.println("eve:"+getEveDayplus(i, month, a, 0));
}else {
if(i==24) {
num+=day;
System.out.println("eve:"+day);
}else {
num+=getEveDayplus(i%12, month, b, 1);
System.out.println("eve:"+getEveDayplus(i%12, month, b, 1));
}
}
}
}else { //起始年份为平年,第二年可能为闰年也可能为平年
if((year+1)%4==0&&(year+1)%100!=0) {//第二年为闰年
for(int i=month;i<=month+12;i++) {
if(i<=12) {
num+=getEveDayplus(i, month, b, 0);
System.out.println("eve:"+getEveDayplus(i, month, b, 0));
}else {
if(i==24) {
num+=day;
System.out.println("eve:"+day);
}else {
num+=getEveDayplus(i%12, month, a, 1);
System.out.println("eve:"+getEveDayplus(i%12, month, a, 1));
}
}
}
}else { //第二年还是平年
for(int i=month;i<=month+12;i++) {
if(i<=12) {
num+=getEveDayplus(i, month, b, 0);
System.out.println("eve:"+getEveDayplus(i, month, b, 0));
}else {
if(i==24) {
num+=day;
System.out.println("eve:"+day);
}else {
num+=getEveDayplus(i%12, month, b, 1);
System.out.println("eve:"+getEveDayplus(i%12, month, b, 1));
}
}
}
}
}
return num;
}
private int getEveDay(int month,int start,int end,int[] c) { //非一年的产品
if(month==start)
return c[month]-day;
else {
if(month==end)
return day;
else
return c[month];
}
}
private int getEveDayplus(int month,int start,int[] c,int flag) {
if(month==start) {
if(flag==0)
return c[month]-day;
else
return day;
}else {
return c[month];
}
}
private String getThDate(int year,int month,int day) {
int endyear,endmonth;
int endday=day;
if(month<=9) {
endyear=year;
endmonth=month+3;
}else {
endyear=year+1;
endmonth=(month+3)%12;
}
return endyear+"-"+endmonth+"-"+endday;
}
private String getSiDate(int year,int month,int day) {
int endyear,endmonth;
int endday=day;
if(month<=6) {
endyear=year;
endmonth=month+6;
}else {
endyear=year+1;
endmonth=(month+6)%12;
}
return endyear+"-"+endmonth+"-"+endday;
}
private String getOnyDate(int year,int month,int day) {
int endyear=year+1;
int endmonth=month;
int endday=day;
return endyear+"-"+endmonth+"-"+endday;
}
}