相对于java8之前的版本最大的亮点在于线程安全,java8时间的时间api为线程非安全,而且在java8中
对于时间的操作更加简单,实用
LocalDate、LocalTime、LocalDateTime
@Test
public void test01(){
LocalDate date=LocalDate.now();
System.out.println(date);//2018-05-20
LocalDateTime dtime=LocalDateTime.now();
System.out.println(dtime);//2018-05-20T22:46:54.300
System.out.println(dtime.getYear());//2018
System.out.println(date.getMonthValue());//5
System.out.println(date.getDayOfYear());//140
System.out.println(date.getDayOfWeek());//SUNDAY
System.out.println("============");
LocalDateTime of = LocalDateTime.of(2017, 12, 22,12, 52);
System.out.println(of);//2017-12-22T12:52
System.out.println(of.minusDays(2));//2017-12-20T12:52
System.out.println(of.plusDays(2));//2017-12-24T12:52
}
Instant : 时间戳。 (使用 Unix 元年 1970年1月1日 00:00:00 所经历的毫秒值)
@Test
public void test02(){
Instant now = Instant.now();
System.out.println(now);//UTC 时区2018-05-20T22:22:36.981Z 实际上本机的时间是2018/05/21 06:23
OffsetDateTime atOffset = now.atOffset(ZoneOffset.ofHours(8));
System.out.println(atOffset);//2018-05-21T06:25:32.204+08:00
long epochSecond = now.getEpochSecond();
System.out.println(epochSecond);//1526855193
Instant ofEpochSecond = Instant.ofEpochSecond(2);
System.out.println(ofEpochSecond);//1970-01-01T00:00:02Z
}
Duration : 用于计算两个“时间”间隔 Period : 用于计算两个“日期”间隔
@Test
public void test03(){
Instant now = Instant.now();
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
Instant now2 = Instant.now();
System.out.println(Duration.between(now, now2).toMillis());//3001
System.out.println(Duration.between(now, now2).getSeconds());//3
LocalDate now3 = LocalDate.now();
LocalDate of = LocalDate.of(2017, 8, 22);
int years = Period.between(of, now3).getYears();
int months = Period.between(of, now3).getMonths();
int days = Period.between(of, now3).getDays();
System.out.println("相差"+years+"年;"+months+"月;"+days+"天");//相差0年;8月;29天
}
TemporalAdjuster : 时间校正器;TemporalAdjusters 静态工具类
@Test
public void test04(){
LocalDateTime l=LocalDateTime.now();
System.out.println(l);//2018-05-21T06:50:56.466
LocalDateTime withHour = l.withDayOfMonth(2);
System.out.println(withHour);//2018-05-02T06:50:56.466
LocalDateTime plusDays = l.plusDays(3);
System.out.println(plusDays);//2018-05-24T06:51:57.069
LocalDateTime with = l.with(TemporalAdjusters.firstDayOfMonth());
System.out.println(with);//2018-05-01T06:52:41.704
LocalDateTime with2 = l.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(with2);//2018-05-27T06:53:37.178
//自定义工作日时间
LocalDateTime with3 = l.with((e)->{
LocalDateTime L2=(LocalDateTime) e;
DayOfWeek dayOfWeek = L2.getDayOfWeek();
if(dayOfWeek.equals(DayOfWeek.FRIDAY)){
return L2.plusDays(3);
}else if(dayOfWeek.equals(DayOfWeek.SATURDAY)){
return L2.plusDays(2);
}else{
return L2.plusDays(1);
}
});
System.out.println(with3);//2018-05-22T06:57:06.338
}
DateTimeFormatter : 解析和格式化日期或时间
@Test
public void test05(){
DateTimeFormatter isoDate = DateTimeFormatter.ISO_WEEK_DATE;
LocalDateTime now = LocalDateTime.now();
String format = now.format(isoDate);
System.out.println(format);//2018-W21-2
DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyy年-MM月-dd日");
LocalDateTime plusDays = now.plusDays(5);
String format2 = plusDays.format(ofPattern);
System.out.println(format2);//2018年-05日-27日
}
ZonedDate、ZonedTime、ZonedDateTime : 带时区的时间或日期
@Test
public void test06(){
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);//2018-05-22T07:10:00.663+08:00[GMT+08:00] 08指的是和UTC的时差
Set<String> set = ZoneId.getAvailableZoneIds();
set.forEach(System.out::println);
/**
* Pacific/Guadalcanal
Europe/Athens
US/Pacific
Europe/Monaco。。。。。所有的时区
*/
LocalDateTime ldt = LocalDateTime.now(ZoneId.of("US/Pacific"));
System.out.println(ldt);//2018-05-21T16:24:31.443
ZonedDateTime atZone = ldt.atZone(ZoneId.of("US/Pacific"));
System.out.println(atZone);//2018-05-21T16:24:31.443-07:00[US/Pacific] 带时区的时间
LocalDateTime localDateTime = atZone.toLocalDateTime();
System.out.println(localDateTime);//2018-05-21T16:24:31.443
}
================传统时间格式话线程安全问题==================
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Callable<Date> task = new Callable<Date>() {
@Override
public Date call() throws Exception {
return sdf.parse("20161121");
}
};
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<Date>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(pool.submit(task));
}
for (Future<Date> future : results) {
System.out.println(future.get());
}
pool.shutdown();
下面是运行结果
利用ThreadLocal解决多线程安全问题
新建类 DateFormatThreadLocal
public class DateFormatThreadLocal {
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
protected DateFormat initialValue(){
return new SimpleDateFormat("yyyyMMdd");
}
};
public static final Date convert(String source) throws ParseException{
return df.get().parse(source);
}
}
Callable<Date> task = new Callable<Date>() {
@Override
public Date call() throws Exception {
return DateFormatThreadLocal.convert("20161121");
}
};
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<Date>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(pool.submit(task));
}
for (Future<Date> future : results) {
System.out.println(future.get());
}
pool.shutdown();
运行结果:
localDate 实现
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
Callable<LocalDate> task = new Callable<LocalDate>() {
@Override
public LocalDate call() throws Exception {
LocalDate ld = LocalDate.parse("20161121", dtf);
return ld;
}
};
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<LocalDate>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(pool.submit(task));
}
for (Future<LocalDate> future : results) {
System.out.println(future.get());
}
pool.shutdown();
运行结果: