java中的时间操作2
文/Ray
三、设置时间
现实中的时间是由不得我们这些凡夫俗子的,如来老头来了也许还有点可能,但在程序里我们可以变得神通广大。设置时间最典型的应用就是定时任务,我们设置一个时间,到时执行某项任务。
但这里我们主要不是为了解决这个定时任务的问题,我们是为了搞清楚怎么设置时间。关于定时任务,在后面再讨论怎么做。
所谓的设置时间,其实就是我们把一个我们能看懂的时间的显性的值(数字、字符串等),转化成程序能看得懂的(Date类,long型的毫秒值等)告诉它。
最直接的思路是,new一个Date类,使用它的某个方法,传进我们指定的数字或字符串类型的值,设置它的时间。
那就先来看一下Date这个类,这个类里面有好多方法,什么setYear,setMonth的,看起来真是太好了,传个int值进去就搞定了。
可惜,这些看起来非常good的方法从JDK1.1以后就不用了,只有一个
setTime(long time)方法还勉强可以用,但是看看这个方法的参数吧,TNND,是个long,2006年7月1号的long值是什么?鬼才知道。
所以这个方法不可取,刚才也提到Date类里有很多方法从JDK1.1以后就不用了,其中就有什么setYear,setMonth这样的方法。这些方法不是JDK里面没有了,而是被Calendar类里面的方法给取代了。(为什么取代?这个问题去问开发JDK的那帮人好了)
其实,还是用上面说到的SimpleDateFormat就可以搞定,代码,三行:
SimpleDateFormat sdf = new SimpleDateFormat("",Locale.SIMPLIFIED_CHINESE);
sdf.applyPattern("yyyy年MM月dd日_HH时mm分ss秒");
Date date = sdf.parse("2006年07月01日_14时00分00秒");
一看就懂了吧,第一行是声明对象的,如果前面已经声明了,这一行也省了,第二行是设置模式(pattern)的,关于这个模式,前面已经解释的很详细了,没有什么好说的。第三行,就是要设置的时间跟模式对应的字符串。第三行就返回了我们要得到的Date类型。(啰嗦了这么半天,才啰嗦出这么三行代码:))
Ok,这个问题搞定,继续下一个。
四、时间的运算
现在我们要开始用Calendar了,简单介绍一下先,JDK的文档里说,Calendar主要是用来对Date对象和Integer对象做转换的(这样看起来上面那个问题我们也可以使用Calendar)。事实上,实际的开发应用中,Calendar往往用来对时间进行操作,比如说设置个时间啊,对时间进行个对比运算什么滴。
举个例子,已知两个Date型时间对象,date1、date2,我们需要计算出这两个时间之间相差几个小时,怎么做。
一种思路:得到这两个时间对象的long值,然后相减,这就得到了他们相差的毫秒值,然后再根据这个毫秒值算出对应的小时。代码如下:
int distance = (int)((date2.getTime() - date1.getTime())/1000/60/60);
简单解释一下:
date2.getTime() - date1.getTime()得到相应的long型时间值并相减,得到相差的毫秒值,再除1000,得到秒,再除60,得到分,再除60,得到小时。呵呵,我真是够啰嗦!从毫秒转化成秒的时候,我在google上搜索了半天才确定一秒等于1000毫秒,真是白痴:)。
按上面的方式,似乎问题已经解决了。但是,结果得到的小时值很大可能是个小数,而且,有可能是个小数位很长的小数,这样就要考虑精确位的问题,上面那行代码就不够用了;还有一个比较关键的问题是,根据我们的习惯,往往可能是希望知道他们相差几小时几分几秒,而不是几点几个小时,也可能我们只想知道他们差几个小时,至于小时之外还差几分几秒,我们不感兴趣,这样,上面那行代码也不够用了。
如果要解决这种方式带来的后续的这两个问题,还要写更多的代码,麻烦死了,我是个懒人,不想费那脑子,我需要找一种更直接,更简单的方式来解决。
终于轮到Calendar出场了,对上面的问题,解决的代码如下:
Calendar ca1 = Calendar.getInstance();
Calendar ca2 = Calendar.getInstance();
ca1.setTime(date1);
ca2.setTime(date2);
int distanceHour = ca2.get(Calendar.HOUR_OF_DAY) - ca1.get(Calendar.HOUR_OF_DAY);
虽然有五行代码,但这五行代码根本都不用费我的脑子考虑,不像前面的,还要考虑转化什么的,而且这五行代码完全可以像前面一样用一行代码搞定。
这样就得到了这两个时间相差的小时的值,我可以保证绝对是个整数,因为这个distanceHour只是这两个时间对象的小时数之差,而不考虑它们的分秒的差,如果想得它们差几分,代码如下
int distanceMin = ca2.get(Calendar.MINUTE) - ca1.get(Calendar.MINUTE);
解释一下上面的代码:
Calendar ca1 = Calendar.getInstance();
得到一个Calendar对象,Calendar不提供公用的构造函数,不能new。这行代码得到的新对象的时间设置为当前时间。
ca1.setTime(date1);
把Calendar对象的时间设置为date1的时间。
ca1.get(Calendar.HOUR_OF_DAY)
获取Calendar对象的小时值,这里得到的是24小时制的。这个get方法参数是int型的,用来指定想要获取的域(field),就是什么年啊月啊周啊小时的东西。参数需要用Calendar类定义的常量,每个常量对应一个域(field),这些常量的含义都很明显(都可以顾名思义出来),用的时候在IDE环境里直接打点选择就可以。
这个get方法用起来很灵活,比如得到一天的int值,我们可以得到这一天一个月里的第几天,也可以得到一周里的第几天,也可以得到一年里的第几天,只要传进对应的参数就OK了。
有一点需要注意的是,按照我们的习惯,周一是一周的第一天,而老外的习惯是周日才是第一天,他们是先做完礼拜才开始这一周的。所以如果今天是周一,我们使用ca1.get(Calendar.DAY_OF_WEEK)时得到的值是2。
前面提到,Canlendar也可以用来设置时间,代码如下
Calendar ca = Calendar.getInstance();
ca.set(Calendar.YEAR, 2006);
ca.set(Calendar.MONTH, 7);
ca.set(Calendar.DAY_OF_MONTH, 1);
ca.set(Calendar.HOUR_OF_DAY, 14);
ca.set(Calendar.MINUTE,0);
ca.set(Calendar.SECOND, 0);
Date date = ca.getTime();
这跟前面第三个问题中的那三行代码的结果基本上是一样的,为什么说基本上?因为毫秒值不一样,ca的毫秒值是当前时间的毫秒值,而我们没有进行设置,所以仍然是当前的毫秒值。用那三行代码,还是用这几行,任君选择。