月度归档:2015 年八月

Java Time(一)

在讨论java8的time前,先回顾一下java8以前的日期,主要两个类java.util包下的Date、Calendar,其次是java.sql包下面对java.util.Date的扩展类Date、Time、Timestamp。
下面就来吐槽一下以前的日期API:
1,Date计算、格式化麻烦;
2,非线程安全
3,时区处理麻烦;
吐槽完了,来看下以前处理日期的一些实例:
1,获取指定的时间,比如获取 2015-08-23 22:00:00 的时间:

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = sdf.parse("2015-08-23 22:00:00");
        } catch (ParseException e) {
            e.printStackTrace();
        }

(这里使用SimpleDateFormat还有个问题,SimpleDateFormat也是非线程安全的,假如说运行过程中其他线程修改了SimpleDateFormat的值,那悲剧就发生了。)
或者:

 Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR,2015);
        calendar.set(Calendar.MONTH,7);
        calendar.set(Calendar.DAY_OF_MONTH,23);
        calendar.set(Calendar.HOUR_OF_DAY,22);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        Date time = calendar.getTime();

.
这里还要注意月份是从0开始的;

2,所有日期类都可变的,非线程安全的,简单说下:
一般的bean类都会有个getter和setter方法,修改date用set方法,getter方法只用做读取,但是由于Date是可变的,getter方法也能用于修改:

bean.getDate().setTime(1440342793161L);

这显然违反了我们的初衷,也容易出问题。

3,关于时区问题:
java.util.Date是没有时区概念的,时区一般是由SimpleDateFormat这个类来控制的,

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
            Date date = sdf.parse("2015-08-23 11:00:00");//得到美国时间 date
            System.out.println(sdf.format(new Date()));//格式化为美国的当前时间

或者是Calendar:

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone("America/New_York"));
        System.out.println(calendar.get(Calendar.HOUR_OF_DAY));

所以,java以前的时间经常被吐槽,所以一般我们都会写一个DateUtil来处理,或者用第三方的库比如说apache commons的DateUtils;因此后来joda解决了以前java日期各种问题,再后来官方的java8也加入了datetime包解决旧版本时间的各种问题