java.time包中的是类是不可变且线程安全的。
新的时间及日期API位于java.time中,下面是一些关键类
●Instant——它代表的是时间戳,注意这里默认的Instant是0时区,比北京少8个时区,例子:2018-10-08T09:50:21.852Z,相当于当天北京时间的17:50:21.852
●LocalDate——不包含具体时间的日期,比如2014-01-14。它可以用来存储生日,周年纪念日,入职日期等。
●LocalTime——它代表的是不含日期的时间
●LocalDateTime——它包含了日期及时间,不过还是没有偏移信息或者说时区。
●ZonedDateTime——这是一个包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准的,如:2018-10-08T18:12:38.547+08:00[Asia/Shanghai]。
Date转化为Instant时间戳,然后instant和系统默认时区转化成LocalDate
/**
* Date转LocalDate: Date -> Instant + System default time zone = LocalDate
*/
@Test
public void dateToLocalDateAndLocalDateTime(){
Date date = new Date();
Instant instant = date.toInstant();
/**
* instant : 2018-10-08T09:50:21.852Z
* Zone : UTC+0
* 注意这里默认的Instant是比北京少8个时区
*/
//获得本地默认时区
ZoneId defaultZoneId = ZoneId.systemDefault();
LocalDate localDate = instant.atZone(defaultZoneId).toLocalDate();
System.out.println(localDate); //2018-10-08
}
Date转化成本地系统时区的LocalDateTime
@Test
public void dateToLocalDateTime(){
Date date = new Date();
Instant instant = date.toInstant();
//系统默认的时区
ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId);
System.out.println(localDateTime);
}
long -> Instant +System default time zone = LocalDate
public LocalDate longToLocalDate(Long time){
//System Default TimeZone : Asia/Shanghai
ZoneId defaultZoneId = ZoneId.systemDefault();
//2018-01-04T16:00:00Z
//时间戳
Instant instant = Instant.ofEpochMilli(time);
//2018-01-05
LocalDate localDate = instant.atZone(defaultZoneId).toLocalDate();
return localDate;
}
Java8中有个叫LocalDate的类,能用来表示日期。这个类与java.util.Date略有不同,因为它只包含日期,没有时间。
/**
* 判断两个日期相差多少天
*/
@Test
public void localDateDiff(){
LocalDate date1 = LocalDate.of(2018,9,20);
LocalDate date2 = LocalDate.of(2018,10,3);
long l = date2.toEpochDay() - date1.toEpochDay();
System.out.println(l);
}
/**
* 获得某个日期所在月的第一天、最后一天
*/
@Test
public void firstLastDay(){
LocalDate localDate = LocalDate.of(2018, 2, 22);
LocalDate firstDay = localDate.with(TemporalAdjusters.firstDayOfMonth());
LocalDate lastDay = localDate.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("firstDay: "+firstDay+" lastDay: "+lastDay);
//firstDay: 2018-02-01 lastDay: 2018-02-28
}
先获取该月的最后一天的LocalDate,再调用getDayOfMonth()方法
/**
* 某个月有多少天
*/
@Test
public void getDayOfMonth(){
LocalDate localDate = LocalDate.of(2018, 2, 22);
LocalDate lastDay = localDate.with(TemporalAdjusters.lastDayOfMonth());
int dayOfMonth = lastDay.getDayOfMonth();
System.out.println(dayOfMonth);
//28
}
/**
* 比较两个LocalDate的大小
*/
@Test
public void localDateCompareTo(){
LocalDate date1 = LocalDate.of(2018,9,20);
LocalDate date2 = LocalDate.of(2018,10,3);
int i = date1.compareTo(date2);
System.out.println(i);
//-1 小
int i1 = date2.compareTo(date1);
System.out.println(i1);
//1 大
int i2 = date1.compareTo(date1);
System.out.println(i2);
//0 等于
}
/**
* 获取下一周的该星期、下个月的这天、下个月的1号
*/
@Test
public void nextMonth(){
LocalDate localDate = LocalDate.of(2018, 2, 12);
//下一周的该星期
LocalDate localDate1 = localDate.minusWeeks(-1);
System.out.println(localDate1);
//2018-02-19
//获取下个月的这天
LocalDate localDate2 = localDate.minusMonths(-1);
System.out.println(localDate2);
//2018-03-12
//下个月的1号
LocalDate localDate3 = LocalDate.of(localDate.getYear(), localDate.getMonthValue()+1, 1);
System.out.println(localDate3);
//2018-03-01
}
Period这个类,这里比较的是两个日期,相差多少年、多少个月、多少天;
比如下面的这个例子中,2018.10.9 比 2019.4.1相差 0年 5个月 23天
/**
* 比较两个LocalDate相差多少年、月、日
*/
@Test
public void localDatePeriod(){
LocalDate date1 = LocalDate.of(2018,10,9);
LocalDate date2 = LocalDate.of(2019,4,1);
Period period = Period.between(date1, date2);
int years = period.getYears();
int months = period.getMonths();
int days = period.getDays();
System.out.println("years:"+years+", months:"+months+", days:"+days);
//years:0, months:5, days:23
}
@Test
public void ofEpochSecond(){
Instant now = Instant.now();
System.out.println(now);
//2019-03-13T06:41:32.865Z
//去除毫秒
long l = now.toEpochMilli() / 1000;
//通过秒构建Instant对象
Instant instant = Instant.ofEpochSecond(l);
System.out.println(instant);
//2019-03-13T06:41:32Z
}
由下面例子总结:
Instant
只能解析"**T**Z
”这种格式的时间,即UTC字符串;
ZonedDateTime
解析的时间字符串必须是要有年月日时分秒
以及时区
;
LocalDateTime
解析的时间字符串必须要有年月日时分秒
,但是不能有时区
,例如末尾有"Z"的时间表示UTC的0时区就不能解析;
LocalDate
解析的时间字符串必须只能有年月日
,格式如"2018-12-07",多任何其他字符都不能解析。
/**
* 解析字符串:2018-12-07T09:33:38+00:00
* ZonedDateTime必须解析有时区的时间
*/
@Test
public void stringToZonedDateTime(){
final String string ="2018-12-07T09:33:38+00:00";
ZonedDateTime parse = ZonedDateTime.parse(string);
System.out.println(parse.toString());
//结果是2018-12-07T09:33:38Z
ZoneId zone = parse.getZone();
System.out.println(zone);
}
/**
* 解析字符串:2018-12-07T09:33:38Z,无法解析2018-12-07T09:33:38+00:00
* Instant只能解析"**T**Z”这种格式的时间
*/
@Test
public void stringToInstant(){
final String string ="2018-12-07T09:33:38Z";
Instant parse = Instant.parse(string);
System.out.println(parse);
//2018-12-07T09:33:38Z
}
/**
* 解析字符串:2018-12-07T09:33:38Z
* 表示的是0时区的时间
*/
@Test
public void stringToZonedDateTime1(){
final String string ="2018-12-07T09:33:38Z";
ZonedDateTime parse = ZonedDateTime.parse(string);
System.out.println(parse.toString());
//结果是2018-12-07T09:33:38Z
ZoneId zone = parse.getZone();
System.out.println(zone);
}
/**
* 解析字符串:2018-12-07T09:33:38,末尾不能有Z,有T有Z代表了UTC 0时区的时间,还必须要有"T时分秒"这一截字符串
* LocaDateTime无法解析带有时区的字符串时间
*/
@Test
public void stringToLocalDateTime(){
final String string ="2018-12-07T09:33:38";
LocalDateTime parse = LocalDateTime.parse(string);
System.out.println(parse.toString());
//结果是2018-12-07T09:33:38
}
/**
* 解析字符串:2018-12-07,只能解析该格式字符串
* LocaDate无法解析带有时区的字符串时间
*/
@Test
public void stringToLocalDate(){
final String string ="2018-12-07";
LocalDate parse = LocalDate.parse(string);
System.out.println(parse.toString());
//结果是2018-12-07
}
ZoneID.of(String zoneId) 时区参数
这里的zoneId字符串可以传入"Asia/Shanghai",字符串如下:
/**
* 把无时区的时间LocaDateTime解析成有时区的ZonedDateTime
*/
@Test
public void localDateTimeToZonedDateTime(){
final String string ="2018-12-07T09:33:38";
LocalDateTime parse = LocalDateTime.parse(string);
ZonedDateTime z1 = ZonedDateTime.of(parse, ZoneId.of("Asia/Shanghai"));
System.out.println(z1.toString());
//2018-12-07T09:33:38+08:00[Asia/Shanghai]
ZonedDateTime z2 = ZonedDateTime.of(parse, ZoneId.of("Z"));
System.out.println(z2.toString());
//2018-12-07T09:33:38Z
ZonedDateTime z3 = ZonedDateTime.of(parse, ZoneId.of("UTC"));
System.out.println(z3.toString());
//2018-12-07T09:33:38Z[UTC]
ZonedDateTime z4 = ZonedDateTime.of(parse, ZoneId.of("UTC+08:00"));
System.out.println(z4.toString());
//2018-12-07T09:33:38+08:00[UTC+08:00]
ZonedDateTime z5 = ZonedDateTime.of(parse, ZoneId.of("+08:00"));
System.out.println(z5.toString());
//2018-12-07T09:33:38+08:00
ZonedDateTime z6 = ZonedDateTime.of(parse, ZoneId.of("+00:00"));
System.out.println(z6.toString());
//2018-12-07T09:33:38Z
}
由结果可知,String zoneId的字符串值,如果为:
“Asia/Shanghai"例子为"2018-12-07T09:33:38+08:00[Asia/Shanghai]” ;
“Z"和”+00:00"表示的是"2018-12-07T09:33:38Z"这种格式的时间;
“UTC"表示的是"2018-12-07T09:33:38Z[UTC]” ;
“UTC+08:00” 例子:“2018-12-07T09:33:38+08:00[UTC+08:00]” ;
“+08:00” 例子:“2018-12-07T09:33:38+08:00”
部分参考:
https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html
http://www.mkyong.com/java8/java-8-convert-date-to-localdate-and-localdatetime/
https://www.cnblogs.com/comeboo/p/5378922.html