安卓中簡(jiǎn)單好用的時(shí)間格式化工具DateUtils

前言

JDK中提供了好用的SimpleDateFormat工具來(lái)幫我們把格式化時(shí)間哺眯,并且制定了格式化的規(guī)范,只要我們按照規(guī)范傳入字符串扒俯,就能隨意定制我們想要的時(shí)間格式奶卓,例如:

  • 傳入"yyyy.MM.dd G 'at' HH:mm:ss z"一疯,就能得到2001.07.04 AD at 12:08:56 PDT
  • 傳入"EEE, MMM d, ''yy",就能得到Wed, Jul 4, '01
  • 傳入"h:mm a"夺姑,就能得到12:08 PM

等等墩邀,具體用法 可以查閱官方文檔,用起來(lái)也非常方便盏浙。
但是近些年移動(dòng)互聯(lián)網(wǎng)發(fā)展迅速眉睹,用戶體驗(yàn)也被越來(lái)越多的重視起來(lái),對(duì)于時(shí)間的顯示也越來(lái)越人性化只盹。比如說聊天記錄的時(shí)間辣往,人們更愿意看到"兩分鐘前","一小時(shí)前"殖卑,"昨天"等樣式站削,而不是冷冰冰的幾月幾號(hào)幾點(diǎn)幾分。
當(dāng)產(chǎn)品給出了如上的需求時(shí)孵稽,很多開發(fā)者都是去判斷要顯示的時(shí)間與當(dāng)前時(shí)間的相對(duì)間隔许起,然后再查表得出需要顯示的時(shí)間。殊不知菩鲜,安卓已經(jīng)給我們提供好了相應(yīng)的工具园细,只需一個(gè)方法調(diào)用統(tǒng)統(tǒng)搞定。該工具就是今天的主角DateUtils接校,他位于android.text.format包下猛频。
作為系統(tǒng)提供的工具,當(dāng)然也會(huì)發(fā)揮本地化的優(yōu)勢(shì)蛛勉。格式化出來(lái)的時(shí)間也會(huì)跟隨系統(tǒng)系統(tǒng)自動(dòng)變化鹿寻,比如說如果系統(tǒng)默認(rèn)語(yǔ)言是中文,格式化出來(lái)的時(shí)間是"一分鐘前"诽凌,而如果系統(tǒng)語(yǔ)言是英語(yǔ)毡熏,格式化的時(shí)間就變成"one minute ago",省去了翻譯字符串的麻煩侣诵。

小試牛刀

按照上面描述的需求痢法,我們來(lái)看看用DateUtils如何實(shí)現(xiàn):

long currentTimeMillis = System.currentTimeMillis();
//兩分鐘前
Log.d(TAG, "getRelativeTimeSpanString " + DateUtils.getRelativeTimeSpanString(
                        currentTimeMillis - 2 * 60 * 1000));
//三個(gè)小時(shí)前
Log.d(TAG, "getRelativeTimeSpanString " + DateUtils.getRelativeTimeSpanString(
                        currentTimeMillis - 3 * 60 * 60 * 1000));
//一天前
Log.d(TAG, "getRelativeTimeSpanString " + DateUtils.getRelativeTimeSpanString(
                        currentTimeMillis - 28 * 60 * 60 * 1000));

打印出來(lái)的結(jié)果如下:

08-12 15:43:30.454 13935-13935/com.wangng.myapplication D/DateUtilsTAG: getRelativeTimeSpanString 2 分鐘前
08-12 15:43:30.454 13935-13935/com.wangng.myapplication D/DateUtilsTAG: getRelativeTimeSpanString 3 小時(shí)前
08-12 15:43:30.464 13935-13935/com.wangng.myapplication D/DateUtilsTAG: getRelativeTimeSpanString 昨天

getRelativeTimeSpanString有幾個(gè)重載方法:

public static CharSequence getRelativeTimeSpanString(long startTime)
public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution)
public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution, int flags)

我們來(lái)看看參數(shù)最多的最后一個(gè)方法,了解下這么多參數(shù)都有什么用杜顺。

  • long time : 即你需要格式化的時(shí)間财搁;
  • long now : 即你需要格式化的時(shí)間的相對(duì)時(shí)間,一般都是相對(duì)與當(dāng)前時(shí)間:System.currentTimeMillis()哑舒;
  • long minResolution : 忽略的最小時(shí)間妇拯,有五個(gè)固定的常量取值,下面會(huì)開一個(gè)段落專門講解;
  • int flags : 格式化的選項(xiàng)越锈,有幾個(gè)固定的取值仗嗦,也可以是這幾個(gè)固定取值的組合,下面會(huì)開一個(gè)段落專門講解甘凭。

