有误差的字符串型时间比较方法String.compareTo

最近因为一个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("不在区间里面");
        }
    }
}

结果输出:
有误差的字符串型时间比较方法String.compareTo_第1张图片
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码也越大,在长度相等的情况下,就可以比较正确。

你可能感兴趣的:(工作问题,java)