新的时间和日期API
在Java 8之前,所有关于时间和日期的API都存在各种使用方面的缺陷,主要有:
- Java的
和java.util.Date
类易用性差,不支持时区,而且他们都不是线程安全的;java.util.Calendar
- 用于格式化日期的类
被放在DateFormat
包中,它是一个抽象类,所以我们需要实例化一个java.text
对象来处理日期格式化,并且SimpleDateFormat
也是非线程安全,这意味着如果你在多线程程序中调用同一个DateFormat
对象,会得到意想不到的结果。DateFormat
- 对日期的计算方式繁琐,而且容易出错,因为月份是从0开始的,从
中获取的月份需要加一才能表示当前月份。Calendar
LocalDate,LocalTime
初始化:
LocalDate ld = LocalDate.of(2018,9,9);
LocalTime lt = LocalTime.of(12,12,12);
获取当前时间:
ld = LocalDate.now();
lt = LocalTime.now();
查看详情
int year = ld.getYear();
Month month = ld.getMonth();
int day = ld.getDayOfMonth();
DayOfWeek weekday = ld.getDayOfWeek();
int hour = lt.getHour();
int minute = lt.getMinute();
int second = lt.getSecond();
LocalDateTime
初始化
LocalDate ld = LocalDate.of(2018,9,9);
LocalTime lt = LocalTime.of(12,12,12);
LocalDateTime ldt = ld.atTime(lt);
LocalDateTime ldt1 = lt.atDate(ld);
localDateTime => localDate/localTime
ld = ldt.toLocalDate
lt = ldt.toLocalTime
parse
String => LocalDateTime
String s = “2013-01-02 12:22:22”;
DateTimeFormatter df = DateTimeFormatter.ofPattern(“yyyy-MM-dd HH:mm:ss”);
LocalDateTime ldt = LocalDateTime.parse(s,df);
String => LocalDate/LocalTime
String sdate = “2013-01-02”;
String stime = “22:22:22”;
LocalDate ld = LocalDate.parse(sdate);
LocalTime lt = LocalTime.parse(stime);
Instant
Instant
用于表示一个时间戳,它与我们常使用的
System.currentTimeMillis()
有些类似,不过Instant可以精确到纳秒(Nano-Second),
System.currentTimeMillis()
方法只精确到毫秒(Milli-Second)。如果查看
Instant
源码,发现它的内部使用了两个常量,seconds表示从1970-01-01 00:00:00开始到现在的秒数,nanos表示纳秒部分(nanos的值不会超过999,999,999)。
Instant
除了使用
now()
方法创建外,还可以通过
ofEpochSecond
方法创建:
Instant instant = Instant.ofEpochSecond(120, 100000);
ofEpochSecond()
方法的第一个参数为秒,第二个参数为纳秒,上面的代码表示从1970-01-01 00:00:00开始后两分钟的10万纳秒的时刻
Duration
Duration
的内部实现与
Instant
类似,也是包含两部分:seconds表示秒,nanos表示纳秒。两者的区别是
Instant
用于表示一个时间戳(或者说是一个时间点),而
Duration
表示一个时间段,所以
Duration
类中不包含
now()
静态方法。可以通过
Duration.between()
方法创建
Duration
对象:
LocalDateTime from = LocalDateTime.of(2017, Month.JANUARY, 5, 10, 7, 0); // 2017-01-05 10:07:00
LocalDateTime to = LocalDateTime.of(2017, Month.FEBRUARY, 5, 10, 7, 0); // 2017-02-05 10:07:00
Duration duration = Duration.between(from, to); // 表示从 2017-01-05 10:07:00 到 2017-02-05 10:07:00 这段时间
long days = duration.toDays(); // 这段时间的总天数
long hours = duration.toHours(); // 这段时间的小时数
long minutes = duration.toMinutes(); // 这段时间的分钟数
long seconds = duration.getSeconds(); // 这段时间的秒数
long milliSeconds = duration.toMillis(); // 这段时间的毫秒数
long nanoSeconds = duration.toNanos(); // 这段时间的纳秒数
Duration
对象还可以通过
of()
方法创建,该方法接受一个时间段长度,和一个时间单位作为参数:
Duration duration1 = Duration.of(5, ChronoUnit.DAYS); // 5天
Duration duration2 = Duration.of(1000, ChronoUnit.MILLIS); // 1000毫秒
Period
Period
在概念上和
Duration
类似,区别在于
Period
是以年月日来衡量一个时间段,比如2年3个月6天:
Period period = Period.of(2, 3, 6);
Period
对象也可以通过
between()
方法创建,值得注意的是,由于
Period
是以年月日衡量时间段,所以
between()
方法只能接收
LocalDate
类型的参数:
Period period2 = Period.between(LocalDate.of(2017, 1, 5),LocalDate.of(2017, 2, 5));
Period
对象可以获得时间段的长度:
int dayP2 = period2.getDays();
int monthP2 = period2.getMonths();
int yearP2 = period2.getYears()
注意,
Period
获得的时间段长度不是总的长度,如:
Period period2 = Period.between(LocalDate.of(2017, 1, 5),LocalDate.of(2017, 2, 5));
int day = period2.getDays(); // day=0
时区
参考
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;
public class LocalDateAndTime {
public static void main(String[] args) throws Exception {
LocalDate ld = LocalDate.of(2019,3,10);
LocalTime lt = LocalTime.of(11,12,12);
int year = ld.getYear();
System.out.println("年:" + year);
Month month = ld.getMonth();
System.out.println("月:" + month);
int day = ld.getDayOfMonth();
System.out.println("日" + day);
DayOfWeek weekday = ld.getDayOfWeek();
System.out.println("周" + weekday);
int hour = lt.getHour();
System.out.println("小时" + hour);
int minute = lt.getMinute();
System.out.println("分钟" + minute);
int second = lt.getSecond();
System.out.println("秒" + second);
System.out.println(ld);
System.out.println(lt);
String sdate = "2013-01-02";
String stime = "22:22:22";
ld = LocalDate.parse(sdate);
lt = LocalTime.parse(stime);
System.out.println(ld);
System.out.println(lt);
ld = LocalDate.now();
lt = LocalTime.now();
System.out.println(ld);
System.out.println(lt);
System.out.println("=========");
String s = "2013-01-02 12:22:22";
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime ldt = LocalDateTime.parse(s,df);
System.out.println(ldt);
ldt = lt.atDate(ld);
System.out.println(ldt);
ldt = ld.atTime(lt);
System.out.println(ldt);
ld = ldt.toLocalDate();
lt = ldt.toLocalTime();
System.out.println(ld);
System.out.println(lt);
System.out.println("=========");
LocalDate hd = LocalDate.of(2019,3,10);
System.out.println(ld == hd);
System.out.println(ld.equals(hd));
LocalDateTime ss = ld.atStartOfDay();
System.out.println(ld);
System.out.println(ld.withMonth(1));
System.out.println(ld.withDayOfMonth(1));
LocalDate md = LocalDate.now();
System.out.println(ld);
System.out.println(md);
Long i = ld.toEpochDay()-md.toEpochDay()+1;
Long j = hd.toEpochDay()-ld.toEpochDay();
System.out.println(i);
System.out.println(j);
System.out.println((double)i/j*3);
System.out.println(Math.floor((double)i/j*3));
System.out.println(Math.ceil((double)i/j*3));
System.out.println("=========");
LocalDateTime from = LocalDateTime.of(2017, Month.JANUARY, 5, 10, 7, 0); // 2017-01-05 10:07:00
LocalDateTime to = LocalDateTime.of(2017, Month.FEBRUARY, 5, 10, 7, 0); // 2017-02-05 10:07:00
Duration duration = Duration.between(from, to); // 表示从 2017-01-05 10:07:00 到 2017-02-05 10:07:00 这段时间
long days = duration.toDays(); // 这段时间的总天数
System.out.println("天数" + days);
long hours = duration.toHours(); // 这段时间的小时数
System.out.println("小时数" + hours);
long minutes = duration.toMinutes(); // 这段时间的分钟数
System.out.println("分钟数" + minutes);
long seconds = duration.getSeconds(); // 这段时间的秒数
System.out.println("秒数" + seconds);
long milliSeconds = duration.toMillis(); // 这段时间的毫秒数
System.out.println("毫秒数" + milliSeconds);
long nanoSeconds = duration.toNanos(); // 这段时间的纳秒数
System.out.println("纳秒数" + nanoSeconds);
Duration duration1 = Duration.of(5, ChronoUnit.DAYS); // 5天
long days1 = duration1.toDays(); // 这段时间的总天数
System.out.println("天数1:" + days1);
Duration duration2 = Duration.of(1000, ChronoUnit.MILLIS); // 1000毫秒
long milliSeconds2 = duration2.toMillis(); // 这段时间的毫秒数
System.out.println("毫秒数2:" + milliSeconds2);
System.out.println("=========");
Period period = Period.of(2, 3, 6);
int dayP1 = period.getDays();
int monthP1 = period.getMonths();
int yearP1 = period.getYears();
System.out.println("Period Days:" + dayP1 + ", Months:" + monthP1 + ", Years:" + yearP1);
// 2017-01-05 到 2017-02-05 这段时间
Period period2 = Period.between(LocalDate.of(2017, 1, 5),LocalDate.of(2017, 2, 5));
int dayP2 = period2.getDays();
int monthP2 = period2.getMonths();
int yearP2 = period2.getYears();
System.out.println("Period2 Days:" + dayP2 + ", Months:" + monthP2 + ", Years:" + yearP2);
period2 = Period.between(LocalDate.of(2017, 1, 4),LocalDate.of(2020, 3, 5));
dayP2 = period2.getDays();
monthP2 = period2.getMonths();
yearP2 = period2.getYears();
System.out.println("Period2 Days:" + dayP2 + ", Months:" + monthP2 + ", Years:" + yearP2);
System.out.println("Period获得的时间段长度不是总的长度,比如获得的天数,与月份和年份无关");
System.out.println("=========");
}
}