Java好用的時(shí)間類(lèi),別在用Date了
前言
假設(shè)你想獲取當(dāng)前時(shí)間,那么你肯定看過(guò)這樣的代碼
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());
}
復(fù)制代碼獲取年份,獲取月份,獲取..日期?
運(yùn)行一下
121
9
27
復(fù)制代碼怎么回事?獲取年份,日期怎么都不對(duì),點(diǎn)開(kāi)源碼發(fā)現(xiàn)
/**
* 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 Date 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 Calendar.get(Calendar.YEAR) - 1900.
*/
@Deprecated
public int getYear() {
return normalize().getYear() - 1900;
}
復(fù)制代碼原來(lái)是某個(gè)對(duì)象值 減去了 1900,注釋也表示,返回值減去了1900,難道我們每次獲取年份需要在 加上1900?注釋也說(shuō)明了讓我們 用Calendar.get()替換,并且該方法已經(jīng)被廢棄了。點(diǎn)開(kāi)getMonth()也是一樣,返回了一個(gè)0到11的值。getDate()獲取日期?不應(yīng)該是getDay()嗎?老外的day都是sunday、monday,getDate()才是獲取日期。再注意到這些api都是在1.1的時(shí)候被廢棄了,私以為是為了消除getYear減去1900等這些歧義。收~
Calendar 日歷類(lèi)
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);
}
復(fù)制代碼打印(運(yùn)行時(shí)間2021年10月27日 星期三 晴)
2021年9月
27日
300日
4日
4
復(fù)制代碼問(wèn):月份怎么是上個(gè)月的?
答:是為了計(jì)算方便,月是0到11之間的值。
問(wèn):計(jì)算方便?
答:比如月份從1月開(kāi)始,增加一個(gè)月,12月+1=13,沒(méi)有13月。假設(shè)取余,(12+1)%12=1 正好為1月,那11月增加一個(gè)月,(11+1)%12=0,這就有問(wèn)題了。所以為了計(jì)算方便1月,返回了0值。date.getMonth()也是一個(gè)道理。問(wèn):那下面的DAY_OF_XXX 又是什么意思?
答:猜!根據(jù)結(jié)果猜。
Calendar.DAY_OF_MONTH ?在這個(gè)月 的這一天
Calendar.DAY_OF_YEAR 在這一年 的這一天
Calendar.DAY_OF_WEEK 在這一周 的這一天
Calendar.DAY_OF_WEEK_IN_MONTH ?在這一個(gè)月 ?這一天在 第幾周
到這里 Calendar.DAY_OF_WEEK 為什么是 4 ,你肯定也猜到了
Calendar.HOUR
Calendar.HOUR_OF_DAY
Calendar.SECOND
...其他的 你肯定也會(huì)用了
LocalDate 本地日期類(lèi)
LocalDate localDate = LocalDate.now();
System.out.println("當(dāng)前日期:"+localDate.getYear()+" 年 "+localDate.getMonthValue()+" 月 "+localDate.getDayOfMonth()+"日" );
//結(jié)果
當(dāng)前日期:2021 年 10 月 27日
復(fù)制代碼也可以通過(guò) LocalDate.of(年,月,日)去構(gòu)造
LocalDate pluslocalDate = localDate.plusDays(1);//增加一天
LocalDate pluslocalDate = localDate.plusYears(1);//增加一年
復(fù)制代碼其他api
LocalDate.isBefore(LocalDate);
LocalDate.isAfter();
LocalDate.isEqual();
復(fù)制代碼也就是對(duì)兩個(gè)日期的判斷,是在前、在后、或者相等。
LocalTime 本地時(shí)間類(lèi)
LocalTime localTime = LocalTime.now();
System.out.println("當(dāng)前時(shí)間:"+localTime.getHour()+"h "+localTime.getSecond()+"m "+localTime.getMinute()+"s" );
復(fù)制代碼LocalDate和LocalTime 都有類(lèi)似作用的api
LocalDate.plusDays(1) ?增加一天
LocalTime.plusHours(1) 增加一小時(shí) 等等~
其他api
LocalTime.isBefore(LocalTime);
LocalTime.isAfter();
復(fù)制代碼對(duì)兩個(gè)時(shí)間的判斷??隙ㄅ龅竭^(guò)一個(gè)需求,今天離活動(dòng)開(kāi)始時(shí)間還剩多少天。
LocalDateTime 本地日期時(shí)間類(lèi)
public final class LocalDateTime ...{
private final LocalDate date;
private final LocalTime time;
}
復(fù)制代碼LocalDateTime = LocalDate + LocalTime ?懂的都懂
Instant 類(lèi)
Instant 是瞬間,某一時(shí)刻的意思
Instant.ofEpochMilli(System.currentTimeMillis())
Instant.now()
復(fù)制代碼通過(guò)Instant可以創(chuàng)建一個(gè) “瞬間” 對(duì)象,ofEpochMilli()可以接受某一個(gè)“瞬間”,比如當(dāng)前時(shí)間,或者是過(guò)去、將來(lái)的一個(gè)時(shí)間。
比如,通過(guò)一個(gè)“瞬間”創(chuàng)建一個(gè)LocalDateTime對(duì)象
LocalDateTime now = LocalDateTime.ofInstant(
Instant.ofEpochMilli(System.currentTimeMillis()),ZoneId.systemDefault());
System.out.println("當(dāng)前日期:"+now.getYear()+" 年 "+now.getMonthValue()+" 月 "+now.getDayOfMonth()+"日" );
復(fù)制代碼Period 類(lèi)
Period 是 時(shí)期,一段時(shí)間 的意思
Period有個(gè)between方法專(zhuān)門(mén)比較兩個(gè) 日期 的
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("目標(biāo)日期距離今天的時(shí)間差:"+p.getYears()+" 年 "+p.getMonths()+" 個(gè)月 "+p.getDays()+" 天" );
//目標(biāo)日期距離今天的時(shí)間差:1 年 1 個(gè)月 1 天
復(fù)制代碼看一眼源碼
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);
}
復(fù)制代碼他只接受兩個(gè)LocalDate對(duì)象,對(duì)時(shí)間的計(jì)算,算好之后返回Period對(duì)象
Duration 類(lèi)
Duration 是 期間 持續(xù)時(shí)間 的意思 上代碼
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("開(kāi)始時(shí)間到結(jié)束時(shí)間,持續(xù)了"+duration.toDays()+"天");
System.out.println("開(kāi)始時(shí)間到結(jié)束時(shí)間,持續(xù)了"+duration.toHours()+"小時(shí)");
System.out.println("開(kāi)始時(shí)間到結(jié)束時(shí)間,持續(xù)了"+duration.toMillis()/1000+"秒");
復(fù)制代碼可以看到between也接受兩個(gè)參數(shù),LocalDateTime對(duì)象,源碼是對(duì)兩個(gè)時(shí)間的計(jì)算,并返回對(duì)象。
對(duì)象轉(zhuǎn)換
再貼點(diǎn)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對(duì)象.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
//LocalDateTime -> String
DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime對(duì)象.format(dateTimeFormatter1)
復(fù)制代碼對(duì)象轉(zhuǎn)換幾乎都涵蓋了,里面有個(gè)時(shí)區(qū)對(duì)象,這個(gè)一般用默認(rèn)時(shí)區(qū)。
總結(jié)
用LocalDate、LocalTime、LocalDateTime代替了Date類(lèi)。Date管日期,Time管時(shí)間
LocalDateTime = LocalDate + LocalTime
Period 只能用LocalDate
Duration 持續(xù)時(shí)間,所以L(fǎng)ocalDate、LocalTime、LocalDateTime 都能處理
至于Calendar 日歷類(lèi),這里面的api,都是針對(duì)日歷的,比如這個(gè)月的第一天是星期幾。
總體來(lái)說(shuō),都是api的使用,非常清晰,廢棄date.getMonth()等,使用localDate.getMonthValue()來(lái)獲取幾月,更易理解,更易貼合使用。代碼都貼在了github上了
作者:回眸婉約
鏈接:https://juejin.cn/post/7024389549652443172
來(lái)源:稀土掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
