老版本: java.util.Date与java.util.Calendar类
新版本:java.time
为什么会出现新的日期类API? 1.对于日期的计算困难问题毫秒值与日期直接转换比较繁琐,其次通过毫秒值来计算时间的差额步骤较多
例如计算从2002.06.20到现在的天数
public static void main(String[] args) {
//初始化Date,无参构造器对应当前时间
Date date = new Date();
//获取对应的毫秒数
long cur_time = date.getTime();
Calendar c = Calendar.getInstance();
//月是从0开始的要求6月要传入5月的值
c.set(2002,5,20);
//要先转成Date类型才能转为long类型
Date date1 = c.getTime();
long pre_time = date1.getTime();
//当前毫秒数-目标毫秒数,进行秒,分,时的进制转换得到天数
long ans=(cur_time-pre_time)/1000/60/60/24;
System.out.println(ans);
long day = ChronoUnit.DAYS.between(LocalDate.of(2002, 6, 20), LocalDate.now());
System.out.println(day);
}
老方法因为毫秒数的计算误差和正确答案相差一天
2.API线程不安全问题SimpleDateFormat类是线程不安全的,在多线程的情况下,全局共享一个SimpleDateFormat类中的Calendar对象有可能会出现异常。除非使用synchronized(){}包裹
final static SimpleDateFormat sm=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
synchronized (sm) {
Date date = sm.parse("2002-06-20 11:11:11");
System.out.println(date);
}
} catch (ParseException e) {
e.printStackTrace();
}
}
});
}
}
java.time包 常用类的概述和功能介绍
Instant类
Instant类对时间轴上的单一瞬时点建模,可以用于记录应用程序中的事件时间戳,之后学习的类型转换中,均可以使用Instant类作为中间类完成转换。
Duration类
Duration类表示秒或纳秒时间间隔,适合处理较短的时间,需要更高的精确性。
Period类
Period类表示一段时间的年、月、日。
LocalDate类
LocalDate是一个不可变的日期时间对象,表示日期,通常被视为年月日。
LocalTime类
LocalTime是一个不可变的日期时间对象,代表一个时间,通常被看作是小时-秒,时间表示为纳秒精度。
LocalDateTime类
LocalDateTime类是一个不可变的日期时间对象,代表日期时间,通常被视为年-月-日=时-分-秒。
ZonedDateTime类
ZonedDateTime是具有时区的日期时间的不可变表示,此类存储所有日期和时间字段,精度为纳秒,时区为区域偏移量,用于处理模糊的本地日期时间。
这些类封装的都是格林威治时间不仅仅是以上提供的及各类可以使用now方法,Java8的Time包种还提供了其它几个类可以更精准的获取某些信息。
Year类(表示年)
YearMonth类(表示年月)
MonthDay类(表示月日)
指定任意时间节点of方法可以根据给定的参数生成对应的日期/时间对象,基本上每个基本类都有of方法用于生成的对应的对象,而且重载形式对边,可以根据不同的参数生成对应的数据。
public static void main(String[] args) {
LocalDate now = LocalDate.now();
//指定年月日
LocalDate localDate = LocalDate.of(2002, 6, 20);
//指定时分秒纳秒(如果秒和纳秒为0则不会显示)
LocalTime localTime = LocalTime.of(8, 0, 0,0);
//指定年月日时分秒
LocalDateTime.of(2002,6,20,11,11,11);
//特殊使用
LocalDateTime.of(localDate,localTime);
}
获取同一时间其他时区的时间
public static void main(String[] args) {
//获取所有时区信息
Set all = ZoneId.getAvailableZoneIds();
//获取当前系统默认时区信息
ZoneId zoneId = ZoneId.systemDefault();
//获取同一时间其他时区的时间
LocalDateTime time = LocalDateTime.of(2002, 6, 20, 11, 11, 11);
//中国时区
ZonedDateTime shanghai = time.atZone(zoneId.of("Asia/shanghai"));
//修改为日本时区
ZonedDateTime Tokyo = shanghai.withZoneSameInstant(zoneId.of("Asia/Tokyo"));
}
java.time包中引用了Month的枚举类,Month中包含标准日历中的12个月份的常量(从JANUARY到DECEMEBER)也提供了一些方便的方法供我们使用。
推荐在初始化LocalDate和LocalDateTime对象的时候,月份的参数使用枚举的方式传入,这样更简单易懂而且不易出错,因为如果是老的思维,Calendar传入0的话,那么会出现异常。
// 创建当前时间(不带时区) LocalDateTime localDateTimeNow = LocalDateTime.now(); // 创建当前时间(只包含年月日) LocalDate LocalDatenow = LocalDate.now(); // 创建当前时间(包含年月日时分秒并且带有时区) ZonedDateTime zonedDateTimeNow = ZonedDateTime.now(); // 创建2012年12月31日7时38分46秒的日期对象,月份用枚举表示 LocalDateTime LocalDateTimeOf = LocalDateTime.of( 2012, Month.DECEMBER, 31, 7, 38, 46); // 创建2012年12月31日的日期对象,月份用枚举表示 LocalDate LocalDate = LocalDate.of( 2012, Month.DECEMBER, 31); // 创建7时38分46秒的时间对象 LocalTime LocalTime = LocalTime.of( 7, 38, 46);



