java: Calculate interval between two dates correctly by Calendar class

When developing an Android application, it is occasionally necessary to use a function that prompts the user to use the number of days. From the implementation point of view, it is nothing more than persistently storing the time firstTime (through SharedPreferences, xml, sqlite, etc.) of the user's first use of the application. When using the application, the time presentTime is obtained at this time, and the number of days between the two times is calculated.

When two time variables are obtained, the method of calculating the date interval on the Internet is usually like this (the difference between the milliseconds of the two times is obtained and then processed):

 

  1. long beginTime = beginDate.getTime();   
  2. long endTime = endDate.getTime();   
  3. long betweenDays = (long)((endTime - beginTime) / (1000 * 60 * 60 *24));   
long beginTime = beginDate.getTime();
long endTime = endDate.getTime();
long betweenDays = (long)((endTime - beginTime) / (1000 * 60 * 60 *24));

Let's test two special cases:

 

Case 1:

 

  1. Calendar beginCalendar = Calendar.getInstance();  
  2. beginCalendar.set( 2017, 2, 3, 1, 0, 0);       //Set the time to March 3, 2017 1:0:0   
  3. Calendar endCalendar = Calendar.getInstance();  
  4. endCalendar.set( 2017, 2, 3, 14, 0, 0);        //Set the time to 14:0:0 on March 3, 2017   
  5. long beginTime = beginCalendar.getTime().getTime();   
  6. long endTime = endCalendar.getTime().getTime();   
  7. long betweenDays = (long)((endTime - beginTime) / (1000 * 60 * 60 *24));   
  8. System.out.println(betweenDays);         //The output is 0  
Calendar beginCalendar = Calendar.getInstance();
beginCalendar.set(2017,2,3,1,0,0); //Set the time to 1:0:0 on March 3, 2017
Calendar endCalendar = Calendar.getInstance();
endCalendar.set(2017,2,3,14,0,0); //Set the time to 14:0:0 on March 3, 2017
long beginTime = beginCalendar.getTime().getTime();
long endTime = endCalendar.getTime().getTime();
long betweenDays = (long)((endTime - beginTime) / (1000 * 60 * 60 *24));
System.out.println(betweenDays); //The output is 0

Case 2:

 

 

  1. Calendar beginCalendar = Calendar.getInstance();  
  2. beginCalendar.set( 2017, 2, 2, 20, 20, 20);<span style= "white-space: pre;"> </span> //Set the time to 20:20 on March 2, 2017: 20    
  3. Calendar endCalendar = Calendar.getInstance();  
  4. endCalendar.set( 2017, 2, 3, 10, 10, 10);      //Set the time to 10:10:10 on March 3, 2017  
  5. long beginTime = beginCalendar.getTime().getTime();   
  6. long endTime = endCalendar.getTime().getTime();   
  7. long betweenDays = (long)((endTime - beginTime) / (1000 * 60 * 60 *24));   
  8. System.out.println(betweenDays);         //The output is 0, but it should be 1  
Calendar beginCalendar = Calendar.getInstance();
beginCalendar.set(2017,2,2,20,20,20); 		//Set the time to 20:20:20 on March 2, 2017  
Calendar endCalendar = Calendar.getInstance();
endCalendar.set(2017,2,3,10,10,10); //Set the time to 10:10:10 on March 3, 2017
long beginTime = beginCalendar.getTime().getTime();
long endTime = endCalendar.getTime().getTime();
long betweenDays = (long)((endTime - beginTime) / (1000 * 60 * 60 *24));
System.out.println(betweenDays); //The output is 0, but it should be 1

 

It can be seen that the code output is 0 for the case where the time interval should be 1. The reason is because when the difference between the milliseconds of the two dates is less than the milliseconds of a day (1000 *60*60*24) , even if the two dates span one day, the result will become 0 after coercion. From the figure below, you can see two cases where the difference in milliseconds is less than one day.

Case 1 (the difference in milliseconds is less than one day and does not span days, the date interval should be 0):

Case 2 (difference in milliseconds is less than one day and across days, date interval should be 1):

So the above code needs to be improved so that it can recognize the special case of crossing the sky:

 

  1. public static int getTimeDistance(Date beginDate , Date endDate ) {  
  2.     Calendar beginCalendar = Calendar.getInstance();  
  3.     beginCalendar.setTime(beginDate);  
  4.     Calendar endCalendar = Calendar.getInstance();  
  5.     endCalendar.setTime(endDate);  
  6.     long beginTime = beginCalendar.getTime().getTime();  
  7.     long endTime = endCalendar.getTime().getTime();  
  8.     int betweenDays = ( int)((endTime - beginTime) / ( 1000 *  60 *  60 * 24)); //First calculate the difference between the milliseconds of the two times is greater than the number of days in a day  
  9.       
  10.     endCalendar.add(Calendar.DAY_OF_MONTH, -betweenDays); //Subtract these days from endCalendar, and convert the problem to a situation where the difference between the milliseconds of the two times is less than one day  
  11.     endCalendar.add(Calendar.DAY_OF_MONTH, - 1); // subtract 1 day from endCalendar  
  12.     if(beginCalendar.get(Calendar.DAY_OF_MONTH)==endCalendar.get(Calendar.DAY_OF_MONTH)) //Compare whether the DAY_OF_MONTH of the two dates are equal  
  13.         return betweenDays +  1;  //Equal means that the day is indeed crossed  
  14.     else  
  15.         return betweenDays +  0;  //Inequality means that the day is not crossed  
  16. }  
public static int getTimeDistance(Date beginDate , Date endDate ) {
    Calendar beginCalendar = Calendar.getInstance();
    beginCalendar.setTime(beginDate);
    Calendar endCalendar = Calendar.getInstance();
    endCalendar.setTime(endDate);
    long beginTime = beginCalendar.getTime().getTime();
    long endTime = endCalendar.getTime().getTime();
    int betweenDays = (int)((endTime - beginTime) / (1000 * 60 * 60 *24));//First calculate the difference between the milliseconds of the two times is greater than the number of days in a day
    
    endCalendar.add(Calendar.DAY_OF_MONTH, -betweenDays);//Subtract these days from endCalendar and convert the problem to a situation where the difference between the milliseconds of the two times is less than one day
    endCalendar.add(Calendar.DAY_OF_MONTH, -1);//Subtract 1 day from endCalendar
    if(beginCalendar.get(Calendar.DAY_OF_MONTH)==endCalendar.get(Calendar.DAY_OF_MONTH))//Compare the DAY_OF_MONTH of the two dates are equal
        return betweenDays + 1; //Equal means that the day is indeed crossed
    else
        return betweenDays + 0; //Inequality means that the day is not crossed
}

There is a detail in the code that needs attention. I first use endCalendar.add(Calendar.DAY_OF_MONTH, -1), and then compare the DAY_OF_MONTH time values ​​of the two dates to determine the return value.

 

rather than directly

 

  1. return betweenDays + endCalendar.get(Calendar.DAY_OF_MONTH)-beginCalendar.get(Calendar.DAY_OF_MONTH);  
return betweenDays + endCalendar.get(Calendar.DAY_OF_MONTH)-beginCalendar.get(Calendar.DAY_OF_MONTH);

This is because there may be cross-month situations. For example, the date of beginCalendar is February 28, the date of endCalendar is March 1, and the value of endCalendar.get(Calendar.DAY_OF_MONTH)-beginCalendar.get(Calendar.DAY_OF_MONTH) will be -27 instead of 1 as expected. And using endCalendar.add(Calendar.DAY_OF_MONTH, -1), the Calendar class method will automatically convert the cross-month situation.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324938098&siteId=291194637