Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4565323
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: Java

2015-07-01 12:16:17

       原来以为,求两个时间之日期差应该不是问题,直到有一天...。 我曾经辅导过的一位开发员向我求教,我还不以为很难,尝试用Calendar/GregorianCalendar类来计算,看起来代码太复杂,放弃。苦想半小时,最后想出一句话,写出来在MSN上发给他。当时的感觉路子很野,上不了台面。这句话也是下面要介绍的简洁方法。
再后来,我的一位前同事发来邮件,说起网上一大牛发布的blog,是一个牛人数落Java标准库的,挺有意思。需求很简单:有两个Date型的变量
(a, b),如何计算两者相隔的天数?你有简单的解决方案吗?(据这个牛人说,还是很麻烦的哦)
看了大牛的方法,暗地思忖:既然Java标准库不能解决,我的方法不是很简单吗?!我的底气腾腾往上涨。

====
我的方法:

public long differ(Date date1, Date date2) 

    
//return date1.getTime() / (24*60*60*1000) - date2.getTime() / (24*60*60*1000); 
    return date2.getTime() / 86400000 - date1.getTime() / 86400000;  //用立即数,减少乘法计算的开销
}
 

 

问题分析:求日期差,重要的是时间对象的日期部分,与时分秒没有关系。所以问题的关键是过滤掉时分秒,保留日期部分。干的活象低通滤波器,滤掉高频杂波,保留低频信号。
解决思路:一天的秒数是24*60*60*1000=86400000=Senconds。时间对象date1.getTime()是自1970年1月1日零点以来的秒数,用它整除以Seconds
,就得到自1970年1月1日以来的天数。注意这里用的是整除符号,时分秒被过滤掉了。对date2也施行同样的操作,得到date2的天数。date2的天数减去date1的天数,所得结果就是日期差。
举例来说,用最简单的例子,假设date1等于1970年1月5日15点整,date2等于1970年1月6日14点整。date1整除以seconds的结果是4,date2整除以
seconds的结果是5,date2与date1相差5-4=1天,与我们的预期相符。

====
我的同事Kun给出了方法:获取二者的milliseconds相减,然后/24/60/60。
这个方法应该是不正确的。因为秒数相减,得到的是二者的时间差,并没有滤掉时分秒。
计算结果:用刚才的例子验算一下,date2.getTime() - date1.getTime() 等于相当于23小时的秒数,再整除以seconds,结果是0天,与预期的1
天不相符。
Kun的方法与正确方法的区别在于:先做减法,还是先做整除法。


====
同事在网上找到的方法:

SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date
= myFormatter.parse("2003-05-1"); 
java.util.Date mydate
= myFormatter.parse("1899-12-30");
long  day=(date.getTime()-mydate.getTime())/(24*60*60*1000);
out.println(day);


结果应该是正确的,它根本就没有时分秒,有了时分秒与Kun的方法等价。不过用起来会很麻烦,因为要先得到字符串的日期,才能用它。

====
最后看看大牛的方法:
大牛博客地址:
http://blog.csdn.net/rmartin/archive/2006/12/22/1452867.aspx

  private int daysBetween(Date now, Date returnDate) {
    Calendar cNow 
= Calendar.getInstance();
    Calendar cReturnDate 
= Calendar.getInstance();
    cNow.setTime(now);
    cReturnDate.setTime(returnDate);
    setTimeToMidnight(cNow);
    setTimeToMidnight(cReturnDate);
    
long todayMs = cNow.getTimeInMillis();
    
long returnMs = cReturnDate.getTimeInMillis();
    
long intervalMs = todayMs - returnMs;
    
return millisecondsToDays(intervalMs);
  }


  
private int millisecondsToDays(long intervalMs) {
    
return (int) (intervalMs / (1000 * 86400));
  }


  
private void setTimeToMidnight(Calendar calendar) {
    calendar.set(Calendar.HOUR_OF_DAY, 
0);
    calendar.set(Calendar.MINUTE, 
0);
    calendar.set(Calendar.SECOND, 
0);
  }

 

看起来很复杂吧,没有求证过,应该是正确的吧!

实际作者方法是错误的:

  1. import java.util.Date;

  2. public class Atest {
  3.     public long duration(Date date1, Date date2) {
  4.         long d1 = date1.getTime();
  5.         long d2 = date2.getTime();
  6.         System.out.printf("%s, %s\n", d1, d2);
  7.         System.out.printf("%s, %s\n", d1/86400000, d2/86400000);
  8.         return d2/86400000 - d1/86400000;
  9.     }

  10.     private void comparation() {
  11.         Date date2 = new Date();
  12.         Date date1 = new Date();
  13.         date1.setHours(2);
  14.         System.out.println(date1);
  15.         System.out.println(date2);

  16.         long durationDays = duration(date1, date2);
  17.         System.out.println(durationDays);
  18.     }

  19.     public static void main(String[] args) {
  20.         Atest obj = new Atest();
  21.         obj.comparation();
  22.     }

  23. }
结果:
Wed Jul 01 02:01:40 CST 2015
Wed Jul 01 15:01:40 CST 2015
1435687300647, 1435734100647
16616, 16617
1




阅读(1392) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~