传统的java日期时间格式和Java8的日期时间格式最大的不同就是现成安全
public class TestDate {
public static void main(String[] args) throws Exception{
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Callable<Date> callable = new Callable<Date>() {
@Override
public Date call() throws Exception {
return sdf.parse("20161121");
}
};
//创建大小为10的线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
//把格式化的结构放入集合中
List<Future<Date>> results = new ArrayList<>();
//执行
for (int i=0; i<10; i++){
results.add(pool.submit(callable));
}
//打印
for (Future<Date> future: results){
System.out.println(future.get());
}
pool.shutdown();
}
}
你会得到一个这样的异常
解决办法就是加锁,这也是传统的解决方案
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
/**
* 时间日期总结
*/
public class TestDate {
public static void main(String[] args) throws Exception{
Callable<Date> callable = new Callable<Date>() {
@Override
public Date call() throws Exception {
return DateFormatThreadLocal.convert("20161121");
}
};
//创建大小为10的线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
//把格式化的结构放入集合中
List<Future<Date>> results = new ArrayList<>();
//执行
for (int i=0; i<10; i++){
results.add(pool.submit(callable));
}
//打印
for (Future<Date> future: results){
System.out.println(future.get());
}
pool.shutdown();
}
static 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);
}
}
}
用上Java8的日期后就不用担心线程安全的问题了
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
/**
* 时间日期总结
*/
public class TestDate {
public static void main(String[] args) throws Exception{
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
Callable<LocalDate> callable = new Callable<LocalDate>() {
@Override
public LocalDate call() throws Exception {
return LocalDate.parse("20161121",dtf);
}
};
//创建大小为10的线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
//把格式化的结构放入集合中
List<Future<LocalDate>> results = new ArrayList<>();
//执行
for (int i=0; i<10; i++){
results.add(pool.submit(callable));
}
//打印
for (Future<LocalDate> future: results){
System.out.println(future.get());
}
pool.shutdown();
}
}
看一下新的java8API大概的分布,都是在java.time包下的
LocalDate、LocalTime、LocalDateTime
看一下这三个类的用法,会用一个其他的都差不多的
/**
* 时间日期总结
*/
public class TestDate {
public static void main(String[] args) throws Exception{
// 获取当前系统的的时间日期
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
// 手动指定日期时间
LocalDateTime ld2 = LocalDateTime.of(2016, 11, 21, 10, 10, 10);
System.out.println(ld2);
// 对日期事假的计算,加20年,可以加月,加日,加十分秒,包括LocalDate、LocalTime都可以加,能显示什么就能加什么
LocalDateTime ldt3 = ld2.plusYears(20);
System.out.println(ldt3);
// 减
LocalDateTime ldt4 = ld2.minusMonths(2);
System.out.println(ldt4);
//单独打印出年月日时分秒
System.out.println(ldt.getYear());
System.out.println(ldt.getMonthValue());
System.out.println(ldt.getDayOfMonth());
System.out.println(ldt.getHour());
System.out.println(ldt.getMinute());
System.out.println(ldt.getSecond());
//LocalDate、LocalTime、LocalDateTime 这三个类的方法大致一样的,只不过操作的方法有点不同而已,比如时间日期类可以操作时间和日期,而日期类只能操作日期而不能操作时间
}
}
Instant时间戳
public class TestDate {
//2. Instant : 时间戳。 (使用 Unix 元年 1970年1月1日 00:00:00 所经历的毫秒值)
public static void main(String[] args) throws Exception{
Instant ins = Instant.now(); //默认使用 UTC 时区(世界协调时间)
System.out.println(ins);
OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));//偏移量计算,utc和北京时间差8小时
System.out.println(odt);
System.out.println(ins.toEpochMilli());//打印时间戳
Instant ins2 = Instant.ofEpochSecond(1);//1970-01-01T00:00:00加上多少毫秒
System.out.println(ins2);
}
}
Duration : 用于计算两个“时间”间隔
Period : 用于计算两个“日期”间隔
public class TestDate {
//Duration : 用于计算两个“时间”间隔
//Period : 用于计算两个“日期”间隔
public static void main(String[] args) throws Exception{
Instant ins1 = Instant.now();
System.out.println("--------------------");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
Instant ins2 = Instant.now();
System.out.println("所耗费时间为(毫秒):" + Duration.between(ins1, ins2).toMillis());
System.out.println("----------------------------------");
LocalDate ld1 = LocalDate.now();
LocalDate ld2 = LocalDate.of(2011, 1, 1);
Period pe = Period.between(ld2, ld1);
System.out.println(pe.getYears());
System.out.println(pe.getMonths());
System.out.println(pe.getDays());
}
}
TemporalAdjuster : 时间校正器(比如下一个周日,下一年等操作)
public class TestDate {
// TemporalAdjuster : 时间校正器(比如下一个周日,下一年等操作)
public static void main(String[] args) throws Exception{
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
//比如月中的天指定为10
LocalDateTime ldt2 = ldt.withDayOfMonth(10);
System.out.println(ldt2);
//如何下一个周日,TemporalAdjusters还有好多方法,自己查看API
LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(ldt3);
//自定义:下一个工作日
LocalDateTime ldt5 = ldt.with((l) -> {
LocalDateTime ldt4 = (LocalDateTime) l;
//拿到目前是周几
DayOfWeek dow = ldt4.getDayOfWeek();
if(dow.equals(DayOfWeek.FRIDAY)){//如果是周五+3天
return ldt4.plusDays(3);
}else if(dow.equals(DayOfWeek.SATURDAY)){//如果是周6+2天
return ldt4.plusDays(2);
}else{//其他的都+1天
return ldt4.plusDays(1);
}
});
System.out.println(ldt5);
}
}
DateTimeFormatter : 解析和格式化日期或时间
// DateTimeFormatter : 解析和格式化日期或时间
public static void main(String[] args) throws Exception {
// 可以用他规定好的格式
// DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE;
// 也可以自己定义格式化标准
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss E");
//格式化
LocalDateTime ldt = LocalDateTime.now();
String strDate = ldt.format(dtf);
System.out.println(strDate);
//再解析回去
LocalDateTime newLdt = ldt.parse(strDate, dtf);
System.out.println(newLdt);
}
ZonedDate、ZonedTime、ZonedDateTime : 带时区的时间或日期
//6.ZonedDate、ZonedTime、ZonedDateTime : 带时区的时间或日期
@Test
public void test7(){
//获取一个指定时区构建一个时间
LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(ldt);
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("US/Pacific"));
System.out.println(zdt);
}
@Test
public void test6(){
//打印看一下java8支持多少时区
Set<String> set = ZoneId.getAvailableZoneIds();
set.forEach(System.out::println);
}