当我们开始使⽤Java操作⽇期和时间的时候,会有⼀些棘⼿。你也许会通过 System.currentTimeMillis() 来返回1970年1⽉1⽇到今天的毫秒数。或者使⽤ Date类来操作⽇期;当遇到加减⽉份、天数的时候 你⼜需要⽤到Calendar类; 当需要格式化⽇期的时候需要使⽤java.text.DateFormat类。 总⽽⾔之在Java中 操作⽇期不是很⽅便,以⾄于很多开发者不得不使⽤第三⽅库,⽐如: jodatime。
这是新的Java⽇期/时间API的基础包,所有的主要基础类都 是这个包的⼀部分,如:LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration等等。所有这些类都是不可变的和线程安全的,在绝⼤多数 情况下,这些类能够有效地处理⼀些公共的需求。
这个包为⾮ISO的⽇历系统定义了⼀些泛化的API, 我们可以扩展AbstractChronology类来创建⾃⼰的⽇历系统。
这个包包含能够格式化和解析⽇期时间对象的类,在绝⼤多数情况下,我们不应该直接使⽤它们,因为java.time包中相应的类已 经提供了格式化和解析的⽅法。 java.time.temporal包:这个包包含⼀些时态对象,我们可以⽤其找出关于 ⽇期/时间对象的某个特定⽇期或时间,⽐如说,可以找到某⽉的第⼀天或最后⼀天。你可以⾮常容易地认出这些⽅法,因为它们都具有“withXXX”的格 式。
这个包包含⽀持不同时区以及相关规则的类。
最常用的就是LocalDate,LocalTime,LocalDateTime三个类,API很类似,所以接下来以LocalDateTime进行演示
//获取当前时间
LocalDateTime today = LocalDateTime.now();
//使用LocalDate and LocalTime 创建LocalDateTime
today = LocalDateTime.of(LocalDate.now(), LocalTime.now());
//通过of方法参数创建
LocalDateTime specificDate = LocalDateTime.of(2014, Month.JANUARY, 1, 10, 10, 30);
//不正确的参数会抛出异常
//Exception in thread "main" java.time.DateTimeException: Invalid value for HourOfDay (valid values 0 - 23): 25
LocalDateTime illegalDate = LocalDateTime.of(2014, Month.FEBRUARY, 28, 25,1,1);
//获取"Asia/Kolkata",加尔哥达
LocalDateTime todayKolkata = LocalDateTime.now(ZoneId.of("Asia/Kolkata"));
//通过时间戳获取时间
LocalDateTime dateFromBase = LocalDateTime.ofEpochSecond(10000, 0, ZoneOffset.UTC);
LocalDateTime today = LocalDateTime.now();
//获取当前年,并判断是否是闰年
System.out.println("Year " + today.getYear() + " is Leap Year? " + today.toLocalDate().isLeapYear());
//比较两个日期的先后
System.out.println("Today is before 01/01/2015? " + today.isBefore(LocalDateTime.of(2015,1, 1, 11, 30)));
//时间加减
System.out.println("10 days after today will be " + today.plusDays(10));
System.out.println("3 weeks after today will be " + today.plusWeeks(3));
System.out.println("20 months after today will be " + today.plusMonths(20));
System.out.println("10 days before today will be " + today.minusDays(10));
System.out.println("3 weeks before today will be " + today.minusWeeks(3));
System.out.println("20 months before today will be " + today.minusMonths(20));
//查询日期的特定点
System.out.println("First date of this month= " + today.with(TemporalAdjusters.firstDayOfMonth()));
LocalDate lastDayOfYear = today.toLocalDate().with(TemporalAdjusters.lastDayOfYear());
System.out.println("Last date of this year= " + lastDayOfYear);
//两个日期间的间隔
Period period = today.toLocalDate().until(lastDayOfYear);
System.out.println("Period Format= " + period);
LocalDateTime now = LocalDateTime.now();
String formatTime = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd mm:ss"));
System.out.println(formatTime);
//Date转换为新的API
Date date = new Date();
LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.of(ZoneId.SHORT_IDS.get("PST")));
//LocalDateTime转换为Date
Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
//Calendar转换为Instant
Instant time = Calendar.getInstance().toInstant();
//TimeZone 转换为 ZoneId
ZoneId defaultZone = TimeZone.getDefault().toZoneId();
System.out.println(defaultZone);
工具类地址
不安全的SimpleDateFormat
public class UnSafeDateFormatExample0 {
private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
final CountDownLatch countDownLatch = new CountDownLatch(5000);
final Semaphore semaphore = new Semaphore(50);
for (int i = 0; i < 5000; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
format();
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
}
private static void format() {
try {
format.parse("1999-12-01 12:12");
} catch (ParseException e) {
e.printStackTrace();
}
}
}