Java 入门总结(六) —— 剖析日期和时间
1、关于时区
英国格林尼治是 0 时区,北京是东八区,也就是说格林尼治凌晨 1 点,北京是早上 9 点。0 时区的时间也称为 GMT+0 时间,GMT 是格林尼治标准时间,北京的时间就是 GMT+8:00。
2、时刻和 Epoch Time(纪元时)
所有计算机系统内部都用一个整数表示时刻,这个整数是距离格林尼治标准时间 1970年1月1日0时0分0秒 的毫秒数。格林尼治标准时间 1970年1月1日0时0分0秒 也被称为 Epoch Time (纪元时)。这个整数表示的是一个时刻,与时区无关,世界上各个地方都是同一个时刻。而对于 1970 年以前的时间则使用负数表示。
3、年历
公历和农历都是年历。年历就是对一年有多少月,每月有多少天,甚至一天有多少小时的规则定义。
时刻是一个绝对时间,对时刻的解读,如年月日周时分秒等,则是相对的,与年历和时区相关。
Date:表示时刻,即绝对时间,与年月日无关。
Calendar:表示年历,Calendar 是一个抽象类,其中表示公历的子类是 GregorianCalendar。
DateFormat:表示格式化,能够将日期和时间与字符串进行相互转换,DateFormat 也是一个抽象类,其中最常用的子类是 SimpleDateFormat。
TimeZone: 表示时区。Locale: 表示国家和语言。
4、Date 表示时刻,内部主要是一个 long 类型的值 private transient long fastTime;
几乎所有的未过时的方法都是对该值进行操作的。
5、Calendar 类是日期和时间操作中的主要类,它表示与 TimeZone 和 Locale 相关的日历信息,可以进行各种相关的运算。
Calendar.MONTH:表示月,一月份是 0。Calendar.DAY_OF_MONTH:表示日,每月的第一天是 1。Calendar.DAY_OF_WEEK:表示星期几,周日是 1,周一是 2,周六是 7。
内部,Calendar 会将表示时刻的毫秒数,按照 TimeZone 和 Locale 对应的年历,计算各个日历字段的值,存放在 fields 数组中,Calendar.get 方法获取的就是 fields 数组中对应字段的值。
内部,根据字段设置或修改时间时,Calendar 会更新 fields 数组对应字段的值,但一般不会立即更新其他相关字段或内部的毫秒数的值,不过在获取时间或字段值的时候,Calendar 会重新计算并更新相关字段。
6、DateFormat 类主要在 Date 和字符串表示之间进行相互转换。
7、DateFormat/SimpleDateFormat 不是线程安全的,因为 DateFormat 内部使用了一个 Calendar 实例对象,多线程同时调用的时候,这个 Calendar 实例的状态可能就会紊乱。
8、总结:Date 表示时刻,与年月日无关,Calendar 表示日历,与时区和 Locale 相关,可进行各种运算,是日期时间操作的主要类,DateFormat/SimpleDateFormat 在 Date 和字符串之间进行相互转换。
9、Joda 的主要工作都是在毫秒和年月日等年历信息之间进行相互转换。
10、Joda-Time 中的主要类都被设计为了不可变类,不可变类有一个很大的优点,那就是简单、线程安全,所有看似的修改操作都是通过创建新对象来实现的。