Java8 LocalDateTime
在java8之前我們在處理時間的時候都是用的Date
,但它其實有很明顯的缺點。
1.我們也會對日期做一些操作,比如加幾天、加幾分,當月的最后一天等等。有些計算實現比較復雜。
2.也會用SimpleDateFormat來格式化日期。但SimpleDateFormat是線程不安全的。
所以現在一般都推薦使用LocalDateTime 它是線程安全的,並且性能更好,代碼更簡潔。
一、示例
新時間日期API常用、重要對象主要有下面三個:
LocalDate
: 只含年月日的日期對象
LocalTime
:只含時分秒的時間對象
LocalDateTime
: 同時含有年月日時分秒的日期對象
下面會通過示例來一一理解它們。
1、創建實例
public static void main(String[] args) {
//1、獲取當前日期
LocalDate now = LocalDate.now();
System.out.println("當前時間 = " + now);
//輸出: 當前時間 = 2020-07-06
//2、獲取指定日期(參數依次 年、月、日)
LocalDate localDate = LocalDate.of(2020, 6, 30);
System.out.println("年月日 = " + localDate);
//輸出: 年月日 = 2020-06-30
//3、獲取當前時間
LocalTime localTime = LocalTime.now();
System.out.println("localTime = " + localTime);
//輸出: localTime = 22:32:45.994
//4、獲取指定時間(參數依次 時、分、秒、納秒
LocalTime localTimeOf = LocalTime.of(12, 24, 12, 4444);
System.out.println("localTimeOf = " + localTimeOf);
//輸出: localTimeOf = 12:24:12.000004444
//5、獲取當前年月日,時分秒都有的日期
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("localDateTime = " + localDateTime);
//輸出: localDateTime = 2020-07-06T22:32:45.994
//6、獲取指定年月日,時分秒都有的日期(參數依次 年、月、日、時、分)
LocalDateTime localDateTimeOf = LocalDateTime.of(2020, 7, 30, 12, 12);
System.out.println("localDateTimeOf = " + localDateTimeOf);
//輸出: localDateTimeOf = 2020-07-30T12:12
//7、日期+時間 組成 包含年月日,時分秒都有的日期
LocalDateTime of = LocalDateTime.of(LocalDate.now(), LocalTime.now());
System.out.println("of = " + of);
//輸出: of = 2020-07-06T22:32:45.995
}
2、計算日期和時間
日期時間的加減
- 對於LocalDate,只有精度大於或等於日的加減,如年、月、日;
- 對於LocalTime,只有精度小於或等於時的加減,如時、分、秒、納秒;
- 對於LocalDateTime,則可以進行任意精度的時間相加減;
加法操作
public static void main(String[] args) {
//獲取當前時間
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("當前時間 = " + localDateTime);
//1、加1年
LocalDateTime plusYears = localDateTime.plusYears(1L);
System.out.println("plusYears = " + plusYears);
//輸出: plusYears = 2021-07-06T22:46:49.196
//2、加1個月
LocalDateTime plusMonths = localDateTime.plusMonths(1L);
System.out.println("plusMonths = " + plusMonths);
//輸出: plusMonths = 2020-08-06T22:46:49.196
//3、加一天
LocalDateTime plusDays = localDateTime.plusDays(1L);
System.out.println("plusDays = " + plusDays);
//輸出: plusDays = 2020-07-07T22:46:49.196
//4、加1個小時
LocalDateTime plusHours = localDateTime.plusHours(1L);
System.out.println("plusHours = " + plusHours);
//輸出: plusHours = 2020-07-06T23:46:49.196
//5、加10分
LocalDateTime plusMinutes = localDateTime.plusMinutes(10L);
System.out.println("plusMinutes = " + plusMinutes);
//輸出: plusMinutes = 2020-07-06T22:56:49.196
//6、加200毫秒
LocalDateTime plusSeconds = localDateTime.plusSeconds(200L);
System.out.println("plusSeconds = " + plusSeconds);
//輸出: plusSeconds = 2020-07-06T22:50:09.196
}
也可以用另外一種方式
LocalDateTime nextMonth = localDateTime.plus(1, ChronoUnit.MONTHS);
LocalDateTime nextYear = localDateTime.plus(1, ChronoUnit.YEARS);
LocalDateTime nextWeek = localDateTime.plus(1, ChronoUnit.WEEKS);
減法操作
public static void main(String[] args) {
//獲取當前時間
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("當前時間 = " + localDateTime);
//輸出: 當前時間 = 2020-07-06T22:53:38.264
//1、減1年
LocalDateTime minusYears = localDateTime.minusYears(1L);
System.out.println("minusYears = " + minusYears);
//輸出: minusYears = 2019-07-06T22:53:38.264
//2、減1個月
LocalDateTime minusMonths = localDateTime.minusMonths(1L);
System.out.println("minusMonths = " + minusMonths);
//輸出: minusMonths = 2020-06-06T22:53:38.264
//3、減一天
LocalDateTime minusDays = localDateTime.minusDays(1L);
System.out.println("minusDays = " + minusDays);
//輸出: minusDays = 2020-07-05T22:53:38.264
//4、減1個小時
LocalDateTime minusHours = localDateTime.minusHours(1L);
System.out.println("minusHours = " + minusHours);
//輸出: minusHours = 2020-07-06T21:53:38.264
//5、減10分
LocalDateTime minusMinutes = localDateTime.minusMinutes(10L);
System.out.println("minusMinutes = " + minusMinutes);
//輸出: minusMinutes = 2020-07-06T22:43:38.264
//6、減200毫秒
LocalDateTime minusSeconds = localDateTime.minusSeconds(200L);
System.out.println("minusSeconds = " + minusSeconds);
//輸出: minusSeconds = 2020-07-06T22:50:18.264
}
也可以用另外一種方式
LocalDateTime lastMonth = localDateTime.minus(1, ChronoUnit.MONTHS);
LocalDateTime lastYear = localDateTime.minus(1, ChronoUnit.YEARS);
LocalDateTime lastWeek = localDateTime.minus(1, ChronoUnit.WEEKS);
注意
從代碼中可以看到,這些 plus() 和 minus() 方法,是不會改變原date和time的實例的,返回的是新的實例。
3、比較日期和時間
當我們想知道給定的時間或日期是在另一個時間/日期之前還是之后,我們就可以用到isBefore()
和isAfter()
方法,如下所示:
public static void main(String[] args) {
public static void main(String[] args) {
LocalDate ld1 = LocalDate.of(2020, 7, 6);
LocalDate ld2 = LocalDate.of(2020, 7, 7);
boolean after = ld1.isAfter(ld2);
System.out.println("ld1是否在ld2之后 = " + after);
//輸出: ld1是否在ld2之后 = false
boolean before = ld1.isBefore(ld2);
System.out.println("ld1是否在ld2之前 = " + before);
//輸出: ld1是否在ld2之前 = true
LocalDateTime ldt1 = LocalDateTime.of(2020, 7, 7, 12, 12);
LocalDateTime ldt2 = LocalDateTime.of(2020, 7, 7, 14, 12);
boolean after1 = ldt1.isAfter(ldt2);
System.out.println("ldt1是否在ldt2之后 = " + after1);
//輸出: ldt1是否在ldt2之后 = false
boolean before1 = ldt1.isBefore(ldt2);
System.out.println("ldt1是否在ldt2之后 = " + before1);
//輸出: ldt1是否在ldt2之后 = true
//時間相減
Duration duration = Duration.between(ldt1, ldt2);
//兩個時間差的天數
long days = duration.toDays();
System.out.println("days = " + days);
//輸出: days = 0
//小時數差
long hours = duration.toHours();
System.out.println("hours = " + hours);
//輸出: hours = 2
//分鍾數差
long minutes = duration.toMinutes();
System.out.println("minutes = " + minutes);
//輸出: minutes = 120
//毫秒數差
long millis = duration.toMillis();
System.out.println("millis = " + millis);
//輸出: millis = 7200000
//納秒數差
long nanos = duration.toNanos();
System.out.println("nanos = " + nanos);
//輸出: nanos = 7200000000000
}
4、在String和日期之間轉換
在以前使用java.util.Date的時候,我們一般使用 SimpleDateFormat 去完成日期/時間和字符串的轉換,在新的日期時間API中,我們使用全新的 DateTimeFormatter。
如果你遵循ISO標准在日期/時間和字符串之間進行轉換,那么這個事情會變得很容易,因為在 DateTimeFormatter 中,已經內置了ISO標准的格式。我們來看看代碼
日期轉時間
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
System.out.println("ldt = " + ldt);
//輸出: ldt = 2020-07-07T18:32:34.757
String format1 = ldt.format(DateTimeFormatter.ISO_DATE);
System.out.println("format1 = " + format1);
//輸出: format1 = 2020-07-07
String format2 = ldt.format(DateTimeFormatter.BASIC_ISO_DATE);
System.out.println("format2 = " + format2);
//輸出: format2 = 20200707
String format3 = ldt.format(DateTimeFormatter.ISO_DATE_TIME);
System.out.println("format3 = " + format3);
//輸出: format3 = 2020-07-07T18:32:34.757
String format4 = ldt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
System.out.println("format4 = " + format4);
//輸出: format4 = 2020-07-07T18:32:34.757
String format = ldt.format(DateTimeFormatter.ofPattern("d-M-y"));
System.out.println("format = " + format);
//輸出: format = 7-7-2020
String format5 = ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("format5 = " + format5);
//輸出: format5 = 2020-07-07 18:32:34
String format6 = ldt.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH時mm分ss秒"));
System.out.println("format6 = " + format6);
//輸出: format6 = 2020年07月07日18時32分34秒
}
String轉日期
public static void main(String[] args) {
LocalDate ld = LocalDate.parse("2020-07-07");
System.out.println("ld = " + ld);
//輸出: ld = 2020-07-07
String str = "2020-07-07 22:24:33";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime ldt = LocalDateTime.parse(str,dateTimeFormatter);
System.out.println("ldt = " + ldt);
//輸出: ldt = 2020-07-07T22:24:33
}
5、其它
有的時候,你需要進行一些更加復雜的操作,比如,將日期調整到下個周日、下個工作日,或者是本月的最后一天。這時,你可以使用重載版本的with方法,向其傳遞一個提供了更多定制化選擇的TemporalAdjuster對象,更 加 靈 活 地 處 理 日 期。
日期處理
public static void main(String[] args) {
LocalDate date = LocalDate.parse("2020-07-07");
//獲取這個月的第一個周末的時間
System.out.println(date.with(TemporalAdjusters.dayOfWeekInMonth(1, DayOfWeek.SUNDAY)));
//輸出: 2020-07-05
//獲取上個月的最后一周末的時間
System.out.println(date.with(TemporalAdjusters.dayOfWeekInMonth(0, DayOfWeek.SUNDAY)));
//輸出: 2020-06-28
//獲取這個月的倒數第一個周末的時間
System.out.println(date.with(TemporalAdjusters.dayOfWeekInMonth(-1, DayOfWeek.SUNDAY)));
//輸出: 2020-07-26
//獲取這個月的第一個周末的時間,上面的dayOfWeekInMonth更靈活,可以定義第幾周
System.out.println(date.with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY)));
//輸出: 2020-07-05
//明年的第一天
System.out.println(date.with(TemporalAdjusters.firstDayOfNextYear()));
//輸出: 2021-01-01
//獲取下個周5的時間
System.out.println(date.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)));
//輸出: 2020-07-10
//獲取本月最后一天
System.out.println(date.with(TemporalAdjusters.lastDayOfMonth()));
//輸出: 2020-07-31
//獲取本月第一天
System.out.println(date.with(TemporalAdjusters.firstDayOfMonth()));
//輸出: 2020-07-01
}
其它還有許多,具體查看api
時間處理
public static void main(String[] args) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//一天開始時間
LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
String format = todayStart.format(dateTimeFormatter);
System.out.println("format = " + format);
//輸出: format = 2020-07-07 00:00:00
//一天結束時間
LocalDateTime todayEnd = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
String format1 = todayEnd.format(dateTimeFormatter);
System.out.println("format1 = " + format1);
//輸出: format1 = 2020-07-07 23:59:59
//一天中午時間
LocalDateTime todayMid = LocalDateTime.of(LocalDate.now(), LocalTime.NOON);
String format2 = todayMid.format(dateTimeFormatter);
System.out.println("format2 = " + format2);
//輸出: format2 = 2020-07-07 12:00:00
}
舉了這么多例子,在實際開發中應該足夠用了。
二、完整示例
這里整理一個完整的時間工具類,可以在實際工作中進行運用它
public class DateTimeUtils {
public static final String DATETIME_FORMATTER = "yyyy-MM-dd HH:mm:ss";
public static final String DATE_FORMATTER = "yyyy-MM-dd";
public static final String DATE_FORM = "yyyy-MM";
//1、 ==================1、獲取當天,當月最早時間和最晚時間 ========================
/**
* 獲取當天的開始時間
* 示例:2020-08-21T00:00
*/
public static LocalDateTime getDayStart(LocalDateTime time) {
return time.withHour(0).withMinute(0).withSecond(0).withNano(0);
}
/**
* 獲取當天的結束時間
* 示例:2020-08-21T23:59:59.999999999
*/
public static LocalDateTime getDayEnd(LocalDateTime time) {
return time.withHour(23).withMinute(59).withSecond(59).withNano(999999999);
}
/**
* 獲取一個月的開始時間
* 示例: 2020-08-01T00:00
*/
public static LocalDateTime getMonthStart(LocalDateTime time) {
return time.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
}
/**
* 獲取一個月的結束時間
* 示例: 2020-08-31T23:59:59.999999999
*/
public static LocalDateTime getMonthDayEnd(LocalDateTime time) {
return time.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
}
/**
* 獲取當天的開始時間
* 示例:2020-08-21T00:00
*/
public static LocalDateTime getDayStart(LocalDate time) {
return LocalDateTime.of(time, LocalTime.MIN);
}
/**
* 獲取一天的結束時間
* 示例:2020-08-21T23:59:59.999999999
*/
public static LocalDateTime getDayEnd(LocalDate time) {
return LocalDateTime.of(time, LocalTime.MAX);
}
/**
* 獲取當月的開始時間
* 示例: 2020-08-01T00:00
*/
public static LocalDateTime getMonthStart(LocalDate time) {
return LocalDateTime.of(time.with(TemporalAdjusters.firstDayOfMonth()), LocalTime.MIN);
}
/**
* 獲取當月的結束時間
* 示例: 2020-08-31T23:59:59.999999999
*/
public static LocalDateTime getMonthDayEnd(LocalDate time) {
return LocalDateTime.of(time.with(TemporalAdjusters.firstDayOfMonth()), LocalTime.MAX);
}
// =============================== 2、時間轉字符串 =====================================
/**
* 獲取 當前 日期時間字符串(yyyy-MM-dd HH:mm:ss)
*
* @return
*/
public static String getCurrentDateTimeStr() {
return DateTimeFormatter.ofPattern(DATETIME_FORMATTER).format(LocalDateTime.now());
}
/**
* 獲取 當前 日期字符串(yyyy-MM-dd)
*
* @return
*/
public static String getCurrentDateStr() {
return DateTimeFormatter.ofPattern(DATE_FORMATTER).format(LocalDateTime.now());
}
/**
* 獲取 當前 時間字符串(yyyy-MM)
*
* @return
*/
public static String getCurrentTimeStr() {
return DateTimeFormatter.ofPattern(DATE_FORM).format(LocalDateTime.now());
}
/**
* 獲取 指定 日期時間字符串(yyyy-MM-dd HH:mm:ss)
*
* @return
*/
public static String getCurrentDateTimeStr(LocalDateTime localDateTime) {
if (localDateTime == null) {
return StringUtils.EMPTY;
}
return DateTimeFormatter.ofPattern(DATETIME_FORMATTER).format(localDateTime);
}
/**
* 獲取 指定 日期字符串(yyyy-MM-dd)
*
* @return
*/
public static String getCurrentDateStr(LocalDateTime localDateTime) {
if (localDateTime == null) {
return StringUtils.EMPTY;
}
return DateTimeFormatter.ofPattern(DATE_FORMATTER).format(localDateTime);
}
/**
* 獲取 指定 時間字符串(yyyy-MM)
*
* @return
*/
public static String getCurrentTimeStr(LocalDateTime localDateTime) {
if (localDateTime == null) {
return StringUtils.EMPTY;
}
return DateTimeFormatter.ofPattern(DATE_FORM).format(localDateTime);
}
/**
* 獲取 指定 日期字符串(yyyy-MM-dd)
*
* @return
*/
public static String getCurrentDateStr(LocalDate localDate) {
if (localDate == null) {
return StringUtils.EMPTY;
}
return DateTimeFormatter.ofPattern(DATE_FORMATTER).format(localDate);
}
// =============================== 3、字符串轉時間 =====================================
/**
* 將時間字符串轉為自定義時間格式的LocalDateTime
* 字符串格式: yyyy-MM-dd HH:mm:ss
*/
public static LocalDateTime convertStringToLocalDateTime(String time) {
return LocalDateTime.parse(time, DateTimeFormatter.ofPattern(DATETIME_FORMATTER));
}
/**
* 字符串格式: yyyy-MM-dd
*/
public static LocalDate convertStringToLocalDate(String time) {
return LocalDate.parse(time, DateTimeFormatter.ofPattern(DATE_FORMATTER));
}
/**
* 將時間字符串轉為自定義時間格式的LocalDateTime
*
* @param time 需要轉化的時間字符串
* @param format 自定義的時間格式
* @return
*/
public static LocalDateTime convertStringToLocalDateTime(String time, String format) {
return LocalDateTime.parse(time, DateTimeFormatter.ofPattern(format));
}
// ============================== 4、求兩個時間的時間差 ==============================
/**
* 獲取兩個日期的 天數 差
*/
public static long betweenLessDay(LocalDateTime startTime, LocalDateTime endTime) {
//時間相減
Duration duration = Duration.between(startTime, endTime);
//兩個時間差的天數
return duration.toDays();
}
/**
* 獲取兩個日期的 小時 差
*/
public static long betweenLessHour(LocalDateTime startTime, LocalDateTime endTime) {
Duration duration = Duration.between(startTime, endTime);
return duration.toHours();
}
/**
* 獲取兩個日期的 分鍾 差
*/
public static long betweenLessMinutes(LocalDateTime startTime, LocalDateTime endTime) {
Duration duration = Duration.between(startTime, endTime);
return duration.toMinutes();
}
/**
* 獲取兩個日期的 秒 差
*/
public static long betweenLessMillis(LocalDateTime startTime, LocalDateTime endTime) {
Duration duration = Duration.between(startTime, endTime);
return duration.toMillis();
}
// ================================ 5. long和LocalDateTime互轉 ============================
/**
* 將long類型的timestamp轉為LocalDateTime
*
* @param timestamp
* @return
*/
public static LocalDateTime convertTimestampToLocalDateTime(long timestamp) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
}
/**
* 將LocalDateTime轉為long類型的timestamp
*
* @param localDateTime
* @return
*/
public static long convertLocalDateTimeToTimestamp(LocalDateTime localDateTime) {
return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
}
參考
別人罵我胖,我會生氣,因為我心里承認了我胖。別人說我矮,我就會覺得好笑,因為我心里知道我不可能矮。這就是我們為什么會對別人的攻擊生氣。
攻我盾者,乃我內心之矛(23)