LocalDateTime
1. 环境
Since JDK8
LocalDateTime 的好处
- 每一个时间对象,都是线程安全的
- 每一个对象都没有公开的构造器,如果需要一个对象你首先想的不是 new,而是静态工厂方法: now、of、from
- 如果你喜欢敲全类名,请在使用时间api时忘记java.util和java.text,记住java.time
2. 代码
为什么建议使用你 LocalDateTime ,而不是 Date?
根据这篇博客学习,下面练习的代码, 并附上了输出结果.
JDK8 新增的 java.time 这篇讲得好
JDK8 的新特性 这个不错
2.1 LocalDate: 获取年月日
/** LocalDate: 获取年月日 */
@Test
public void m1() {
//获取当前年月日
LocalDate localDate = LocalDate.now();
//构造指定的年月日
LocalDate localDate1 = LocalDate.of(2019, 9, 10);
System.out.println("localDate = " + localDate); // localDate = 2020-07-04
System.out.println("localDate1 = " + localDate1); // localDate1 = 2019-09-10
int year = localDate.getYear();
System.out.println("year = " + year); // year = 2020
int year1 = localDate.get(ChronoField.YEAR);
System.out.println("year1= " + year1); // year1= 2020
Month month = localDate.getMonth();
System.out.println("month= " + month); // month= JULY
int month1 = localDate.get(ChronoField.MONTH_OF_YEAR);
System.out.println("month1= " + month1); // month1= 7
int day = localDate.getDayOfMonth();
System.out.println("day= " + day); // day= 6
int day1 = localDate.get(ChronoField.DAY_OF_MONTH);
System.out.println("day1= " + day1); // day1= 6
DayOfWeek dayOfWeek = localDate.getDayOfWeek();
System.out.println("dayOfWeek= " + dayOfWeek); // dayOfWeek= MONDAY
int dayOfWeek1 = localDate.get(ChronoField.DAY_OF_WEEK);
System.out.println("dayOfWeek1= " + dayOfWeek1); // dayOfWeek1= 1
}
2.2 LocalTime: 获取时分秒
/** LocalTime: 获取时分秒 */
@Test
public void m2() {
// 获取当前时分秒
LocalTime localTime = LocalTime.now();
// 构造指定的时分秒
LocalTime localTime1 = LocalTime.of(10, 30, 55);
System.out.println("localTime= " + localTime); // localTime= 10:34:27.591553
System.out.println("localTime1= " + localTime1); // localTime1= 10:30:55
//获取小时
int hour = localTime.getHour();
int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);
System.out.println("hour= " + hour); // hour= 10
System.out.println("hour1= " + hour1); // hour1= 10
//获取分
int minute = localTime.getMinute();
int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);
System.out.println("minute = " + minute); // minute = 34
System.out.println("minute1 = " + minute1); // minute1 = 34
//获取秒
int second = localTime.getSecond();
int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);
System.out.println("second = " + second); // second = 27
System.out.println("second1 = " + second1); // second1 = 27
}
2.3 LocalDateTime: 获取年月日时分秒
/** LocalDateTime: 获取年月日时分秒 */
@Test
public void m3() {
//获取当前年月日
LocalDate localDate = LocalDate.now();
// 获取当前时分秒
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime localDateTime1 = LocalDateTime.of(LocalDate.of(2020, 7, 3), LocalTime.of(10, 38, 55));
LocalDateTime localDateTime2 = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);
LocalDateTime localDateTime3 = localDate.atTime(localTime); // 相当于 localDate + localTime = LocalDateTime
LocalDateTime localDateTime4 = localTime.atDate(localDate); // 相当于 localDate + localTime = LocalDateTime
System.out.println("localDateTime = " + localDateTime); // localDateTime = 2020-07-06T10:40:10.128524
System.out.println("localDateTime1 = " + localDateTime1); // localDateTime1 = 2020-07-03T10:38:55
System.out.println("localDateTime2 = " + localDateTime2); // localDateTime2 = 2019-09-10T14:46:56
System.out.println("localDateTime3 = " + localDateTime3); // localDateTime3 = 2020-07-08T14:58:20.685306
System.out.println("localDateTime4 = " + localDateTime4); // localDateTime4 = 2020-07-08T14:58:20.685306
// 获取LocalDate
LocalDate localDate2 = localDateTime.toLocalDate();
// 获取LocalTime
LocalTime localTime2 = localDateTime.toLocalTime();
System.out.println("localDate2 = " + localDate2); // localDate2 = 2020-07-08; localDateTime = 2020-07-08T15:05:34.630987
System.out.println("localTime2 = " + localTime2); // localTime2 = 15:05:34.630987; localDateTime = 2020-07-08T15:05:34.630987
// 获取秒数. ( 用 System.currentTimeMills()更方便 )
Instant instant = Instant.now();
long currentSecond = instant.getEpochSecond();
long timeStamp1 = instant.toEpochMilli();
long timeStamp2 = System.currentTimeMillis();
System.out.println("currentSecond = " + currentSecond); // currentSecond = 1594192226
System.out.println("timeStamp1 = " + timeStamp1); // timeStamp1 = 1594192226826
System.out.println("timeStamp2 = " + timeStamp2); // timeStamp2 = 1594192226826
}
2.4 LocalDateTime 年月日时分秒的 操作.
/**
* LocalDateTime 年月日时分秒的 操作.
*
* LocalDate、LocalTime、LocalDateTime、Instant为不可变对象,修改这些对象对象会返回一个副本
*
* plusXX(): 在原来的基础上加
* withXX(): 直接设定值
*/
@Test
public void m4() {
LocalDateTime localDateTime = LocalDateTime.of(1997, Month.FEBRUARY, 2, 9, 13, 14);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1997-02-02T09:13:14
//增加一年 plusYears()
localDateTime = localDateTime.plusYears(1);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1998-02-02T09:13:14
localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1999-02-02T09:13:14
// 减少一年 minusYears()
localDateTime = localDateTime.minusYears(1);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1998-02-02T09:13:14
//减少一个月 minusMonths(); 同理增加一月 就是 plusMonths(); 还可以修改 日、时分秒、周等等.
localDateTime = localDateTime.minusMonths(1);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1998-01-02T09:13:14
localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1997-12-02T09:13:14
/* with: 设定值 */
//修改年为2020
localDateTime = localDateTime.withYear(2020);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 2020-12-02T09:13:14
//修改为2022
localDateTime = localDateTime.with(ChronoField.YEAR, 2022);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 2022-12-02T09:13:14
}
2.5 时间计算
/**
* 时间计算
*
* 比如有些时候想知道这个月的最后一天是几号、下个周末是几号,通过提供的时间和日期API可以很快得到答案
*/
@Test
public void m5() {
LocalDate localDate = LocalDate.now();
System.out.println("localDate = " + localDate); // localDate = 2020-07-08
// 年的第一天
LocalDate localDate1 = localDate.with(TemporalAdjusters.firstDayOfYear());
System.out.println("localDate1 = " + localDate1); // localDate1 = 2020-01-01
// 月的第一天; 还有很多其他的, 点进去看吧.
localDate = localDate.with(TemporalAdjusters.firstDayOfMonth());
System.out.println("localDate = " + localDate); // localDate = 2020-07-01
}
2.6 格式化时间
LocalDateTime -> String
/**
* 格式化时间
*
* DateTimeFormatter默认提供了多种格式化方式,如果默认提供的不能满足要求,可以通过DateTimeFormatter的ofPattern方法创建自定义格式化方式
*/
@Test
public void m6() {
LocalDate localDate = LocalDate.of(2019, 9, 10);
String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
//自定义格式化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String s3 = localDate.format(dateTimeFormatter);
System.out.println("localDate = " + localDate); // localDate = 2019-09-10
System.out.println("s1 = " + s1); // s1 = 20190910
System.out.println("s2 = " + s2); // s2 = 2019-09-10
System.out.println("s3 = " + s3); // s3 = 10/09/2019
// LocalDateTime 转换成 特定格式的 字符串
LocalDateTime now = LocalDateTime.now();
String nowStr1 = now.format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
String nowStr2 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
System.out.println("now = " + now); // now = 2020-07-08T16:41:12.647672
System.out.println("nowStr1 = " + nowStr1); // nowStr1 = 2020/07/08 16:41:12
System.out.println("nowStr2 = " + nowStr2); // nowStr2 = 2020-07-08 16:42
// format 是线程不安全的. 用 parse() 方法时候 需要特定格式的, 并且还要 try-catch
String dateStr = "";
Date date = new Date();
if (date != null) {
dateStr = new SimpleDateFormat("yyyy MM dd HH:mm").format(date);
}
System.out.println("dateStr = " + dateStr); // dateStr = 2020 07 08 16:43
}
2.7 解析时间:
String -> LocalDateTime
/**
* 解析时间: 感觉还是 SimpleDateTime好用, 即使它线程不安全, 但是在开辟一个线程处理 好了.
*
* 注意:
* 1. 要解析的字符串, 格式必须要和 设定的pattern是一致的, 不然就报错。
* 2. 使用 解析必须要 try-catch, SimpleDateFormate的parse还会提示要处理异常, LocalDateTime居然不提示...
*/
@Test
public void m7() {
String dateStr = "1997-02-02 17:13:14";
LocalDateTime localDateTime = null;
try {
localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1997-02-02T17:13:14
/*
* 自我感觉 没 SimpleDateTime好用啊... 虽然 SimpleDateTime是线程不安全的
*
* 1. LocatDateTime的parse() 使用 LocalDateTime 那字符串必须要 年月日 时分秒, 如果只写年月日, 就算 ofPattern("yyyy-MM-dd") 也不行. 需要用 LocalDate.parse()
* 2. 而SimpleDateFormat.parse() 就算只写了 "yyyy-MM-dd" 只需要保证 年月日是此格式即可, 后面的时分秒无所谓.
*/
Date date = null;
try {
date = new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("date = " + date); // date = Sun Feb 02 00:00:00 CST 1997
// LocalDate, 这样是不会报错的, 字符串只写了年月日 就必须用 LocalDate来解析.
String dateStr2 = "1997-02-02";
LocalDate localDate = null;
try {
localDate = LocalDate.parse(dateStr2, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("localDate = " + localDate); // localDate = 1997-02-02
}
2.8 看得懂的时间输出
挺好用的东西… JDK 14 会报错, JDK8没问题
/** 挺好用的东西.. JDK 14 会报错, JDK8没问题 */
@Test
public void m8() {
LocalDateTime d1=LocalDateTime.now();
FormatStyle dateTimeStyle=FormatStyle.LONG;
Locale.setDefault(Locale.CHINA);
DateTimeFormatter formater=DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
String format = d1.format(formater);
System.out.println(format);//2017年11月30日 下午04时10分32秒
dateTimeStyle=FormatStyle.MEDIUM;
Locale.setDefault(Locale.CHINA);
formater=DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
format = d1.format(formater);
System.out.println(format);//2017-11-30 16:10:32
Locale.setDefault(Locale.UK);
format = d1.format(formater);
System.out.println(formater);//2017-11-30 16:10:32
// Locale.setDefault 和 DateTimeFormatter.ofLocalizedDateTime 必须重新设置一次, 否则像上面这样的输出结果和 第2个一样
Locale.setDefault(Locale.UK);
formater=DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
format = d1.format(formater);
System.out.println(format);//30-Nov-2017 16:10:32
}
2.9 日期加减日期
2.91 LocalDateTime.util()
2.92 Duration.between()
public class Test02_LocalDateTime {
public static void main(String[] args) {
ZoneId zoneId = ZoneId.systemDefault();
System.out.println("zoneId = " + zoneId); // zoneId = Asia/Shanghai
LocalDateTime now = LocalDateTime.now();
String dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("dateStr1 = " + dateStr1);
LocalDateTime loc = LocalDateTime.of(1997, 07, 13, 14, 55, 59);
String dateStr2 = loc.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("locStr = " + dateStr2); // dateStr2 = 1997-07-13 14:55:00
/// JDK14 报错, JDK8 可以.
// FormatStyle formatStyle = FormatStyle.LONG;
// Locale.setDefault(Locale.CHINA);
// DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(formatStyle);
// String f1 = now.format(dateTimeFormatter);
// System.out.println("f1 = " + f1);
/*
* 日期加减日期
*
* 1. minusXX/plusXX: 只能单独加减年月日 or 时分秒的.
* TemporalAmount 实现类之一是: Duration
* 3. LocalDateTime.until(): 第二个参数 - 第一个参数 的出来的正负天数.
* 4. Duration.between(): 第二个参数 - 第一个参数 的出来的正负天数.
*/
Duration duration = Duration.between(now, loc);
System.out.println("duration = " + duration); // duration = PT-201690H-36M-19.603835S .
now = LocalDateTime.of(2020, 7, 16, 10, 13, 14);
dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 2020-07-16 10:13:14
// locStr = 1997-07-13 14:55:59
now = now.minusYears(loc.getYear()); // 1997
dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 0023-07-16 10:13:14
now = now.minusDays(loc.getDayOfMonth()); // 13
dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 0023-07-03 10:13:14
now = now.plusDays(13);
TemporalAmount amountToSubtract = Duration.ofDays(13);
now = now.minus(amountToSubtract);
dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 0023-07-03 10:13:14
/*
* 时间与时间的计算
*
* 两个时间之间的计算,结果为一个量。如,计算两个时间相隔多少天。
* 举例,计算2016年元旦到五一劳动节相隔多少天?
*/
LocalDateTime d1=LocalDateTime.of(2020, 07, 16, 11, 04);
LocalDateTime d2=LocalDateTime.of(1997, 01, 03, 13, 14);
System.err.println("d1 = " + d1.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); // d1 = 2020-07-16 11:04:00
System.err.println("d2 = " + d2.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); // d2 = 1997-01-03 13:14:00
long interval = d2.until(d1, ChronoUnit.DAYS);
System.out.println(interval); // 8594
// 也可以使用时间量的计算:
Duration d = Duration.between(d1, d2);
System.out.println(d.toDays()); // -8594
System.out.println(d.toHours()); // -206277
long age = d2.until(d1, ChronoUnit.YEARS);
System.out.println("age = " + age); // age = 23, 这个算年龄... 但是不算天数, 自己写的 age计算的工具类 会把天算上.
}
}
7.0 相关工具类
/** 听说是 解决 SImpleDateFormat线程不安全问题 */
private static final ThreadLocal<SimpleDateFormat> local = new ThreadLocal<SimpleDateFormat>();
private static SimpleDateFormat getTime() {
SimpleDateFormat sdf = local.get();
if (sdf == null) {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
local.set(sdf);
}
return sdf;
}
/** LocalDate转Date */
public static Date localDateToDate(LocalDate localDate) {
if (null == localDate) {
return null;
}
ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
return Date.from(zonedDateTime.toInstant());
}
/** Date转LocalDate */
public static LocalDate dateToLocalDate(java.util.Date date) {
if (null == date) {
return null;
}
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
/** Date转换为LocalDateTime */
public static LocalDateTime dateToLocalDateTime(Date date){
if (null == date) {
return null;
}
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
return localDateTime;
}
/** LocalDateTime转换为Date */
public static Date localDateTimeToDate( LocalDateTime localDateTime){
if (localDateTime == null) {
return null;
}
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}