前言
假設你想獲取當前時間,那么你肯定看過這樣的代碼
public static void main(String[] args) {
Date date = new Date(System.currentTimeMillis());
System.out.println(date.getYear());
System.out.println(date.getMonth());
System.out.println(date.getDate());
}
獲取年份,獲取月份,獲取..日期?
運行一下
121
9
27
怎么回事?獲取年份,日期怎么都不對,點開源碼發現
/**
* Returns a value that is the result of subtracting 1900 from the
* year that contains or begins with the instant in time represented
* by this <code>Date</code> object, as interpreted in the local
* time zone.
*
* @return the year represented by this date, minus 1900.
* @see JAVA.util.Calendar
* @deprecated As of JDK version 1.1,
* replaced by <code>Calendar.get(Calendar.YEAR) - 1900</code>.
*/
@Deprecated
public int getYear() {
return normalize().getYear() - 1900;
}
原來是某個對象值 減去了 1900,注釋也表示,返回值減去了1900,難道我們每次獲取年份需要在 加上1900?注釋也說明了讓我們 用Calendar.get()替換,并且該方法已經被廢棄了。點開getMonth()也是一樣,返回了一個0到11的值。getDate()獲取日期?不應該是getDay()嗎?老外的day都是sunday、monday,getDate()才是獲取日期。再注意到這些api都是在1.1的時候被廢棄了,私以為是為了消除getYear減去1900等這些歧義。收~
Calendar 日歷類
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int dom = calendar.get(Calendar.DAY_OF_MONTH);
int doy = calendar.get(Calendar.DAY_OF_YEAR);
int dow = calendar.get(Calendar.DAY_OF_WEEK);
int dowim = calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH);
System.out.println(year+"年"+ month+"月");
System.out.println(dom+"日");
System.out.println(doy+"日");
System.out.println(dow+"日");
System.out.println(dowim);
}
打印(運行時間2021年10月27日 星期三 晴)
2021年9月
27日
300日
4日
4
問:月份怎么是上個月的?
答:是為了計算方便,約是0到11之間的值。
問:計算方便?
答:比如月份從1月開始,增加一個月,12月+1=13,沒有13月。假設區域,(12+1)%12=1 正好為1月,那11月增加一個月,(11+1)%12=0,這就有問題了。所以為了計算方便1月,返回了0值。date.getMonth()也是一個道理。 問:那下面的DAY_OF_XXX 又是什么意思?
答:猜!根據結果猜。
Calendar.DAY_OF_MONTH 在這個月 的這一天
Calendar.DAY_OF_YEAR 在這一年 的這一天
Calendar.DAY_OF_WEEK 在這一周 的這一天
Calendar.DAY_OF_WEEK_IN_MONTH 在這一個月 這一天在 第九周
到這里 Calendar.DAY_OF_WEEK 為什么是 4 ,你肯定也猜到了
Calendar.HOUR
Calendar.HOUR_OF_DAY
Calendar.SECOND
...其他的 你肯定也會用了
LocalDate 本地日期類
LocalDate localDate = LocalDate.now();
System.out.println("當前日期:"+localDate.getYear()+" 年 "+localDate.getMonthValue()+" 月 "+localDate.getDayOfMonth()+"日" );
//結果
當前日期:2021 年 10 月 27日
也可以通過 LocalDate.of(年,月,日)去構造
LocalDate pluslocalDate = localDate.plusDays(1);//增加一天
LocalDate pluslocalDate = localDate.plusYears(1);//增加一年
其他api
LocalDate.isBefore(LocalDate);
LocalDate.isAfter();
LocalDate.isEqual();
也就是對兩個日期的判斷,是在前、在后、或者相等。
LocalTime 本地時間類
LocalTime localTime = LocalTime.now();
System.out.println("當前時間:"+localTime.getHour()+"h "+localTime.getSecond()+"m "+localTime.getMinute()+"s" );
LocalDate和LocalTime 都有類似作用的api
LocalDate.plusDays(1) 增加一天
LocalTime.plusHours(1) 增加一小時 等等~
其他api
LocalTime.isBefore(LocalTime);
LocalTime.isAfter();
對兩個時間的判斷。肯定碰到過一個需求,今天離活動開始時間還剩多少天。
LocalDateTime 本地日期時間類
public final class LocalDateTime ...{
private final LocalDate date;
private final LocalTime time;
}
LocalDateTime = LocalDate + LocalTime 懂得都懂
Instant 類
Instant 是瞬間,某一時刻的意思
Instant.ofEpochMilli(System.currentTimeMillis())
Instant.now()
通過Instant可以創建一個 “瞬間” 對象,ofEpochMilli()可以接受某一個“瞬間”,比如當前時間,或者是過去、將來的一個時間。
比如,通過一個“瞬間”創建一個LocalDateTime對象
LocalDateTime now = LocalDateTime.ofInstant(
Instant.ofEpochMilli(System.currentTimeMillis()),ZoneId.systemDefault());
System.out.println("當前日期:"+now.getYear()+" 年 "+now.getMonthValue()+" 月 "+now.getDayOfMonth()+"日" );
Period 類
Period 是 時期,一段時間 的意思
Period有個between方法專門比較兩個 日期 的
LocalDate startDate = LocalDateTime.ofInstant(
Instant.ofEpochMilli(1601175465000L), ZoneId.systemDefault()).toLocalDate();//1601175465000是2020-9-27 10:57:45
Period p = Period.between(startDate, LocalDate.now());
System.out.println("目標日期距離今天的時間差:"+p.getYears()+" 年 "+p.getMonths()+" 個月 "+p.getDays()+" 天" );
//目標日期距離今天的時間差:1 年 1 個月 1 天
看一眼源碼
public static Period between(LocalDate startDateInclusive, LocalDate endDateExclusive) {
return startDateInclusive.until(endDateExclusive);
}
public Period until(ChronoLocalDate endDateExclusive) {
LocalDate end = LocalDate.from(endDateExclusive);
long totalMonths = end.getProlepticMonth() - this.getProlepticMonth(); // safe
int days = end.day - this.day;
if (totalMonths > 0 && days < 0) {
totalMonths--;
LocalDate calcDate = this.plusMonths(totalMonths);
days = (int) (end.toEpochDay() - calcDate.toEpochDay()); // safe
} else if (totalMonths < 0 && days > 0) {
totalMonths++;
days -= end.lengthOfMonth();
}
long years = totalMonths / 12; // safe
int months = (int) (totalMonths % 12); // safe
return Period.of(Math.toIntExact(years), months, days);
}
他只接受兩個LocalDate對象,對時間的計算,算好之后返回Period對象
Duration 類
Duration 是 期間 持續時間 的意思 上代碼
LocalDateTime end = LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.systemDefault());
LocalDateTime start = LocalDateTime.ofInstant(Instant.ofEpochMilli(1601175465000L), ZoneId.systemDefault());
Duration duration = Duration.between(start, end);
System.out.println("開始時間到結束時間,持續了"+duration.toDays()+"天");
System.out.println("開始時間到結束時間,持續了"+duration.toHours()+"小時");
System.out.println("開始時間到結束時間,持續了"+duration.toMillis()/1000+"秒");
可以看到between也接受兩個參數,LocalDateTime對象,源碼是對兩個時間的計算,并返回對象。
對象轉換
再貼點api
//long -> LocalDateTime
LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault())
//String -> LocalDateTime
DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime.parse("2021-10-28 00:00:00", dateTimeFormatter1);
//LocalDateTime -> long
LocalDateTime對象.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
//LocalDateTime -> String
DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime對象.format(dateTimeFormatter1)
對象轉換幾乎都涵蓋了,里面有個時區對象,這個一般用默認時區。
總結
用LocalDate、LocalTime、LocalDateTime代替了Date類。Date管日期,Time管時間
LocalDateTime = LocalDate + LocalTime
Period 只能用LocalDate
Duration 持續時間,所以LocalDate、LocalTime、LocalDateTime 都能處理
至于Calendar 日歷類,這里面的api,都是針對日歷的,比如這個月的第一天是星期幾。
總體來說,都是api的使用,非常清晰,廢棄date.getMonth()等,使用localDate.getMonthValue()來獲取幾月,更易理解,更易貼合使用。代碼都貼在了github上了