Android技能树 — 时间相关整体小结

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);
}
复制代码

上面代码固然没有任何问题,可是咱们其实能够用时间相关类来处理。工具


正文:

1. 时间获取

既然说到了时间相关知识,最主要的确定先要获取到时间。ui

1.1 Date:

其实看脑图,就已经很详细了,并且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)
复制代码

1.2 Calendar:

咱们知道了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对象进行比较,这里也不细说了:


其实咱们前面说的DateCalendar都是你们很熟悉的类,用的也是最多的,可是由于使用方式不友好,因此后面java8以后,都是使用新的·InstantLocalxxxx系列用来替换DateCalendar 的类了。

1.3 Instant:

不少人说,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小时,你们要注意下

1.4 LocalXXXXX系列

Local系列主要有: LocalTimeLocalDateLocalDateTime

从单纯的字面意思就能够看出来: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的使用和LocalTimeLocalDate的使用方法基本的同样。

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]

复制代码

咱们能够看到当前的时区,其余方法使用方式也基本都如出一辙。


2.时间格式化

前面咱们已经说了怎么获取到时间。接下去咱们讲时间和各类格式的字符串等各类相互转换。

  1. 但咱们知道界面上咱们想要显示的文字不一样: 2018-08-07 09:12:12,2018#08#07#09#12#12各类方式,这个是时间转成字符串显示。

  2. 而后假如别人传给你2018-08-07 09:12:122018#08#07#09#12#12,想要把字符串转换成时间对象。

2.1 DateFormat:

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可获取日期和时间格式。能够将不一样选项传入这些工厂方法,以控制结果的长度(从 SHORTMEDIUMLONG 再到 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 的解析和格式化方法形式来逐步地解析字符串的各部分。 对齐任意特定的字段,或者找出字符串在屏幕上的选择位置。 同步日期格式不是同步的。建议为每一个线程建立独立的格式实例。若是多个线程同时访问一个格式,则它必须保持外部同步。

2.2 SimpleDateFormat:

SimpleDateFormatDateFormat的子类,因此前面的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
复制代码

2.3 DateTimeFormatter:

这个是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);
复制代码

3.时间相关类

3.1 比较时间:

咱们能够看到获取某二个日期直接差值的对象,主要是:年月日的Period类和秒的Duration类.

3.2 时间辅助类:

3.2.1 TimeUnit:

时间颗粒度转换 :

好比我想算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

复制代码

又是很懒的不更新文章.........有错误的请指出哦。

相关文章
相关标签/搜索