JDK8新特性提供了3个时间类:localDate,localTime,localDateTime
在Java8之前,
在做有关时间日期的操作时,会想到用Date
在做日期、月份、天数相加减时,会想到用Calendar
当需要对日期进行格式化时,会想到用SimpleDateFormat或DateFormat下的其他子类
但SimpleDateFormat是线程不安全的。
private StringBuffer format(Date date, StringBuffer toAppendTo, FieldDelegate delegate) {
// Convert input date to time field list
calendar.setTime(date);
boolean useDateFormatSymbols = useDateFormatSymbols();
for (int i = 0; i < compiledPattern.length; ) {
int tag = compiledPattern[i] >>> 8;
int count = compiledPattern[i++] & 0xff;
if (count == 255) {
count = compiledPattern[i++] << 16;
count |= compiledPattern[i++];
}
switch (tag) {
case TAG_QUOTE_ASCII_CHAR:
toAppendTo.append((char) count);
break;
case TAG_QUOTE_CHARS:
toAppendTo.append(compiledPattern, i, count);
i += count;
break;
default:
subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
break;
}
}
return toAppendTo;
}
calendar是共享变量,并且这个共享变量是没有做线程安全机制,当多个线程同时使用相同的SimpleDateFormat对象调用format方法时,多个线程会同时调用Calendar.setTime方法,可能一个线程刚设置好time值,另外一个线程马上把设置的time值给修改了导致返回的格式化时间可能是错误的。
新时间日期API常用、重要对象介绍
ZoneId:时区ID,用来确定instant和LocalDateTime互相转换的规则
Instant:用来表示时间线上的一个点(瞬时)
LocalDate:表示没有时区的日期,LocalDate是不可变并且线程安全的
LocalTime:表示没有时区的时间,LocalTime是不可变并且线程安全的
Clock:用于访问当前时刻、日期、时间,用到时区
Duration:用秒和纳秒表示时间段 数量(长短),用来计算两个日期的时间间隔
period:用于计算两个“日期”间隔
LocalDate:只含年月日的日期对象
LocalTime:只含时分秒的时间对象
LocalDateTime:同时包含年月日时分秒的日期对象
获取当前时间
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime dateTime = LocalDateTime.now();
System.out.println(date);
System.out.println(time);
System.out.println(dateTime);
localDate 指定时间,并获取年月日
//设置日期
LocalDate localDate = LocalDate.of(2021,7,24);
//获取年
int year = localDate.getYear();//2021
int year1= localDate.get(ChronoField.YEAR);//2021
//获取月
Month month = localDate.getMonth();//JULY
int month1 = localDate.get(ChronoField.MONTH_OF_YEAR);//7
//获取日
int day = localDate.getDayOfMonth();//24
int day1 = localDate.get(ChronoField.DAY_OF_MONTH);//24
//获取星期
DayOfWeek week =localDate.getDayOfWeek();//Saturday
int dayOfWeek = localDate.get(ChronoField.DAY_OF_WEEK);//2
localTime 指定时间,获取时分秒
//设置时间
LocalTime localTime = LocalTime.of(11,56,20);
//获取小时
int hour = localTime.getHour();//11
int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);//11
//获取分
int minute = localTime.getMinute();//56
int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);//56
//获取秒
int second = localTime.getSecond();//20
int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);//20
localDateTime 相当于LocalDate+LocalTime 设置时间
//设置时间
LocalDateTime localDateTime = LocalDateTime.of(2021,Month.JULY,24,12,4,12);
LocalDateTime localDateTime1 = localDateTime.of(localDate,localTime);
LocalDateTime localDateTime2 = localDate.atTime(localTime);
LocalDateTime localDateTime3 = localTime.atDate(localDate);
//获取localDate
LocalDate localDate1 = localDateTime.toLocalDate();
//获取LocalTime
LocalTime localTime1 = localDateTime.toLocalTime();
修改LocalDate、LocalTime、LocalDateTime、Instant
//指定时间
LocalDateTime localDateTime = LocalDateTime.of(2021,Month.JULY,24,12,11,43);
//增加一年
localDateTime = localDateTime.plusYears(1);//2022-07-24
System.out.println(localDateTime);
localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);
System.out.println(localDateTime);
//减少一个月
localDateTime = localDateTime.minusMonths(1);
System.out.println(localDateTime);
localDateTime = localDateTime.minus(1,ChronoUnit.MONTHS);
System.out.println(localDateTime);
可以通过with修改某些值
localDateTime = localDateTime.withYear(2021);
localDateTime = localDateTime.with(ChronoField.YEAR,2020);
Date与LocalDateTime转换
//localDateTime转时间戳
LocalDateTime localDateTime = LocalDateTime.now();
ZoneId id = ZoneId.systemDefault();
Instant instant =localDateTime.atZone(id).toInstant();
Long time = instant.toEpochMilli();
System.out.println(time);
//时间戳转localDateTime
Instant instant1 = Instant.ofEpochMilli(time);
ZoneId zoneId =ZoneId.systemDefault();
LocalDateTime localDateTime1 = LocalDateTime.ofInstant(instant1,zoneId);
System.out.println("localDateTime:"+localDateTime1);
//date转LocalDateTime
Date date = new Date();
Instant instant2 =date.toInstant();
ZoneId zoneId1 =ZoneId.systemDefault();
LocalDateTime localDateTime2 = instant2.atZone(zoneId1).toLocalDateTime();
System.out.println("date转locatDateTIme: "+localDateTime2);
//LocalDateTime转date
LocalDateTime localDateTime3 = LocalDateTime.now();
ZoneId zoneId2 = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime3.atZone(zoneId);
Date date1 = Date.from(zdt.toInstant());
System.out.println("localDateTime转date: "+date1);