计算nextDay的实现

实现nextDay算法

1.题目要求

用户从键盘输入”2014/11/11”,然后输出该输入的下一天日期是多少.
要求很简单,看上去也不是很复杂,但是要考虑到闰年,月份进位等等问题.

2.思路分析

  • 用户输入合法性问题
  • nextDay的推算算法

我们先看第一个问题:
这个比较简单,我们可以使用正则表达式来匹配用户的输入,当然了,只是正则表达式可能还无法完全约束合法,我们可以继续针对个别的在正确的校验.

1
2
3
4
5
//使用分隔符'/'分割年月日
//年份可以使用09或者2009这样的形式 月份使用1或者01 日使用01或者1
//至少有一位 至多有两位
//则可以得到下面的匹配规则
String pattern = "^(([0-9][0-9])|([1-2][0,9][0-9][0-9]))\\/(([1-9])|(0[1-9])|(1[0-2]))\\/(([0-9])|([0-2][0-9])|(3[0-1]))$";

这样,就可以得到一个合法的类似于”2013/14/22”这样的字符串,但是我们发现,14月仍然是不合法的,仍需我们再次校验合法性.于是,可以封装三个函数:

1
2
3
4
5
6
7
8
9
10
11
public static boolean isLegalYear(int year) {
return year >= 1900 && year < 3000;
}

public static boolean isLegalMonth(int month) {
return month <= 12 && month > 0;
}

public static boolean isLegalDay(int month, int day) {
return mapDay.get(month).intValue() >= day;
}

这样,我们就可以得到一个正确合法的输入日期,然后就可以依照算法,计算下一天.

再看第二个问题:
算法说起来也比较简单,类似于一个加法器,只是各个位置上的进位法则不一样而已.

  • 将day自加1
    • 若day合法,返回该data
    • 若day不合法,day赋值为1,month自加1
      • 若month合法,返回该data
      • 若month不合法,month赋值为1,year自加,返回data

经过上述算法计算,即可得到正确的日期了.

3.具体实现

首先封装一个data数据类:

1
2
3
4
5
6
7
8
9
10
class MyData {
public MyData(int year, int month, int day) {
this.day = day;
this.month = month;
this.year = year;
}
public int year;
public int month;
public int day;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import java.util.*;
import java.util.regex.*;

public class NextDay{

public static Map<Integer, Integer> mapDay = new HashMap<Integer, Integer>(){
{
put(1, 31); put(2, 28); put(3, 31); put(4, 30);
put(5, 31); put(6, 30); put(7, 31); put(8, 31);
put(9, 30); put(10, 31); put(11, 30); put(12, 31);
}
};

public static void main(String[] args) {
MyData d = getNextData(getData());
System.out.println(d.year+"-"+d.month+"-"+d.day);
}

public static MyData getNextData(MyData data) {
data.day++;
if (isLegalDay(data.month, data.day)) {
return data;
} else {
data.day = 1;
data.month++;
if (isLegalMonth(data.month)) {
return data;
} else {
data.month = 1;
data.year++;
return data;
}
}
}

public static MyData getData() {
// get input from keyboard
Scanner s = new Scanner(System.in);
// month/day/year
String input = s.next();
// using Regular Expression to verify input
String pattern = "^(([0-9][0-9])|([1-2][0,9][0-9][0-9]))\\/(([1-9])|(0[1-9])|(1[0-2]))\\/(([0-9])|([0-2][0-9])|(3[0-1]))$";
Matcher m = Pattern.compile(pattern).matcher(input);
if (m.matches()) {
String[] data = input.split("/");
int year = Integer.parseInt(data[0]);
int month = Integer.parseInt(data[1]);
int day = Integer.parseInt(data[2]);
if (isLeapYear(year)) {
mapDay.put(2, 29);
}
if (isLegalYear(year) && isLegalMonth(month) && isLegalDay(month, day)) {
MyData d = new MyData(year, month, day);
return d;
} else {
System.out.println("your input is illegal!");
System.exit(-1);
return null;
}
} else {
System.out.println("your input format is worry!");
System.exit(-1);
return null;
}
}

public static boolean isLegalYear(int year) {
return year >= 1900 && year < 3000;
}

public static boolean isLegalMonth(int month) {
return month <= 12 && month > 0;
}

public static boolean isLegalDay(int month, int day) {
return mapDay.get(month).intValue() >= day;
}

public static boolean isLeapYear(int year) {
return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}
}