java - 按 yyyymmdd 整数计算日差时结果不一致

标签 java date

我为这个奇怪的问题苦苦挣扎了一整天。问题是这样的:

下面有三行代码

        float y=Float.parseFloat(line[1]);
        int dayDiff = DateUtil.countDay(lineDateid,testDateIdBelongTo,true);//
        dataBelongTo.set(dayDiff,y);// Some error thrown from here, so I set a break point here and watch

我在第三行发现了一些奇怪的 IndexOutOfBound Exception,所以我开始调试(断点条件为 (dayDiff<0) || (dayDiff>=dataBelongTo.size()) )并注意到奇怪的结果,下面是屏幕截图:

enter image description here

我注意到 dayDiff 返回了意外的结果,并且 DateUtil.countDay似乎返回不一致的结果,所以我在主方法中调试它:

    try {
        System.out.println("begins");
        for(int i=0; i< 500000;i++){//run 500000 times
           int dateDiff = DateUtil.countDay(20150604,20150601,true);
            if(dateDiff!=3) System.out.println(dateDiff);
        }
        System.out.println("ends");
    } catch (Exception e) {
        e.printStackTrace();
    }

但是结果是对的!每次都返回3(没有错误结果打印)!!

这是我的代码 countDay

public static int countDay(int day1, int day2 , boolean distinguish ) {
    int  res = 0;
    try {
        Date date1 = formatDate.parse(day1+"");
        Date date2 = formatDate.parse(day2 + "");
        long diff = date1.getTime() - date2.getTime();
        res = (int)TimeUnit.MILLISECONDS.toDays(diff);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    if(!distinguish)
        res =Math.abs(res);

    return res;
}

formatDate

public static final SimpleDateFormat formatDate = new SimpleDateFormat("yyyyMMdd");

PS:我使用的是 JDK 7,问题代码在 Tomcat 上运行,数据(param)来自 MySQL 。

这是该问题部分的更完整代码,仅在某些情况下才会出现问题。

    for(String[] line : tableData){//for each records in the database
        int lineDateid = Integer.parseInt(line[0]);//0 index is dateid
        int testDateIdBelongTo = 0;//init with 0
        JSONArray dataBelongTo = null;//data array 

        //below , need to assgin dataBelongTo and testDateIdBelongTo
        for(int i=0;i<testDates.length;i++){
            int testDate =testDates[i];
            NumberInterval interval = intervals.get(i);
            if(interval.isIn(lineDateid)){
                dataBelongTo = datas.get(i);
                testDateIdBelongTo=testDate;
                break;
            }
        }
        if(testDateIdBelongTo==0) throw new IllegalStateException("data errors, no matched dataid");


        float y=Float.parseFloat(line[1]);
        int dayDiff = DateUtil.countDay(lineDateid,testDateIdBelongTo,true);
        dataBelongTo.set(dayDiff,y);
    }

最佳答案

最可能的原因是:

public static final SimpleDateFormat formatDate = new SimpleDateFormat("yyyyMMdd");

SimpleDateFormat 不是线程安全的,Tomcat 可能从多个线程调用此单个实例。

简单修复:删除静态变量并更改代码:

public static int countDay(int day1, int day2 , boolean distinguish ) {
  SimpleDateFormat formatDate = new SimpleDateFormat("yyyyMMdd");
  //rest of your code
}

如果性能是一个问题,您可以缓存格式化程序,但这将使代码变得更加复杂(正如注释中所述,在管理自己的线程池的应用程序服务器中可能不建议使用 ThreadLocals 的典型方法)。

您还可以重写代码以不使用 SimpleDateFormat - 这可能会更简单。

顺便说一句,如果运行代码的计算机的默认时区发生 DST 更改,您当前的计算可能会被破坏。

关于java - 按 yyyymmdd 整数计算日差时结果不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30663316/

相关文章:

javascript - 如何验证日期输入?

java - 我如何判断一个日期是否在 Java 中的某个时间之前?

java - 无法应用插件 "com.google.gms.google-services"

MySQL 查询返回每个月之前创建的所有行

python - 在 Python 中按创建日期排序文件列表时出现奇怪的错误

sql - 为什么 SELECT DISTINCT 返回两次相同的值?

带冒号和不带冒号的 Java 类路径 ":"

java - jooq 为 Oracle 返回没有时间的日期

java - Java 9 中文件夹/目录名称为模块名称是否存在问题?

java - 如何在Java中查找一年的总周数?