java:通过Calendar类正确计算两日期之间的间隔
在开发Android应用时偶然需要用到一个提示用户已用天数的功能,从实现上来看无非就是持久化存入用户第一次使用应用的时间firstTime(通过SharedPreferences 、xml、sqlite等),当用户再次使用应用时取得此时时间presentTime,通过两个时间计算其间隔天数。
当取得两个时间变量后,网上计算日期间隔的做法通常是这样的(获得两时间的毫秒数之差再进行处理):
- long beginTime = beginDate.getTime();
- long endTime = endDate.getTime();
- 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));
下面测试一下两种特殊情况:
情况1:
- Calendar beginCalendar = Calendar.getInstance();
- beginCalendar.set(2017,2,3,1,0,0); //设定时间为2017年3月3日 1:0:0
- Calendar endCalendar = Calendar.getInstance();
- endCalendar.set(2017,2,3,14,0,0); //设定时间为2017年3月3日 14:0:0
- long beginTime = beginCalendar.getTime().getTime();
- long endTime = endCalendar.getTime().getTime();
- long betweenDays = (long)((endTime - beginTime) / (1000 * 60 * 60 *24));
- System.out.println(betweenDays); //输出为0
Calendar beginCalendar = Calendar.getInstance();
beginCalendar.set(2017,2,3,1,0,0); //设定时间为2017年3月3日 1:0:0
Calendar endCalendar = Calendar.getInstance();
endCalendar.set(2017,2,3,14,0,0); //设定时间为2017年3月3日 14:0:0
long beginTime = beginCalendar.getTime().getTime();
long endTime = endCalendar.getTime().getTime();
long betweenDays = (long)((endTime - beginTime) / (1000 * 60 * 60 *24));
System.out.println(betweenDays); //输出为0
情况2:
- Calendar beginCalendar = Calendar.getInstance();
- beginCalendar.set(2017,2,2,20,20,20);<span style="white-space: pre;"> </span>//设定时间为2017年3月2日20:20:20
- Calendar endCalendar = Calendar.getInstance();
- endCalendar.set(2017,2,3,10,10,10); //设定时间为2017年3月3日10:10:10
- long beginTime = beginCalendar.getTime().getTime();
- long endTime = endCalendar.getTime().getTime();
- long betweenDays = (long)((endTime - beginTime) / (1000 * 60 * 60 *24));
- System.out.println(betweenDays); //输出为0,但其实应该为1
Calendar beginCalendar = Calendar.getInstance();
beginCalendar.set(2017,2,2,20,20,20); //设定时间为2017年3月2日20:20:20
Calendar endCalendar = Calendar.getInstance();
endCalendar.set(2017,2,3,10,10,10); //设定时间为2017年3月3日10:10:10
long beginTime = beginCalendar.getTime().getTime();
long endTime = endCalendar.getTime().getTime();
long betweenDays = (long)((endTime - beginTime) / (1000 * 60 * 60 *24));
System.out.println(betweenDays); //输出为0,但其实应该为1
可见,对于本应该时间间隔为1的情况该代码输出为0。究其原因,是因为当 两日期的毫秒数之差 < 一天的毫秒数(1000*60*60*24)时,即使两日期跨了一天,强制类型转换后结果也会变成0。通过下图可以看出毫秒数之差小于一天的两种情况。
情况1(毫秒数之差小于一天且不跨天,日期间隔应为0):
情况2(毫秒数之差小于一天且跨天,日期间隔应为1):
所以上述代码需要改进,使其能够识别跨天这种特殊情况:
- 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));//先算出两时间的毫秒数之差大于一天的天数
- endCalendar.add(Calendar.DAY_OF_MONTH, -betweenDays);//使endCalendar减去这些天数,将问题转换为两时间的毫秒数之差不足一天的情况
- endCalendar.add(Calendar.DAY_OF_MONTH, -1);//再使endCalendar减去1天
- if(beginCalendar.get(Calendar.DAY_OF_MONTH)==endCalendar.get(Calendar.DAY_OF_MONTH))//比较两日期的DAY_OF_MONTH是否相等
- return betweenDays + 1; //相等说明确实跨天了
- else
- return betweenDays + 0; //不相等说明确实未跨天
- }
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));//先算出两时间的毫秒数之差大于一天的天数
endCalendar.add(Calendar.DAY_OF_MONTH, -betweenDays);//使endCalendar减去这些天数,将问题转换为两时间的毫秒数之差不足一天的情况
endCalendar.add(Calendar.DAY_OF_MONTH, -1);//再使endCalendar减去1天
if(beginCalendar.get(Calendar.DAY_OF_MONTH)==endCalendar.get(Calendar.DAY_OF_MONTH))//比较两日期的DAY_OF_MONTH是否相等
return betweenDays + 1; //相等说明确实跨天了
else
return betweenDays + 0; //不相等说明确实未跨天
}
代码中有个细节需要注意,我先使 endCalendar.add(Calendar.DAY_OF_MONTH, -1),然后比较两日期的DAY_OF_MONTH时间值是否相等,从而确定返回值
而没有直接
- 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);
是因为有可能出现跨月的情况,例如beginCalendar的日期为2月28日,endCalendar日期为3月1日,endCalendar.get(Calendar.DAY_OF_MONTH)-beginCalendar.get(Calendar.DAY_OF_MONTH)的值就会是-27而不是预期中的1。而使用endCalendar.add(Calendar.DAY_OF_MONTH, -1),Calendar类的方法会自动的对跨月情况进行转换。
java:通过Calendar类正确计算两日期之间的间隔的更多相关文章
- C++练习 | 计算两日期之间天数差
#include<iostream> #include<string> #include<cstring> using namespace std; class D ...
- MySql计算两日期时间之间相差的天数,秒数,分钟数,周数,小时数
MySql计算两日期时间之间相差的天数,秒数,分钟数,周数,小时数 计算两日期时间之间相差的天数,秒数,分钟数,周数,小时数,这里主要分享的是通过MySql内置的函数 TimeStampDiff() ...
- Java基础-Calendar类常用方法介绍
Java基础-Calendar类常用方法介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Calendar类概念 Calendar 类是一个抽象类,它为特定瞬间与一组诸如 Y ...
- Java学习--Calendar 类的应用
Calendar 类的应用 Date 类最主要的作用就是获得当前时间,同时这个类里面也具有设置时间以及一些其他的功能,但是由于本身设计的问题,这些方法却遭到众多批评,不建议使用,更推荐使用 Calen ...
- JAVA中Calendar 类的应用
转自:https://www.imooc.com/code/2340 侵删! Date 类最主要的作用就是获得当前时间,同时这个类里面也具有设置时间以及一些其他的功能,但是由于本身设计的问题,这些方法 ...
- Java.util.Calendar类
Java.util.Calendar类 package myProject; import java.text.SimpleDateFormat; import java.util.Calendar; ...
- HDOJ(HDU) 2133 What day is it(认识下Java的Calendar类---日期类)
Problem Description Today is Saturday, 17th Nov,2007. Now, if i tell you a date, can you tell me wha ...
- java 使用Date类、Calendar类,实现增加日期
Date date= new Date(); System.out.println("Date date= new Date()中的date: "+date); 输出对象date: ...
- Java的Calendar类
通过Date类我们可以创建并格式化一个日期对象,但是如何才能设置和获取日期数据的特定部分呢?----Calendar类 Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,通过getIn ...
随机推荐
- 在k8s中搭建可解析hostname的DNS服务
2016-01-25更新 上篇文章总结k8s中搭建hbase时,遇到Pod中hostname的DNS解析问题,本篇将通过修改kube2sky源码来解决这个问题. 1 前言 kube2sky在Githu ...
- JVM笔记6-垃圾回收器
JVM进行垃圾回收时要考虑哪的问题如下: 1.如何判定对象为垃圾对象? 1.引用计数法:在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用计数器的值就+1,引用失效的时候,计数器的值就-1, ...
- printf()函数中\t,水平制表符,空格的个数
在控制台输出数据的时候,也就是用printf()的时候,我们经常用\t来控制对齐,以使输出的结果更加整齐美观. 然而有时候我们发现及时使用了\t 也会出现数据对不齐的情况,这就跟\t究竟对应几个空格有 ...
- C++中迭代器原理、失效和简单实现
目录 迭代器的使用 迭代器的种类 迭代器的失效 迭代器的实现 1.迭代器的使用 为了提高C++编程的效率,STL中提供了许多容器,包括vector.list.map.set等.有些容器例如vector ...
- Ruby语言学习系列--String 类函数
函数名称 说明 示例 * 将字符串拷贝N次 “ha”*4 >> “hahahaha” + << concat 连接字符串 “yes” + “no” >& ...
- [BZOJ 2839]集合计数
Description 题库链接 有 \(2^n\) 个集合,每个集合只包含 \([1,n]\) ,且这些集合两两不同.问有多少种选择方法(至少选一个),使得这些集合交集大小为 \(k\) . \(0 ...
- C# WebBrowser设置代理
WebBrowser控件是基于IE浏览器的,所以它的内核功能是依赖于IE. code: class IEProxy { //设置代理选项 private const int INTERNET_OPTI ...
- SQL Server附加数据库拒绝访问解决方法汇总
@本文来自百度 方法一:修改权限法 1 打开要附加的数据库文件所在的文件夹,即扩展名为mdf的文件所在的文件夹,如下图所示: 2 右键单击mdf文件,选择“属性”,如下图所示: 3 单击“安全”选项卡 ...
- 初识IntPtr
一:什么是IntPtr 先来看看MSDN上说的:用于表示指针或句柄的平台特定类型.这个其实说出了这样两个事实,IntPtr 可以用来表示指针或句柄.它是一个平台特定类型.对于它的解释,这个哥们写的比较 ...
- ant编译apache-nutch-2.2.1结合mysql实现爬虫的安装配置全过程
之前的数据抓取都是用的八爪鱼软件,老大突发奇想要我自己搞个爬虫来抓取数据,网上找找貌似apache的nutch比较合适,于是就开始安装这啥nutch. 对于一个linux零基础的人来说,还要先学学li ...