其實(shí)看源碼就知道參數(shù)少的方法內(nèi)部最終都是調(diào)用的參數(shù)最多的方法稀拐。

public static CharSequence getRelativeTimeSpanString(long startTime) {
    return getRelativeTimeSpanString(startTime, System.currentTimeMillis(), MINUTE_IN_MILLIS);
}
public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution) {
    int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR | FORMAT_ABBREV_MONTH;
    return getRelativeTimeSpanString(time, now, minResolution, flags);
}

第三個(gè)參數(shù)minResolution

那個(gè)方法的注釋已經(jīng)寫的很清楚

the minimum timespan to report. For example, a time3 seconds in the past will be reported as "0 minutes ago" if this is set to MINUTE_IN_MILLIS. Pass one of 0,MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS

大致意思就是:格式化的時(shí)候忽略的最小時(shí)間,比如說:如果該參數(shù)被設(shè)置成MINUTE_IN_MILLIS丹弱,小于一分鐘的時(shí)間就會(huì)被忽略德撬,傳入的時(shí)間剛好是3秒前,由于小于一分鐘就會(huì)被忽略而格式化成"0分鐘前";
該參數(shù)的取值有:

  • 0 :即再小的時(shí)間間隔也不會(huì)被忽略躲胳;
  • MINUTE_IN_MILLIS :其值為60X1000蜓洪,如果間隔小于一分鐘就會(huì)被忽略,最常用坯苹;
  • HOUR_IN_MILLIS :其值為60X60X1000隆檀,如果時(shí)間間隔小于一個(gè)小時(shí)就會(huì)被忽略,詳見下面代碼打印結(jié)果粹湃;
  • DAY_IN_MILLIS :其值為24X60X60X1000恐仑,如果時(shí)間間隔小于一天就會(huì)被忽略,詳見下面代碼打印結(jié)果为鳄;
  • WEEK_IN_MILLIS :其值為7X24X60X60X1000裳仆,如果時(shí)間間隔小于一個(gè)周就會(huì)被忽略枯饿,詳見下面代碼打印結(jié)果拙友;
    為了更容易理解酬蹋,我們分別把函數(shù)的第三個(gè)參數(shù)設(shè)置成如上的幾個(gè)值挠阁,然后打印出來(lái)結(jié)果,一目了然:
DateUtils.getRelativeTimeSpanString(
                        currentTimeMillis - 2 * 60 * 1000,
                        currentTimeMillis,
                        DateUtils.MINUTE_IN_MILLIS,
                        DateUtils.FORMAT_SHOW_DATE)
DateUtils.getRelativeTimeSpanString(
                        currentTimeMillis - 3 * 60 * 60 * 1000,
                        currentTimeMillis,
                        DateUtils.DAY_IN_MILLIS,
                        DateUtils.FORMAT_SHOW_DATE)
DateUtils.getRelativeTimeSpanString(
                        currentTimeMillis - 28 * 60 * 60 * 1000,
                        currentTimeMillis,
                        DateUtils.DAY_IN_MILLIS,
                        DateUtils.FORMAT_SHOW_DATE)
DateUtils.getRelativeTimeSpanString(
                        currentTimeMillis - 180 * 60 * 60 * 1000,
                        currentTimeMillis,
                        DateUtils.DAY_IN_MILLIS,
                        DateUtils.FORMAT_SHOW_DATE)

為了直觀颜启,整理成表格如下:

時(shí)刻 時(shí)刻描述 MINUTE HOUR DAY WEEK
currentTimeMillis - 2 * 60 * 1000 兩分鐘前 2分鐘前 0小時(shí)前 今天 8月12日
currentTimeMillis - 3 * 60 * 60 * 1000 三小時(shí)前 3小時(shí)前 3小時(shí)前 今天 8月12日
currentTimeMillis - 28 * 60 * 60 * 1000 一天前 昨天 昨天 昨天 8月11日
currentTimeMillis - 180 * 60 * 60 * 1000 一周前 8月5日 8月5日 8月5日 8月5日

注1: 試驗(yàn)的當(dāng)前日期是8月12日
注2: 為了表格的簡(jiǎn)潔脏里,表格中的"MINUTE","HOUR","DAY","WEEK"均省略了后面的"IN_MILLIS"
注3 : markdown的表格真難用

