java 取时间差_用Java求两时间点之间日期差的简洁方法

原来以为,求两个时间之日期差应该不是问题,直到有一天...。 我曾经辅导过的一位开发员向我求教,我还不以为很难,尝试用Calendar/GregorianCalendar类来计算,看起来代码太复杂,放弃。苦想半小时,最后想出一句话,写出来在MSN上发给他。当时的感觉路子很野,上不了台面。这句话也是下面要介绍的简洁方法。

再后来,我的一位前同事发来邮件,说起网上一大牛发布的blog,是一个牛人数落Java标准库的,挺有意思。需求很简单:有两个Date型的变量(a, b),如何计算两者相隔的天数?你有简单的解决方案吗?(据这个牛人说,还是很麻烦的哦)

看了大牛的方法,暗地思忖:既然Java标准库不能解决,我的方法不是很简单吗?!我的底气腾腾往上涨。

====

我的方法:

None.gifpublic long differ(Date date1, Date date2)

ExpandedBlockStart.gif{

6a9c071a08f1dae2d3e1c512000eef41.png //return date1.getTime() / (24*60*60*1000) - date2.getTime() / (24*60*60*1000);

6a9c071a08f1dae2d3e1c512000eef41.png return date2.getTime() / 86400000 - date1.getTime() / 86400000;  //用立即数,减少乘法计算的开销

ExpandedBlockEnd.gif}

问题分析:求日期差,重要的是时间对象的日期部分,与时分秒没有关系。所以问题的关键是过滤掉时分秒,保留日期部分。干的活象低通滤波器,滤掉高频杂波,保留低频信号。

解决思路:一天的秒数是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的方法与正确方法的区别在于:先做减法,还是先做整除法。

====

同事在网上找到的方法:

None.gifSimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");

None.gifjava.util.Date date= myFormatter.parse("2003-05-1");

None.gifjava.util.Date mydate= myFormatter.parse("1899-12-30");

None.giflong  day=(date.getTime()-mydate.getTime())/(24*60*60*1000);

None.gifout.println(day);

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

ExpandedBlockStart.gif private int daysBetween(Date now, Date returnDate) {

6a9c071a08f1dae2d3e1c512000eef41.png    Calendar cNow = Calendar.getInstance();

6a9c071a08f1dae2d3e1c512000eef41.png    Calendar cReturnDate = Calendar.getInstance();

6a9c071a08f1dae2d3e1c512000eef41.png    cNow.setTime(now);

6a9c071a08f1dae2d3e1c512000eef41.png    cReturnDate.setTime(returnDate);

6a9c071a08f1dae2d3e1c512000eef41.png    setTimeToMidnight(cNow);

6a9c071a08f1dae2d3e1c512000eef41.png    setTimeToMidnight(cReturnDate);

6a9c071a08f1dae2d3e1c512000eef41.png long todayMs = cNow.getTimeInMillis();

6a9c071a08f1dae2d3e1c512000eef41.png long returnMs = cReturnDate.getTimeInMillis();

6a9c071a08f1dae2d3e1c512000eef41.png long intervalMs = todayMs - returnMs;

6a9c071a08f1dae2d3e1c512000eef41.png return millisecondsToDays(intervalMs);

ExpandedBlockEnd.gif  }

None.gif

ExpandedBlockStart.gif private int millisecondsToDays(long intervalMs) {

6a9c071a08f1dae2d3e1c512000eef41.png return (int) (intervalMs / (1000 * 86400));

ExpandedBlockEnd.gif  }

None.gif

ExpandedBlockStart.gif private void setTimeToMidnight(Calendar calendar) {

6a9c071a08f1dae2d3e1c512000eef41.png    calendar.set(Calendar.HOUR_OF_DAY, 0);

6a9c071a08f1dae2d3e1c512000eef41.png    calendar.set(Calendar.MINUTE, 0);

6a9c071a08f1dae2d3e1c512000eef41.png    calendar.set(Calendar.SECOND, 0);

ExpandedBlockEnd.gif  }

None.gif

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

posted on 2012-04-16 18:15 cpegtop 阅读(3177) 评论(1)  编辑  收藏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值