Android第三方庫源碼解析:java
發現不少開發人員作在時間相關的問題的時候,各有各的方法,而後對時間相關的處理,各類Java自帶的時間相關類的知識面都不是很清楚,有時候看見他們在開發時候,都是一邊使用到了,而後臨時百度去處理時間相關的問題。bash
說個簡單的,好比如今要問一首歌的時長,後臺返回給你00:03:06
,而後你代碼中要用到總秒數時長,這時候問你怎麼把這個變成具體的秒數。在現有的項目中,我看這個的處理代碼是這樣的:函數
if (min.contains(":")) {
String[] items = min.split(":");
duration += (Integer.valueOf(items[0]) * 60 * 60 * 1000 + Integer.valueOf(items[1]) * 60 * 1000 + Integer.valueOf(items[2]) * 1000);
}
複製代碼
上面代碼固然沒有任何問題,可是咱們其實能夠用時間相關類來處理。工具
既然說到了時間相關知識,最主要的確定先要獲取到時間。ui
其實看腦圖,就已經很詳細了,並且Date你們應該熟悉的不要太熟悉了,因此不會超級詳細說明,咱們只挑幾個點說一下:spa
構造函數:線程
Date date = new Date();
// 使用 toString() 函數顯示當前日期時間
date.toString(); //Sat Aug 31 15:20:08 CST 2019
Date date1 = new Date(1000);
//1970.01.01 00:00:00開始加上你填入的數值後的時間點
date1.toString(); //Thu Jan 01 08:00:01 CST 1970
複製代碼
get/set函數:3d
Date date = new Date();
//獲取當前Date表明的時間距離1970.01.01 08:00:00的差值
//'實際的Date表明的是1970.01.01 00:00:00的時間差,由於當前是東八區,因此獲取到的是08:00:00'
date.getTime(); //1567576587763
Date date1 = new Date(1000);
date1.getTime(); //1000
Date date2 = new Date();
date2.setTime(1000);
date2.getTime(); //1000
複製代碼
二個Date比較函數:code
Date aaaaa = new Date(1000);
Date bbbbb = new Date(2000);
aaaaa.after(bbbbb);//false
aaaaa.before(bbbbb);//true
aaaaa.equals(bbbbb);//false
aaaaa.compareTo(bbbbb);//-1(a<b返回-1,a==b返回0,a>b返回1)
複製代碼
咱們知道了Date
能夠表明時間值(由於有了Date
就能夠獲取距離1970-01-01 08:00:00 的差值,也就知道了當前Date
表明的時間)orm
因此Calendar
在獲取時間的方法上,不只提供了獲取時間返回long
類型的方法,還提供了返回Date
對象的方法
獲取時間:
Calendar cl = Calendar.getInstance();
Date date = cl.getTime();//獲取Date對象
cl.getTimeInMillis();//直接獲取long值
date.getTime() 與 cl.getTimeInMillis()的結果是同樣的
複製代碼
固然Calendar
也能夠具體的拿年月日時分秒等具體某個想要的值:
好比獲取當前時間的小時:
Calendar cl = Calendar.getInstance();
//好比如今是下午四點,獲取到的就
cl.get(Calendar.HOUR_OF_DAY));
是16
//'注意一點,拿到的Mouth是從0開始的,好比如今是9月,你獲取的是8'
cl.get(Calendar.MONTH); //8
複製代碼
具體的參數有不少,能夠本身去選:
設置時間:
上面說了獲取時間,設置時間也是同樣的,能夠直接設置long類型,也能夠設置Date類型,也能夠直接設置具體的年月日字段值。
public final void setTime(Date date)
public void setTimeInMillis(long millis)
public void set(int field, int value)
public final void set(int year, int month, int date)
public final void set(int year, int month, int date, int hourOfDay, int minute)
public final void set(int year, int month, int date, int hourOfDay, int minute,int second)
複製代碼
二個Calendar對象比較: 徹底能夠參考前面的二個Date對象進行比較,這裏也不細說了:
其實咱們前面說的
Date
和Calendar
都是你們很熟悉的類,用的也是最多的,可是由於使用方式不友好,因此後面java8以後,都是使用新的·Instant
和Localxxxx
系列用來替換Date
和Calendar
的類了。
不少人說,Date
不是挺好用的,感受夠用了。假如我如今須要你獲取當前時間,而後在該基礎上加上6小時,再求時間,你就會發現有點不方便了。
Date dd1 = new Date();
dd1.setTime(dd1.getTime()+6*60*60*1000);
//'當前有些人會說Date不是有個setHours()方法嗎?但實際已經標記拋棄了'
複製代碼
咱們看下Instant
的用法:
Instant i = Instant.now();
i.toString(); //2019-09-04T09:44:07.169Z
Instant i2 = i.plus(6,ChronoUnit.HOURS);//加了6個小時
i2.toString(); //2019-09-04T15:44:07.169Z
//也能夠經過Duration類輔助 ('Duration類後面會講到')
Instant i3 = i.plus(Duration.ofHours(6));
i3.toString(); //2019-09-04T15:44:07.169Z
//也能夠經過TimeUnit輔助類('TimeUnit類後面會講到')
Instant i4 = i.plusMillis(TimeUnit.HOURS.toMillis(6));
i4.toString(); ////2019-09-04T15:44:07.169Z
//'減小則使用minus方法,使用方式同plus'
複製代碼
二個Instant對象的相關比較方法,與Date同樣:
這裏主要講一個until
方法:
Instant i = Instant.now();
Instant i2 = i.plus(6,ChronoUnit.HOURS);
i2.until(i,ChronoUnit.HOURS); //-6
i.until(i2,ChronoUnit.HOURS); //6
'(i2.until(i,ChronoUnit.HOURS); i2到i1,說明要回到之前,固然是要減小6個小時,反之亦然)'
複製代碼
PS: Instant.now(); 拿到的時間是比咱們當前中國時區慢8小時,你們要注意下
Local系列主要有: LocalTime
, LocalDate
,LocalDateTime
從單純的字面意思就能夠看出來:LocalTime
是指時間(時分秒),LocalDate
是指日期(年月日),LocalDateTime
是整個完整日期(年-月-日-時-分-秒)
1.4.1 LocalDate :
基本的方法就如上面腦圖,經常使用的方法也都有了。
這裏提個點:
Calendar
獲取的月份是從0
開始的,好比如今是9月份
,你獲取到的數字是8
。可是localDate.getMonthValue()
獲取到的是9
。更貼合實際。
1.4.2 LocalTime :
LocalTime
的方法也入上面腦圖,經常使用的方法也都有了。
1.4.3 LocalDateTime :
LocalDateTime = LocalDate + LocalTime
LocalDate.atTime()方法添加時間
返回的結果對象同時變爲LocalDateTime對象
LocalTime.atDate()方法添加日期
返回的結果對象同時變爲LocalDateTime對象
複製代碼
而LocalDateTime
的使用和LocalTime
和LocalDate
的使用方法基本的同樣。
1.4.4 ZoneDateTime :
和LocalDateTime也基本相同,從字面意思看咱們也知道是帶有時區相關的:
LocalDateTime.now();
//2019-09-05T22:49:06.369
ZoneDateTime.now();
//2019-09-05T22:49:06.371+08:00[Asia/Shanghai]
複製代碼
咱們能夠看到當前的時區,其餘方法使用方式也基本都如出一轍。
前面咱們已經說了怎麼獲取到時間。接下去咱們講時間和各類格式的字符串等各類相互轉換。
但咱們知道界面上咱們想要顯示的文字不一樣: 2018-08-07 09:12:12
,2018#08#07#09#12#12
各類方式,這個是時間轉成字符串顯示。
而後假如別人傳給你2018-08-07 09:12:12
,2018#08#07#09#12#12
,想要把字符串轉換成時間對象。
DateFormat
是日期/時間格式化子類的抽象類,它以與語言無關的方式格式化並解析日期或時間。日期/時間格式化子類(如SimpleDateFormat
)容許進行格式化(也就是日期 -> 文本)、解析(文本-> 日期)和標準化。將日期表示爲 Date 對象,或者表示爲從 GMT(格林尼治標準時間)1970 年 1 月 1 日 00:00:00這一刻開始的毫秒數。
2.1.1時間和字符串的互轉:
DateFormat
可幫助進行格式化並解析任何語言環境的日期。對於月、星期,甚至日曆格式(陰曆和陽曆),其代碼可徹底與語言環境的約定無關。
要格式化一個當前語言環境下的日期,可以使用某個靜態工廠方法:
myString = DateFormat.getDateInstance().format(myDate);
複製代碼
若是格式化多個日期,那麼獲取該格式並屢次使用它是更爲高效的作法,這樣系統就沒必要屢次獲取有關環境語言和國家/地區約定的信息了。
DateFormat df = DateFormat.getDateInstance();
for (int i = 0; i < myDate.length; ++i) {
output.println(df.format(myDate[i]) + "; ");
}
複製代碼
要格式化不一樣語言環境的日期,可在 getDateInstance() 的調用中指定它。
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
複製代碼
還可以使用 DateFormat
進行解析。
myDate = df.parse(myString);
複製代碼
2.1.2獲取DateFormat對象:
使用getDateInstance
來獲取該國家/地區的標準日期格式。另外還提供了一些其餘靜態工廠方法。使用 getTimeInstance
可獲取該國家/地區的時間格式。使用 getDateTimeInstance
可獲取日期和時間格式。能夠將不一樣選項傳入這些工廠方法,以控制結果的長度(從 SHORT
到 MEDIUM
到 LONG
再到 FULL
)。確切的結果取決於語言環境,可是一般:
SHORT 徹底爲數字,如 12.13.52 或 3:30pm
MEDIUM 較長,如 Jan 12, 1952
LONG 更長,如 January 12, 1952 或 3:30:32pm
FULL 是徹底指定,如 Tuesday、April 十二、1952 AD 或 3:30:42pm PST。
複製代碼
若是願意,還能夠在格式上設置時區。若是想對格式化或解析施加更多的控制(或者給予用戶更多的控制),能夠嘗試將從工廠方法所獲取的 DateFormat 強制轉換爲 SimpleDateFormat。這適用於大多數國家/地區;只是要記住將其放入一個 try 代碼塊中,以防遇到特殊的格式。還可使用藉助 ParsePosition 和 FieldPosition 的解析和格式化方法形式來逐步地解析字符串的各部分。 對齊任意特定的字段,或者找出字符串在屏幕上的選擇位置。 同步日期格式不是同步的。建議爲每一個線程建立獨立的格式實例。若是多個線程同時訪問一個格式,則它必須保持外部同步。
SimpleDateFormat
是DateFormat
的子類,因此前面的DateFormat
的基本的知識介紹基本都是如出一轍的。這裏就不說明了。
這個類估計你們百分之99.9999都使用,而且知道怎麼使用了。
下面這段代碼,基本是使用率最高的:
Date date = new Date();
String strDateFormat = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
//時間轉換爲字符串
sdf.format(date); //2019-09-06 21:13:23
String str = "2019-09-06 21:13:23";
//字符串轉換爲時間
Date date = sdf.parse(str);
複製代碼
主要的不熟悉的反而不是方法的使用,而是格式的定義總是記不清楚:
字母 日期或時間元素 表示 示例
G Era 標誌符 Text AD
y 年 Year 1996; 96
M 年中的月份 Month July; Jul; 07
w 年中的週數 Number 27
W 月份中的週數 Number 2
D 年中的天數 Number 189
d 月份中的天數 Number 10
F 月份中的星期 Number 2
E 星期中的天數 Text Tuesday; Tue
a Am/pm 標記 Text PM
H 一天中的小時數(0-23) Number 0
k 一天中的小時數(1-24) Number 24
K am/pm 中的小時數(0-11) Number 0
h am/pm 中的小時數(1-12) Number 12
m 小時中的分鐘數 Number 30
s 分鐘中的秒數 Number 55
S 毫秒數 Number 978
z 時區 General time zone Pacific Standard Time; PST; GMT-08:00
Z 時區 RFC 822 time zone -0800
複製代碼
這個是Java8 後的推薦轉換使用類。
2.3.1 字符串轉換時間對象:
// 定義一個任意格式的日期時間字符串
String str1 = "2014==04==12 01時06分09秒";
// 根據須要解析的日期、時間字符串定義解析所用的格式器
DateTimeFormatter fomatter1 = DateTimeFormatter.ofPattern("yyyy==MM==dd HH時mm分ss秒");
// 執行解析
LocalDateTime dt1 = LocalDateTime.parse(str1, fomatter1);
// ---下面代碼再次解析另外一個字符串---
String str2 = "2014$$$四月$$$13 20小時";
DateTimeFormatter fomatter2 = DateTimeFormatter.ofPattern("yyy$$$MMM$$$dd HH小時");
LocalDateTime dt2 = LocalDateTime.parse(str2, fomatter2);
複製代碼
這裏的使用方式和SimpleDateFormat
基本一致。
2.3.2 :時間對象轉換字符串:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy==MM==dd HH時mm分ss秒");
//'1. 和SimpleDateFormat的使用方法同樣,把時間對象做爲參數傳入'
formatter.format(LocalDateTime.now());
//'2. 把DateTimeFormatter做爲參數傳入'
LocalDateTime.now().format(formatter);
複製代碼
咱們能夠看到獲取某二個日期直接差值的對象,主要是:年月日的Period
類和秒的Duration
類.
時間顆粒度轉換 :
好比我想算N個小時M分鐘有幾秒,不少人多是這麼寫的
N* 60 * 60 + M * 60;
複製代碼
其實有了TimeUnit
這個類,不少不一樣時間單位的相互轉換很是方便。
TimeUnit.HOURS.toSeconds(N) + TimeUnit.MINUTES.toSeconds(M);
複製代碼
特別是換算成其餘毫秒等,使用通常的乘法,那麼多個0,很容易弄錯,用TimeUnit就很方便了:
TimeUnit.HOURS.toMillis(N) + TimeUnit.MINUTES.toMillis(M);
複製代碼
//把3天轉化成小時
TimeUnit.HOURS.convert( 3 , TimeUnit.DAYS );
//結果是:72
複製代碼
延時:
除了這個,TimeUnit
還能夠用在線程Sleep:
通常人寫線程休眠:
Thread.sleep( 5 * 1000 );
複製代碼
使用TimeUnit
:
TimeUnit.SECONDS.sleep( 5 );
複製代碼
還有timeJoin/timeWait
等,都是同理。
回到剛開始的問題,咱們剛開始提的歌曲時長獲取:
咱們也能夠經過這些自帶的時間工具類(我隨便舉二個寫法,固然還有其餘寫法:)
String str = "00:03:06";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
LocalTime localTime = LocalTime.parse(str, formatter);
localTime.toSecondOfDay();//186
String str1 = "00:00:00";
LocalTime time1 = LocalTime.parse(str1);
String str2 = "00:03:06";
LocalTime time2 = LocalTime.parse(str2);
Duration duration = Duration.between(time1,time2);
duration.getSeconds(); //186
複製代碼
又是很懶的不更新文章.........有錯誤的請指出哦。