android系统控件androidAndroid开发经验谈

安卓中简单好用的时间格式化工具DateUtils

2017-08-12  本文已影响2312人  胡几手

前言

JDK中提供了好用的SimpleDateFormat工具来帮我们把格式化时间,并且制定了格式化的规范,只要我们按照规范传入字符串,就能随意定制我们想要的时间格式,例如:

等等,具体用法 可以查阅官方文档,用起来也非常方便。
但是近些年移动互联网发展迅速,用户体验也被越来越多的重视起来,对于时间的显示也越来越人性化。比如说聊天记录的时间,人们更愿意看到"两分钟前","一小时前","昨天"等样式,而不是冷冰冰的几月几号几点几分。
当产品给出了如上的需求时,很多开发者都是去判断要显示的时间与当前时间的相对间隔,然后再查表得出需要显示的时间。殊不知,安卓已经给我们提供好了相应的工具,只需一个方法调用统统搞定。该工具就是今天的主角DateUtils,他位于android.text.format包下。
作为系统提供的工具,当然也会发挥本地化的优势。格式化出来的时间也会跟随系统系统自动变化,比如说如果系统默认语言是中文,格式化出来的时间是"一分钟前",而如果系统语言是英语,格式化的时间就变成"one minute ago",省去了翻译字符串的麻烦。

小试牛刀

按照上面描述的需求,我们来看看用DateUtils如何实现:

long currentTimeMillis = System.currentTimeMillis();
//两分钟前
Log.d(TAG, "getRelativeTimeSpanString " + DateUtils.getRelativeTimeSpanString(
                        currentTimeMillis - 2 * 60 * 1000));
//三个小时前
Log.d(TAG, "getRelativeTimeSpanString " + DateUtils.getRelativeTimeSpanString(
                        currentTimeMillis - 3 * 60 * 60 * 1000));
//一天前
Log.d(TAG, "getRelativeTimeSpanString " + DateUtils.getRelativeTimeSpanString(
                        currentTimeMillis - 28 * 60 * 60 * 1000));

打印出来的结果如下:

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 小时前
08-12 15:43:30.464 13935-13935/com.wangng.myapplication D/DateUtilsTAG: getRelativeTimeSpanString 昨天

getRelativeTimeSpanString有几个重载方法:

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)

我们来看看参数最多的最后一个方法,了解下这么多参数都有什么用。

其实看源码就知道参数少的方法内部最终都是调用的参数最多的方法。

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);
}

第三个参数minResolution

那个方法的注释已经写的很清楚

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

大致意思就是:格式化的时候忽略的最小时间,比如说:如果该参数被设置成MINUTE_IN_MILLIS,小于一分钟的时间就会被忽略,传入的时间刚好是3秒前,由于小于一分钟就会被忽略而格式化成"0分钟前";
该参数的取值有:

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)

为了直观,整理成表格如下:

时刻 时刻描述 MINUTE HOUR DAY WEEK
currentTimeMillis - 2 * 60 * 1000 两分钟前 2分钟前 0小时前 今天 8月12日
currentTimeMillis - 3 * 60 * 60 * 1000 三小时前 3小时前 3小时前 今天 8月12日
currentTimeMillis - 28 * 60 * 60 * 1000 一天前 昨天 昨天 昨天 8月11日
currentTimeMillis - 180 * 60 * 60 * 1000 一周前 8月5日 8月5日 8月5日 8月5日

注1: 试验的当前日期是8月12日
注2: 为了表格的简洁,表格中的"MINUTE","HOUR","DAY","WEEK"均省略了后面的"IN_MILLIS"
注3 : markdown的表格真难用

如果看完上面的表格还有什么不清楚的,麻烦你去撞墙清醒一下脑袋。

第四个参数flags

我们知道,一个完整的时间包括年份,月份,日期,星期,时,分,秒,当然时分又有12小时制和24小时制。flag的值就是限制显示时间的哪些元素。
该参数可选的值包括:

参数的名字叫“flags”,是复数形式,所以意味着我们可以叠加这些flag使用。举个例子,大家就明白怎么用了:

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

分析上面的代码,flag用到了FORMAT_SHOW_TIME,FORMAT_SHOW_DATE,根据我们上面的介绍,可以推断会显示出时间和日期,又用到了FORMAT_ABBREV_ALL,所以月份和时间都会采用简写形式,打印一下:8月12日 下午8点15,FORMAT_ABBREV_ALL貌似没起作用,但是如果把系统语言切换成英语,就能看到差别了:“Aug 12, 8:15 PM”。

DateUtils的其他方法

public boolean isToday(long when)

从方法名就能看出来,判断传入时间是否跟今天是同一天,在发送某个页面的UV统计的时候非常好用。

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)

格式化一个时间区间,比如说电商的一个活动的活动时间就是由开始时间和结束时间组成,用上面的方法格式化就很方便。

小结

其实要是弄懂了flag的用法,就基本上已经掌握了这个工具类了。

上一篇 下一篇

猜你喜欢

热点阅读