如果看完上面的表格還有什么不清楚的踩麦,麻煩你去撞墻清醒一下腦袋壳猜。

第四個(gè)參數(shù)flags

我們知道,一個(gè)完整的時(shí)間包括年份滑凉,月份统扳,日期,星期畅姊,時(shí)咒钟,分,秒若未,當(dāng)然時(shí)分又有12小時(shí)制和24小時(shí)制朱嘴。flag的值就是限制顯示時(shí)間的哪些元素。
該參數(shù)可選的值包括:

  • FORMAT_SHOW_TIME單獨(dú)使用只顯示時(shí)和分,例如“下午12:16”萍嬉,或者“23:22”乌昔,具體是12小時(shí)制還是24小時(shí)制,取決于系統(tǒng)設(shè)置的樣式壤追,當(dāng)然也可以配合下面的FORMAT_12HOUR磕道,F(xiàn)ORMAT_24HOUR使用;
  • FORMAT_SHOW_WEEKDAY單獨(dú)使用只顯示星期幾行冰,例如“星期五”溺蕉;
  • FORMAT_SHOW_YEAR如果該值被設(shè)置了,則年份始終會(huì)顯示悼做,如果沒有設(shè)置疯特,年份只有在格式化的時(shí)間跟當(dāng)前時(shí)間不在同一年的時(shí)候顯示。例如現(xiàn)在是2017年8月12日肛走,而要格式化的時(shí)間是2017年7月22日漓雅,如果flag設(shè)置了FORMAT_SHOW_YEAR,則格式化出來(lái)的時(shí)間為“2017年7月12日”羹与,如果沒有設(shè)置FORMAT_SHOW_YEAR故硅,則格式化出來(lái)的時(shí)間為“7月12日”;
  • FORMAT_SHOW_DATE顯示月份和日期纵搁;
  • FORMAT_NO_MONTH_DAY顯示月份和日期當(dāng)中的月份吃衅,而不是日期,例如會(huì)顯示“八月”腾誉,而不是“8月18日”徘层;
  • FORMAT_12HOUR按照12小時(shí)制顯示,通常不要設(shè)置這個(gè)值利职,因?yàn)橄到y(tǒng)會(huì)自動(dòng)根據(jù)系統(tǒng)設(shè)置的顯示樣式來(lái)顯示趣效,如果FORMAT_12HOUR和FORMAT_24HOUR同時(shí)被設(shè)置,則按照FORMAT_24HOUR顯示猪贪;
  • FORMAT_24HOUR類似于FORMAT_12HOUR跷敬;
  • FORMAT_CAP_AMPM如果這個(gè)值和FORMAT_12HOUR同時(shí)被設(shè)置,則“AM”和“PM"會(huì)顯示成大寫热押;
  • FORMAT_NO_NOON正常情況下中午12點(diǎn)會(huì)被顯示成“noon”西傀,但是如果這個(gè)值和FORMAT_12HOUR同時(shí)被設(shè)置,則會(huì)顯示成“12pm”
  • FORMAT_CAP_NOON正常情況下中午12點(diǎn)會(huì)被顯示成“noon”桶癣,但是如果這個(gè)值被設(shè)置拥褂,則會(huì)顯示成“Noon”;
  • FORMAT_NO_MIDNIGHT類似于FORMAT_NO_NOON牙寞,正常情況下物業(yè)12點(diǎn)會(huì)被顯示成“midnight”饺鹃,如果設(shè)置了該值,則顯示成“12am”;
  • FORMAT_CAP_MIDNIGHT類似于FORMAT_CAP_NOON悔详,“midnight”大寫顯示成“Midnight”镊屎;
  • FORMAT_ABBREV_TIME如果該值和FORMAT_12HOUR同時(shí)被設(shè)置,且時(shí)間剛好是整點(diǎn)伟端,則分“00”就會(huì)被省略杯道,例如“3:00pm”將會(huì)簡(jiǎn)寫成“3pm”;
  • FORMAT_ABBREV_WEEKDAY星期幾會(huì)被簡(jiǎn)寫成三個(gè)字母的字符串责蝠,當(dāng)然這是在系統(tǒng)語(yǔ)言是英語(yǔ)的情況下党巾,例如“Sunday”會(huì)簡(jiǎn)寫成“Sun”;
  • FORMAT_ABBREV_MONTH類似于FORMAT_ABBREV_WEEKDAY霜医,簡(jiǎn)寫月份成三個(gè)字母的字符串齿拂;
  • FORMAT_ABBREV_ALL時(shí)間,星期肴敛,月份都會(huì)按照對(duì)應(yīng)的簡(jiǎn)寫規(guī)則簡(jiǎn)寫署海;
  • FORMAT_NUMERIC_DATE如果該值被設(shè)置,則直接格式化成“12/13”医男,而不是顯示月份的名稱砸狞,如“December 31”

