最近因为一个bug看公司的老项目,发现了这个以下这个代码:
/**
* 返回间隔秒数,获取指定时间内的设置,如果不在指定时间内,返回为null
* @param conf 配置信息类
* @param time 目前是HH:mm:ss,与start和end并不统一,start和end是HH:mm
* @return
*/
private String getDistanceSecond(RepostUser conf,String time)
{
if (conf.getStart1()!=null && !conf.getStart1().equals("") && time.compareTo(conf.getStart1()) >= 0 && time.compareTo(conf.getEnd1()) <= 0)
{
return (conf.getDistanceSecond()+ conf.getDistanceTime()*60)+","+conf.getNum();
}
else if (conf.getStart2() != null && conf.getStart2() != null && !conf.getStart2().equals("") && time.compareTo(conf.getStart2()) >= 0 && time.compareTo(conf.getEnd2()) <= 0)
{
return conf.getDistanceSecond2()+ conf.getDistanceTime2()*60+","+conf.getNum2();
}
else if (conf.getStart3()!=null && conf.getStart3() != null && !conf.getStart3().equals("") && time.compareTo(conf.getStart3()) >= 0 && time.compareTo(conf.getEnd3()) <= 0)
{
return conf.getDistanceSecond3()+ conf.getDistanceTime3()*60+","+conf.getNum3();
}
else if (conf.getStart4() != null && conf.getStart4() != null && !conf.getStart4().equals("") && time.compareTo(conf.getStart4()) >= 0 && time.compareTo(conf.getEnd4()) <= 0)
{
return conf.getDistanceSecond4()+ conf.getDistanceTime4()*60+","+conf.getNum4();
}
else if (conf.getStart5()!=null && conf.getStart5() != null && !conf.getStart5().equals("") && time.compareTo(conf.getStart5()) >= 0 && time.compareTo(conf.getEnd5()) <= 0)
{
return conf.getDistanceSecond5()+conf.getDistanceTime5()*60+","+conf.getNum5();
}
return null;//表示不在范围内
}
这里的start和end,格式是HH:mm
time则是HH:mm:ss
这里start和end ,为什么和time的格式不一样,先不管,就当start和end的秒数为00去处理。
按照上面的,我写了一个测试程序。
public class MainApp {
public static void main(String[] args) {
String time="16:40:00";
String start="16:35";
String end="16:40";
if(time.compareTo(start) >= 0 && time.compareTo(end) <= 0){
System.out.println("在区间里面");
}else{
System.out.println("不在区间里面");
}
}
}
结果输出:
OK,那么这么说,原来的代码是不包含边界的吧?那么我再试试time=16:35:00
public class MainApp {
public static void main(String[] args) {
String time="16:35:00";
String start="16:35";
String end="16:40";
if(time.compareTo(start) >= 0 && time.compareTo(end) <= 0){
System.out.println("在区间里面");
}else{
System.out.println("不在区间里面");
}
}
}
结果输出:
在区间里面
!!!,那么这样就不对了,边界要么包含,要么都不包含,你给我一个包含一个不包含是什么意思?
其实这个使用的是String的compareTo方法来比较,这个方法是这样的:
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
首先compareTo会比较字符串每个字符的ASCII码的大小,如果不等,那么则返回他们之间的差值。否则继续找到不等的字符。
如果在Math.min(len1,len2)以内的字符,都是相同的。
那么直接返回他们字符串长度的差值。
所以觉得这个方法可以比较时间大小?我的答案是不一定,如果都是相同的长度的话,理论上确实是没问题的,但是你给我弄成长度不一样了,我也没办法,只好用一个比较准确的时间比较。
于是我使用JDK8提供的时间api(在java.time的包里面)进行重构。
public class MainApp {
public static void main(String[] args) {
String time="16:35:00";
String start="16:35";
String end="16:40";
LocalTime time2=LocalTime.parse(time,DateTimeFormatter.ofPattern("HH:mm:ss"));
LocalTime time3=LocalTime.parse(start,DateTimeFormatter.ofPattern("HH:mm"));
LocalTime time4=LocalTime.parse(end,DateTimeFormatter.ofPattern("HH:mm"));
System.out.println(time3);
if (time2.compareTo(time3) >= 0 && time2.compareTo(time4) <= 0) {
System.out.println("在区间里面");
}else{
System.out.println("不在区间里面");
}
}
}
这样的话会比较符合正常思维。
但是如果嫌 生成了比较多的对象,我觉得可以走一下邪门路线。直接将start和end的后面加上:00就好了。
public class MainApp {
public static void main(String[] args) {
String time="16:40:00";
String start="16:35";
String end="16:40";
if(start.length()==5){
start+=":00";
}
if(end.length()==5){
end+=":00";
}
if (time.compareTo(start) >= 0 && time.compareTo(end) <= 0) {
System.out.println("在区间里面");
}else{
System.out.println("不在区间里面");
}
这样也是可以,因为数字越大,ASCII码也越大,在长度相等的情况下,就可以比较正确。