时间和日期处理,在一个应用中都是很重要的,掌握时间和日期类的处理也是很重要的。Java中的Calendar类和Date类,在java.util包下。在JDK1.0中,Date类是唯一处理时间的类,但是由于Date类中方法比较少并且有一些方法不便于实现国际化,所以从JDK1.1版本开始新增了Calendar类,增加了许多功能强大的方法,推荐使用 Calendar类进行时间和日期处理。下面开始总结Date类和Calendar类的一些使用方法
Date类
在Java中有两个Date类,一个是java.sql.Date,另一个是java.util.Date,他们的关系是:前者是后者的子类,主要用在构造SQL语句的时候,比如读写数据库的时候可以使用它,后者是在大多是情况下使用的。他们的用法基本都是一样的。
Date的构造
创建一个Date类的对象,构造方法的参数可以有如下几种:
- 无参构造方法,使用默认无参构造方法创建出来的对象表示当前系统时间:
<code class="hljs vbnet has-numbering"><span class="hljs-built_in">Date</span> <span class="hljs-built_in">date</span> = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();</code><ul style="" class="pre-numbering"><li>1</li></ul>
- long类型的时间,long类型的时间就是自1970年1月1日00:00:00这一刻开始到目前所经历的毫秒数,这个值每时每刻都在变大,Date类可以已它作为构造参数创建一个指定的Date,比如:
<code class="hljs vbscript has-numbering"><span class="hljs-built_in">Date</span> <span class="hljs-built_in">now</span> = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(System.currentTimeMillis());</code><ul style="" class="pre-numbering"><li>1</li></ul>
这样就将当前系统时间封装成了一个Date类型数据,通过这个数据能够得到年月日等信息。
- 具体的年,月,日。传入具体的年月日的数值(年的数值并不是表示绝对的时间,而是自1900年开始的年份,所以,如果要表示年,应为指定值减去1900,比如要表示2015年,则应填写(2015-1900),月份的数值是从0到11,所以如果想表示3月,月份的数值就应该填2),以构造一个指定日期的Date类型数据,得到一个指定日期0点0分0秒的Date对象:
<code class="hljs lasso has-numbering"><span class="hljs-built_in">Date</span> <span class="hljs-built_in">date</span><span class="hljs-subst">=</span> <span class="hljs-literal">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-number">2015</span><span class="hljs-subst">-</span><span class="hljs-number">1900</span>, <span class="hljs-number">11</span>, <span class="hljs-number">27</span>);<span class="hljs-comment">//或者Date date = new Date(115,11,27)</span></code><ul style="" class="pre-numbering"><li>1</li></ul>
- 具体到时分秒的构造方法。传入一个具体时间的 值以构造指定时间的Date对象,比如:
<code class="hljs javascript has-numbering"><span class="hljs-built_in">Date</span> date1=<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-number">2015</span>-<span class="hljs-number">1900</span>,<span class="hljs-number">11</span>,<span class="hljs-number">30</span>,<span class="hljs-number">23</span>,<span class="hljs-number">59</span>,<span class="hljs-number">59</span>);</code><ul style="" class="pre-numbering"><li>1</li></ul>
这样就创建了一个2015年12月30日23时59分59秒的Date对象
所有这些参数都是有取值范围的,就像秒的范围为0-59一样,如果在构造一个Date对象时参数的值超出了取值范围,会默认往后叠加的,比如一个Date对象的构造为:
<code class="hljs javascript has-numbering"><span class="hljs-built_in">Date</span> oldDate = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-number">2015</span>-<span class="hljs-number">1900</span>, <span class="hljs-number">4</span>, <span class="hljs-number">40</span>);</code><ul style="" class="pre-numbering"><li>1</li></ul>
表面上看,这样得到的是一个2015年5月40日的Date对象,当然,肯定是不存在这个日期的,所以Date类型会自动往后叠加,打印输出为:
<code class="hljs css has-numbering">2015<span class="hljs-tag">-06-09</span> 00<span class="hljs-pseudo">:00</span><span class="hljs-pseudo">:00</span></code><ul style="" class="pre-numbering"><li>1</li></ul>
Date的操作
构造完成后,需要对它进行一些操作,来满足具体的需求,常用的有格式化输入输出,Date类型时间和String类型时间的转换,日期比较,加减
格式化
按照指定格式输出一个时间,为了满足不同的使用场景,比如有的时候仅需要显示时分,如“12:30”有的时候需要显示完整的时间,如“01-01 12:30”这样不同的显示只需要不同的格式,而Date对象不需要做任何改动,使用起来很灵活,这就需要用到SimpleDateFormat类来实现,下面是一个简单的例子:
<code class="hljs vbnet has-numbering">SimpleDateFormat format1 = <span class="hljs-keyword">new</span> SimpleDateFormat(<span class="hljs-string">"YYYY-MM-dd HH:mm:ss"</span>); SimpleDateFormat format2 = <span class="hljs-keyword">new</span> SimpleDateFormat(<span class="hljs-string">"HH:mm:ss"</span>); <span class="hljs-built_in">Date</span> <span class="hljs-built_in">date</span> = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(); System.out.println(format1.format(<span class="hljs-built_in">date</span>)); System.out.println(format2.format(<span class="hljs-built_in">date</span>));</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul>
输出结果:
<code class="hljs css has-numbering">2015<span class="hljs-tag">-11-29</span> 20<span class="hljs-pseudo">:27</span><span class="hljs-pseudo">:24</span> 20<span class="hljs-pseudo">:27</span><span class="hljs-pseudo">:24</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li></ul>
可以看到,控制Date输出显示格式的,就是SimpleDateFormat类的构造参数,这个构造参数规范了Date输出的格式,SimpleDateFormat中一些格式字符的含义如下:
- G: 年代标志符
- y: 年(大小写无区别)
- M: 月(大写表示 月,小写表示 分)
- d: 日(大写表示一年中的第几天,小写表示 日)
- H: 时(24小时制的时间)
- m: 分
- s: 秒
- S: 毫秒
- E: 星期
- D: 一年中的第几天
- w: 一年中第几个星期
- W:一月中第几个星期
- a: 上午或下午的标志符
- k: 一天中的第几个小时(24小时制)
- K: 一天中的第几个小时(12小时制)
- z: 时区
有了以上字符的解释,就能很轻松的构造任意格式的时间了,比如:“yyyy年mm月dd日 HH:mm:ss 是第D天 在第w周”输出如下:
<code class="hljs css has-numbering">2015年52月29日 20<span class="hljs-pseudo">:52</span><span class="hljs-pseudo">:21</span> 是第333天 在第49周</code><ul style="" class="pre-numbering"><li>1</li></ul>
类型转换
在很多时候需要将Date类型数据转换成String类型数据用以显示,或者将String类型的时间转成Date类型用以计算比较,所以下面是通用的类型转换代码:
<code class="hljs java has-numbering"> <span class="hljs-javadoc">/** * 将String类型的时间转换成Date类型,传入的时间格式必须要满足下面的格式,否则会报错 */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Date <span class="hljs-title">str2Date</span>(String dateStr) { SimpleDateFormat format = <span class="hljs-keyword">new</span> SimpleDateFormat(<span class="hljs-string">"yyyy-MM-dd HH:mm:ss"</span>, Locale.CHINA); Date date = <span class="hljs-keyword">null</span>; <span class="hljs-keyword">try</span> { date = format.parse(dateStr); } <span class="hljs-keyword">catch</span> (ParseException e) { e.printStackTrace(); } <span class="hljs-keyword">return</span> date; } <span class="hljs-javadoc">/** * 将Date型转换成指定格式的时间字符串 */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">date2Str</span>(Date date) { SimpleDateFormat format = <span class="hljs-keyword">new</span> SimpleDateFormat(<span class="hljs-string">"yyyy-MM-dd HH:mm:ss"</span>, Locale.CHINA); <span class="hljs-keyword">return</span> format.format(date); }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li></ul>
时间比较
有时候需要比较两个时间谁在前谁在后,可以使用Date类的compareTo方法来实现:
<code class="hljs java has-numbering"> <span class="hljs-javadoc">/** * 如果d1在d2后则返回true,否则返回false */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">greater</span>(Date d1, Date d2) { <span class="hljs-comment">//如果compareTo返回0,表示两个日期相等,返回小于0的值,表示d1在d2之前,大于0表示d1在d2之后</span> <span class="hljs-keyword">return</span> d1.compareTo(d2) > <span class="hljs-number">0</span>; }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul>
有时候想要获取指定时间之前或之后一段时间的日期,如下:
<code class="hljs java has-numbering"> <span class="hljs-javadoc">/** * 返回当前日期之后或者之前n天的时间 * n为正数表示当前日期之后的时间 * n为负数表示当前日期之前的时间 */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Date <span class="hljs-title">duration</span>(<span class="hljs-keyword">int</span> n) { <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Date(<span class="hljs-keyword">new</span> Date().getTime() + n * <span class="hljs-number">24</span> * <span class="hljs-number">60</span> * <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>); }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>
类似发布微博后显示距离当前时间“几分钟前”,“几小时前”的日期比较可以如下实现:
<code class="hljs java has-numbering"><span class="hljs-javadoc">/** * 返回发布时间距离当前的时间 */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">timeAgo</span>(Date createdTime) { SimpleDateFormat format = <span class="hljs-keyword">new</span> SimpleDateFormat(<span class="hljs-string">"MM-dd HH:mm"</span>, Locale.CHINA); <span class="hljs-keyword">if</span> (createdTime != <span class="hljs-keyword">null</span>) { <span class="hljs-keyword">long</span> agoTimeInMin = (<span class="hljs-keyword">new</span> Date(System.currentTimeMillis()).getTime() - createdTime.getTime()) / <span class="hljs-number">1000</span> / <span class="hljs-number">60</span>; <span class="hljs-comment">//如果在当前时间以前一分钟内</span> <span class="hljs-keyword">if</span> (agoTimeInMin <= <span class="hljs-number">1</span>) { <span class="hljs-keyword">return</span> <span class="hljs-string">"刚刚"</span>; } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (agoTimeInMin <= <span class="hljs-number">60</span>) { <span class="hljs-comment">//如果传入的参数时间在当前时间以前10分钟之内</span> <span class="hljs-keyword">return</span> agoTimeInMin + <span class="hljs-string">"分钟前"</span>; } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (agoTimeInMin <= <span class="hljs-number">60</span> * <span class="hljs-number">24</span>) { <span class="hljs-keyword">return</span> agoTimeInMin / <span class="hljs-number">60</span> + <span class="hljs-string">"小时前"</span>; } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (agoTimeInMin <= <span class="hljs-number">60</span> * <span class="hljs-number">24</span> * <span class="hljs-number">2</span>) { <span class="hljs-keyword">return</span> agoTimeInMin / (<span class="hljs-number">60</span> * <span class="hljs-number">24</span>) + <span class="hljs-string">"天前"</span>; } <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> format.format(createdTime); } } <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> format.format(<span class="hljs-keyword">new</span> Date(<span class="hljs-number">0</span>)); } }</code>