參數(shù)的名字叫“flags”,是復(fù)數(shù)形式镀梭,所以意味著我們可以疊加這些flag使用刀森。舉個(gè)例子,大家就明白怎么用了:

DateUtils.formatDateTime(getActivity(),
        System.currentTimeMillis(), DateUtils.FORMAT_SHOW_TIME
                | DateUtils.FORMAT_SHOW_DATE
                | DateUtils.FORMAT_ABBREV_ALL)

分析上面的代碼报账,flag用到了FORMAT_SHOW_TIME研底,F(xiàn)ORMAT_SHOW_DATE,根據(jù)我們上面的介紹透罢,可以推斷會(huì)顯示出時(shí)間和日期榜晦,又用到了FORMAT_ABBREV_ALL,所以月份和時(shí)間都會(huì)采用簡(jiǎn)寫形式羽圃,打印一下:8月12日 下午8點(diǎn)15乾胶,F(xiàn)ORMAT_ABBREV_ALL貌似沒起作用,但是如果把系統(tǒng)語(yǔ)言切換成英語(yǔ)朽寞,就能看到差別了:“Aug 12, 8:15 PM”胚吁。

DateUtils的其他方法

public boolean isToday(long when)

從方法名就能看出來(lái),判斷傳入時(shí)間是否跟今天是同一天愁憔,在發(fā)送某個(gè)頁(yè)面的UV統(tǒng)計(jì)的時(shí)候非常好用。

public static String formatDateRange(Context context, long startMillis,
            long endMillis, int flags)
public static Formatter formatDateRange(Context context, Formatter formatter, long startMillis,
            long endMillis, int flags)
public static Formatter formatDateRange(Context context, Formatter formatter, 
            long startMillis,long endMillis, int flags, String timeZone)

格式化一個(gè)時(shí)間區(qū)間孽拷,比如說電商的一個(gè)活動(dòng)的活動(dòng)時(shí)間就是由開始時(shí)間和結(jié)束時(shí)間組成吨掌,用上面的方法格式化就很方便。

小結(jié)

其實(shí)要是弄懂了flag的用法,就基本上已經(jīng)掌握了這個(gè)工具類了膜宋。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末窿侈,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子秋茫,更是在濱河造成了極大的恐慌史简,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肛著,死亡現(xiàn)場(chǎng)離奇詭異圆兵,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)枢贿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門殉农,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人局荚,你說我怎么就攤上這事超凳。” “怎么了耀态?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵轮傍,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我首装,道長(zhǎng)创夜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任簿盅,我火速辦了婚禮挥下,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘桨醋。我一直安慰自己棚瘟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布喜最。 她就那樣靜靜地躺著偎蘸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瞬内。 梳的紋絲不亂的頭發(fā)上迷雪,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音虫蝶,去河邊找鬼章咧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛能真,可吹牛的內(nèi)容都是我干的赁严。 我是一名探鬼主播扰柠,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼疼约!你這毒婦竟也來(lái)了卤档?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤程剥,失蹤者是張志新(化名)和其女友劉穎劝枣,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體织鲸,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舔腾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昙沦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琢唾。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖盾饮,靈堂內(nèi)的尸體忽然破棺而出采桃,到底是詐尸還是另有隱情,我是刑警寧澤丘损,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布普办,位于F島的核電站,受9級(jí)特大地震影響徘钥,放射性物質(zhì)發(fā)生泄漏衔蹲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一呈础、第九天 我趴在偏房一處隱蔽的房頂上張望舆驶。 院中可真熱鬧,春花似錦而钞、人聲如沸沙廉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)撬陵。三九已至,卻和暖如春网缝,著一層夾襖步出監(jiān)牢的瞬間巨税,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工粉臊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留草添,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓扼仲,卻偏偏與公主長(zhǎng)得像果元,于是被迫代替她去往敵國(guó)和親促王。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容