JDK 1.8 新特性 Date Time包介绍

        我们回顾下,JDK1.8之前的 SimpleDateFormat 线程安全问题,下图是阿里巴巴java 开发规范中描述 SimpleDateFormat 片段:

首先我们看下线程不安全部分的源码:

        我们把重点放在 calendar ,这个 format 方法在执行过程中,会操作成员变量 calendar 来保存时间 calendar.setTime(date) 。

        但由于在声明 SimpleDateFormat 的时候,使用的是 static 定义的,那么这个 SimpleDateFormat 就是一个共享变量,SimpleDateFormat 中的 calendar 也就可以被多个线程访问到,当多个线程同时使用相同的SimpleDateFormat 对象调用format方法时,多个线程会同时调用calendar.setTime方法,可能一个线程刚设置好time值另外的一个线程马上把设置的time值给修改了导致返回的格式化时间可能是错误的。

        除了 format() 方法以外,SimpleDateFormat 的 parse 方法也有同样的问题。

SimpleDateFormat如何保证线程安全

  • 避免线程之间共享一个SimpleDateFormat对象,每个线程使用时都创建一次SimpleDateFormat对象 => 创建和销毁对象的开销大
  • 对使用format和parse方法的地方进行加锁 => 线程阻塞性能差
  • 使用ThreadLocal保证每个线程最多只创建一次SimpleDateFormat对象 => MVP的解决方法

JDK 1.8,为我们提供了全新的日期和时间API

在使用Java程序操作数据库时,我们需要把数据库类型与Java类型映射起来。下表是数据库类型与Java新旧API的映射关系:

数据库对应Java类(旧)对应Java类(新)
DATETIMEjava.util.DateLocalDateTime
DATE  java.sql.DateLocalDate
TIME java.sql.Time LocalTime
TIMESTAMP java.sql.Timestamp LocalDateTime

LocalDate(日期类):

// 01:获取当前时间
LocalDate now = LocalDate.now();
System.out.println("当前时间:" + now);

// 02:自定义当前时间
LocalDate data = LocalDate.of(1997, 02, 21);
System.out.println("自定义当前时间:" + data);

// 03:修改时间的格式
String dataWithString = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println("当前时间的String格式:" + dataWithString);

// 04:解析当前时间
LocalDate parseTime = LocalDate.parse("1997-02-21");
System.out.println("解析当前的时间" + parseTime);

// 05:获取今天是本月的第几天
int dayOfMonth = LocalDate.now().getDayOfMonth();
System.out.println("dateOfMonth:" + dayOfMonth);

// 06:获取今天是今年的第多少天
int dateOfYear = LocalDate.now().getDayOfYear();
System.out.println("dateOfYear:" + dateOfYear);

// 07:获取年
int year = LocalDate.now().getYear();
System.out.println("year:" + year);

// 08:获取星期
DayOfWeek week = LocalDate.now().getDayOfWeek();
System.out.println(week.getValue());

// 09:获取当前时间并给它加一定的天数
LocalDate localDate = LocalDate.now().plusDays(5);
System.out.println("添加一定天数后的时间:" + localDate);

// 10:获取当前时间并给它减一定的天数
LocalDate minusDate = LocalDate.now().minusDays(9);
System.out.println("减去一定天数后的时间:" + minusDate);

// 11:计算两个日期间的天数
long dates = localDate.until(minusDate, ChronoUnit.DAYS);
System.out.println("相差的天数:" + dates);

// 12:计算两个日期间的天数的周数
long until = localDate.until(minusDate, ChronoUnit.WEEKS);
System.out.println("相差的周数:" + until);

LocalTime类(时间类):

// 01:获取带毫秒值的当前时间
LocalTime now = LocalTime.now();
System.out.println("当前时间:" + now);

// 02:获取不带毫秒值的当前时间
LocalTime nowWithNoNano = LocalTime.now().withNano(0);
System.out.println("不带毫秒值的当前时间:" + nowWithNoNano);

// 03:获取不带毫秒值不带分钟的时间
LocalTime nowWithNoSeconde = LocalTime.now().withNano(0).withSecond(0);
System.out.println("不带毫秒不带分钟的时间:" + nowWithNoSeconde);

// 04:获取不带毫秒值不带分钟的时间还可以这样做(格式化处理)
String nowTime = LocalTime.now().format(DateTimeFormatter.ofPattern("hh:mm"));
System.out.println("nowTime:" + nowTime);

// 05:获取制定的时间
LocalTime localTime = LocalTime.parse("06:00");
System.out.println("指定时间:" + localTime);

// 06:获取指定时间还可以这样做
LocalTime localTime1 = LocalTime.of(6,00);
System.out.println("localTime1:" + localTime1);

LocalDateTime类(时间日期类):


// 01:获取当前时间
LocalDateTime now = LocalDateTime.now();
System.out.println("now: " + now);

// 02:格式化一下当前时间
String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss E"));
System.out.println("格式化处理后的时间: " + time);

// 03:使用with开头的方法可以设置对应的年月日等
LocalDateTime localDateTime = LocalDateTime.now().withYear(1997);
System.out.println("localDateTime: " + localDateTime);

// 04:使用get开头的方法可以获取对应的年月日等
int dayOfMonth = LocalDateTime.now().getDayOfMonth();
System.out.println("dayOfMonth: " + dayOfMonth);

日期计算

        增加、减少年数、月数、天数等,以LocalDateTime为例


//修改LocalDate、LocalTime、LocalDateTime、Instant
LocalDateTime localDateTime = LocalDateTime.of(2019, Month.SEPTEMBER, 10,
        14, 46, 56);
        
//增加一年
localDateTime = localDateTime.plusYears(1);
localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);

//减少一个月
localDateTime = localDateTime.minusMonths(1);
localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);

//通过with修改某些值
//修改年为2020
localDateTime = localDateTime.withYear(2020);
//修改为2022
localDateTime = localDateTime.with(ChronoField.YEAR, 2022);

        有些时候想知道这个月的最后一天是几号、下个周末是几号,通过提供的时间和日期API可以很快得到答案

LocalDate localDate = LocalDate.now();
LocalDate localDate1 = localDate.with(TemporalAdjusters.firstDayOfYear());

格式化时间

        DateTimeFormatter默认提供了多种格式化方式,如果默认提供的不能满足要求,可以通过DateTimeFormatter的ofPattern方法创建自定义格式化方式


LocalDate localDate = LocalDate.of(2019, 9, 10);
String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);

//自定义格式化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String s3 = localDate.format(dateTimeFormatter);

解析时间

LocalDate localDate1 = LocalDate.parse("20190910", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate localDate2 = LocalDate.parse("2019-09-10", DateTimeFormatter.ISO_LOCAL_DATE);

DateTimeFormatter底层原理

        通过final修饰类,不可被继承,final修饰变量,做成了不可变类,因为一旦分配了一个对象的某个引用,它就不能指向另一个对象的引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值