发现
Calendar的比较时基于毫秒的,但是calendar使用set方法只能精确到秒,如果用Calendar进行同一秒的比较,可能会有…
会有如下代码:
1 | public class MainActivity extends AppCompatActivity{ |
每次点击时的结果都是不尽相同的。为什么?
探索
我们尝试新增如下日志
1 |
|
可以看到打出的日志(这里就不贴日志了,可以自行尝试)有毫秒级的差别,也就是:
- calStart的真实时间是2008.01.01 00:00:00.xxx
(注:xxx是Calendar calStart = Calendar.getInstance();
时的毫秒数) - calEnd的真实时间的毫秒数则是点击瞬间的毫秒数
- 由于毫秒数的不确定性,导致时而calStart大于、时而小于、时而等于calEnd
解决方案
解决方案有两种:
在使用到Calendar的类中定义一个基础Calendar
1
2
3
4
5
6
7
8
9Calendar calBase = Calendar.getInstance();
Calendar calStart = Calendar.getInstance();
calStart.setTime(calBase.getTime());
calStart.set(2008,0,1,0,0,0);
Calendar calEnd = Calendar.getInstance();
calEnd.setTime(calBase.getTime());
calEnd.set(2008,0,1,0,0,0);千万别写成如下:
1
2
3
4
5
6//那我还得和你解释数据是怎么存储在堆和栈中... pass
Calendar calStart = calBase;
calStart.set(2008,0,1,0,0,0);
Calendar calEnd = calBase;
calStart.set(2008,0,1,0,0,0);这种写法其实都是在操作calBase,都不能算是另外操作calStart和calEnd.可尝试如下代码看看效果:
1
2
3
4
5
6
7
8
9
10
11
12
13public void initTry() {
Calendar calBase = Calendar.getInstance();
Calendar calStart = calBase;
calBase.set(2008,1,1,0,0,0);
Calendar calEnd = calBase;
calEnd.set(2009,1,1,0,0,0);
Log.i(TAG,"log\nCalendar0-->"+calStart.getTime().toString()+"\nCalendar1-->"+calEnd.getTime().toString());
}
//日志
//log
// Calendar0-->Sun Feb 01 00:00:00 GMT+08:00 2009
// Calendar1-->Sun Feb 01 00:00:00 GMT+08:00 2009比较时根据精确度进行比较:
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
50public class CalendarUtils{
public boolean isNotBefore(Calendar calStart, Calendar calEnd, @NotNull CalendarType type) {
// int startYear = calStart.get(Calendar.YEAR);
// int endYear = calEnd.get(Calendar.YEAR);
// if (startYear <= endYear) return false;
if (ifBefore(calStart,calEnd,Calendar.YEAR)) return false;
if (CalendarType.YEAR == type) return true;
// int startMonth = calStart.get(Calendar.MONTH);
// int endMonth = calEnd.get(Calendar.MONTH);
// if (startMonth <= endMonth) return false;
if (ifBefore(calStart,calEnd,Calendar.MONTH)) return false;
if (CalendarType.MONTH == type) return true;
// int startDay = calStart.get(Calendar.DAY_OF_MONTH);
// int endDay = calEnd.get(Calendar.DAY_OF_MONTH);
// if (startDay <= endDay) return false;
if (ifBefore(calStart,calEnd,Calendar.DAY_OF_MONTH)) return false;
if (CalendarType.DAY == type) return true;
// int startHour = calStart.get(Calendar.HOUR_OF_DAY);
// int endHour = calEnd.get(Calendar.HOUR_OF_DAY);
// if (startHour <= endHour) return false;
if (ifBefore(calStart,calEnd,Calendar.HOUR_OF_DAY)) return false;
if (CalendarType.HOUR == type) return true;
// int startMinute = calStart.get(Calendar.MINUTE);
// int endMinute = calEnd.get(Calendar.MINUTE);
// if (startMinute <= endMinute) return false;
if (ifBefore(calStart,calEnd,Calendar.MINUTE)) return false;
if (CalendarType.MINUTE == type) return true;
// int startSecond = calStart.get(Calendar.SECOND);
// int endSecond = calEnd.get(Calendar.SECOND);
// if (startSecond <= endSecond) return false;
if (ifBefore(calStart,calEnd,Calendar.SECOND)) return false;
if (CalendarType.SECOND == type) return true;
return calStart.getTimeInMillis() >= calEnd.getTimeInMillis();
}
//后续做了变更,封装此方法,方便调整代码
private boolean isBefore(Calendar calStart,Calendar calEnd,int calendarField){
return calStart.get(calendarField)<=calEnd.get(calendarField);
}
public enum CalendarType {
YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLIS_SECOND
}
}
结语
写代码时务必要注重细节~
另:(免责声明)以上代码未在编辑器上校验过,纯手打~
如有问题,请根据实际情况修改代码
如有疑问,评论区见~