时间日期类-概述
生活中的时间
每个国家的时间,没有一个统一的标准,都是自己算自己的,行不行?
世界标准时间:格林尼治时间/格林威治时间(Greenwich Mean Time)简称 GMT
。现在提供的时间已经有些误差了,所以不再使用这个时间了,现在使用的是原子钟提供的时间
中国的标准时间:世界标准时间 +8小时 ,中国在东八区
时间换算公式
1秒 = 1000毫秒
1毫秒 = 1000微秒
1微秒 = 1000纳秒
计算机中的时间原点
计算机中的起始时间:1970年1月1日 00:00:00
原因:1969年8月,贝尔实验室的程序员肯汤普逊利用妻儿离开一个月的机会,开始着手创造一个全新的革命性的操作系统,他使用 B
编译语言在老旧的 PDP-7
机器上开发出了 Uix
的一个版本。随后,汤普逊和同事丹尼斯里奇改进了 B
语言,开发出了 C
语言,重写了 UNX
。
1970年1月1日算C语言的生日
1
2
3
// Long 是 long 的 包装类
long time = System . currentTimeMillis (); //打印的是从1970年1月1日到现在时间过了这么多毫秒
System . out . println ( time ); // 1575465416955
(图1
)
Calendar
日期计算,例如,从今天开始退后 65
天是第几天,今天是第几天
Timezone
是进行时区计算
时间日期类-Date构造方法
Date类概述和构造方法
Date
代表了一个特定时间,精确到毫秒
2020年1月1日 0:0:0
2030年1月1日 11:11:11
方法名
说明
public Date()
创建一个Date对象,表示默认时间
public Date(long date)
创建一个Date对象,表示指定时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TestDemo {
public static void main ( String [] args ) {
//那么这个时间就表示电脑中的当前时间。
Date date1 = new Date ();
System . out . println ( date1 );
//从计算机的时间原点开始,过了指定毫秒的那个时间。
Date date2 = new Date ( 0L ); //L表示的是long长整型
System . out . println ( date2 ); //Thu Jan 01 08:00:00 CST 1970
//从时间原点开始,过了0毫秒。
//因为我们是在中国,我们是在东八区需要+8小时。
//1970年1月1日 上午的9点
//60分 * 60秒 = 3600秒,3600秒 * 1000 = 3600000 毫秒 (参数是毫秒,1秒=1000毫秒)
Date date3 = new Date ( 3600L * 1000 );
System . out . println ( date3 );
}
}
总结
Date date1 = new Date();
→ 把当前时间封装成一个 Date
对象
Date date2 = new Date(0L);
→ 把从时间原点开始,过了指定 毫秒
的时间,封装成一个 Date
对象,需要考虑时差问题。
时间日期类-Date成员方法
Date类的常用方法
方法名
说明
public long getTime()
获取Date所代表的毫秒值
public void setTime(long time)
修改Date中的毫秒值
getYear (过时)
获取的是"从1900年开始到现在过了多少年"
getMonth (过时)
获取当前的月份,获取的月是从0开始的(0-11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TestDemo {
public static void main ( String [] args ) {
//把当前时间封装成一个date对象
Date date1 = new Date ();
//获取这个date对象的毫秒值---获取当前时间的毫秒值
long time = date1 . getTime ();
System . out . println ( time ); //2461471445407
//getTime获得的毫秒值与currentTimeMillis获取的毫秒值进行对比,查看获取的毫秒值是否正确
long time2 = System . currentTimeMillis ();
System . out . println ( time2 ); //2461471445407
//将当前系统的时间包装成一个data2对象,再通过setTime()来将data2设置成距1970.1.1.0:0:0过去0秒的时间
Date date2 = new Date ();
date2 . setTime ( OL ); //跟new Date(0L)效果一样
System . out . println ( date2 ); //Thu Jan 01 08:00:00 CST 1970
}
}
SimpleDataFormat概述
1
2
3
4
5
6
// 代码
Date date1 = new Date ();
System . out . println ( date1 );
// 控制台输出
Wed Jan 01 15 : 00 : 22 CST 2048
我们发现上面打印的时间不符合我们的阅读习惯,我们之前看到的时间是 2020-11-27 08:11:39
SimpleDataFormat
可以对 Date
对象,进行 格式化和解析
格式化:Date对象
→ 2020年1月1日 0:0:0
解析:2020年1月1日 0:0:0
→ Date对象
常用的模式字母及对应关系如下:
2020-11-11 13:27:06
→ yyyy-MM-dd HH:mm:ss
2020年11月11日 13:27:06
→ yyyy年MM月dd日 HH:mm:ss
SimpleDataFormat的构造方法
方法名
说明
public SimpleDateFormat()
构造一个SimpleDateFormat,使用默认格式
public SimpleDateFormat(String pattern)
构造一个SimpleDateFormat,使用指定的格式
1
2
3
4
5
6
7
8
9
public class TestDemo {
public static void main ( String [] args ) {
//当前时间的Date对象
Date date = new Date ();
//创建了一个日期格式。
SimpleDateFormat sdf = new SimpleDateFormat ( "yyyy年MM月dd日 HH:mm:ss" );
}
}
SimpleDataFormat格式化和解析日期
格式化(从 Date
到 String
)
public final String format(Date date) :将日期格式化成日期/时间字符串
解析(从 String
到 Date
)
public Date parse(String source) :从给定字符串的开始,解析文本以生成日期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class TestDemo {
public static void main ( String [] args ) {
//当前时间的Date对象
Date date = new Date ();
//创建了一个日期格式。
SimpleDateFormat sdf = new SimpleDateFormat ( "yyyy年MM月dd日 HH:mm:ss" );
String result1 = sdf . format ( date );
System . out . println ( result1 );
}
}
public class TestDemo {
public static void main ( String [] args ) {
String s = "2048-01-01" ;
//解析的格式要和字符串里时间的格式一样,否则会出现解析异常
SimpleDateFormat sdf = new simpleDateFormat ( "yyyy-MM-dd" );
Date date = sdf . parse ( s );
System . out . println ( date ); //Wed Jan 01 00:00:00 CST 2048
}
}
小结
格式化(从 Date
到 String
)
Public final String format(Date date) :把时间按照固定格式进行展示
解析(从 String
到 Date
)
Public Date parse(String source) :需要对时间进行计算
时间日期类-练习
案例:秒杀活动
秒杀开始时间:2020年11月11日 0:0:0
秒杀结束时间:2020年11月11日 0:10:0
小贾下单并付款的时间为:2020年11月11日 0:03:47
小皮下单并付款的时间为:2020年11月11日 0:10:11
用代码说明这两位同学有没有参加上秒杀活动?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class TestDemo {
public static void main ( String [] args ) {
String start = "2020年11月11日 0:0:0" ;
String end = "2020年11月11日 0:10:0" ;
String jia = "2020年11月11日 0:03:47" ;
String pi = "2020年11月11日 0:10:11" ;
SimpleDateFormat sdf = new simpleDateFormat ( "yyyyMMdd HH:mm:ss" );
long startTime = sdf . parse ( start ). getTime ();
long endTime = sdf . parse ( end ). getTime ();
long jiaTime = sdf . parse ( jia ). getTime ();
long piTime = sdf . parse ( pi ). getTime ();
if ( jiaTime >= startTime && jiaTime <= endTime ){
System . out . println ( "小贾同学参加上了秒杀活动" );
} else {
System . out . println ( "小贾同学没有参加上了秒杀活动" );
}
//---------------------------------------------
if ( piTime >= startTime && piTime <= endTime ){
System . out . println ( "小皮同学参加上了秒杀活动" );
} else {
System . out . println ( "小皮同学没有参加上了秒杀活动" );
}
}
}
Calendar
往前推 35
年是那天,往前推 10
个月是哪天,加多少天,减多少天,date
类解决不了
Calendar
:做表示日期以及日期计算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 获取当前 年份、月份、日期
public static void getDateTime () throws ParseException {
Calendar now = Calendar . getInstance ();
System . out . println ( "年: " + now . get ( Calendar . YEAR ));
System . out . println ( "月: " + ( now . get ( Calendar . MONTH ) + 1 ) + "" );
System . out . println ( "日: " + now . get ( Calendar . DAY_OF_MONTH ));
System . out . println ( "时: " + now . get ( Calendar . HOUR_OF_DAY ));
System . out . println ( "分: " + now . get ( Calendar . MINUTE ));
System . out . println ( "秒: " + now . get ( Calendar . SECOND ));
System . out . println ( "当前时间毫秒数:" + now . getTimeInMillis ());
System . out . println ( now . getTime ());
Date d = new Date ();
System . out . println ( d );
SimpleDateFormat sdf = new SimpleDateFormat ( "yyyy-MM-dd HH:mm:ss" );
String dateNowStr = sdf . format ( d );
System . out . println ( "格式化后的日期:" + dateNowStr );
String str = "2012-1-13 17:26:33" ; //要跟上面sdf定义的格式一样
Date today = sdf . parse ( str );
System . out . println ( "字符串转成日期:" + today );
}
LocalDate-概述
旧版日期时间的问题
设计不合理,在 java.util
和 java.sql
的包中都有日期类,java.util.Date
同时包含日期和时间,而 java.sql.Date
仅仅包含日期,此外用于格式化和解析的类在 java.text
包下
非线程安全,java.util.Date
是非线程安全的,所有的日期类都是可变的,这是 java
日期类最大的问题之一
时区处理麻烦,日期类并不提供国际化,没有时区支持
新日期时间的API介绍
JDK8
中增加了一套全新的日期时间 API
,这套 API
设计合理,是线程安全的,新的日期及时间 API
位于 java.time
包中,下面是一些关键的类
名称
描述
LocalDate
表示日期,包含年月日,格式为 2019-10-16
LocalTime
表示时间,包含时分秒,格式为 16:38:54.158549300
LocalDateTime
表示日期时间,包含年月日,时分秒,格式为 2018-09-06T15:33:56.750
DateTimeFormatter
日期时间格式化类
Instant
时间戳,表示一个特定的时间瞬间
Duration
用于计算2个时间(LocalTime,时分秒)的距离
Period
用于计算2个日期(LocalDate,年月日)的距离
ZonedDateTime
包含时区的时间
LocalDate-使用
LocalDate使用
java.util.Date
和 SimpleDateFormatter
都不是线程安全的,而 LocalDate
和 LocalTime
和最基本的 String
一样,是不变类型,不单线程安全,而且不能修改。
java.util.Date
月份是从 0
开始,一月是 0
,十二月是 11
。
java.time.LocalDate
月份和星期都改成了 enum
,就不可能再用错了。
java.util.Date
包含日期、时间、还有毫秒数,在新的 java8
中,日期和时间被明确划分为 LocalDate
和 LocalTime
LocalDate
无法包含时间,LocalTime
无法包含日期,当然,LocalDateTime
才能同时包含时间和日期。
java.util.Date
推算时间(比如往前推几天、往后推几天、推算某年某月第一天等等)要结合 Calender
要写好多代码,相当麻烦,LocaDate
只需要使用对应的方法即可。
总结
Date
月份从 0
开始,容易用错,LocalDate
用的是枚举,不容易出错
Date
包含年月日时分秒,太乱了,LocalDate
将年月日时分秒分开了
Date
推算时间需要配合 Calender
使用,代码开发量大,LocalDate
直接使用对应的方法即可
获取当前时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void localDateCreate () {
LocalDate yyyyMMdd = LocalDate . now ();
LocalTime HHmmsssss = LocalTime . now ();
LocalDateTime yyyyMMddHHmmssSSs = LocalDateTime . now ();
System . out . println ( "年月日:" + yyyyMMdd );
System . out , println ( "时分秒毫秒:" + HHmmssSSS );
System . out . println ( "年月日时分秒毫秒:" + yyyyMMddHHmmssSSS ):
//输出:
//年月日:2020-10-16
//时分秒毫秒:09:55:49.448
//年月日时分秒毫秒:2020-10-16T09:55:49.448
}
设置自定义日期,根据指定日期、时间创建对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void setDate () {
LocalDate yyyyMMdd = LocalDate . of ( 2020 , 10 , 15 );
LocalTime HHmmssSSs = LocalTime . of ( 10 , 10 , 10 );
LocalDateTime yyyyMMddHHmmssSss = LocalDateTime . of ( 2020 , 10 , 15 , 10 , 10 );
System . out . println ( "自定义的年月日:" + yyyyMMdd );
System . out . print1n ( "自定义时分秒毫秒:" + HHmmssSSS );
System . out . println ( "自定义年月日时分秒毫秒:" + yyyyMMddHHmmssSSS );
//输出:
//自定义的年月日:2020-10-15
//自定义时分秒毫秒:10:10:10
//自定义年月日时分秒毫秒:2020-10-15T10:10
}
日期的加减
方法名
说明
public LocalDateTime plusYears(long years)
添加或者减去年
public LocalDateTime plusMonths(long months)
添加或者减去月
public LocalDateTime plusDays(long days)
添加或者减去日
public LocalDateTime plusHours(long hours)
添加或者减去时
public LocalDateTime plusMinutes(long minutes)
添加或者减去分
public LocalDateTime plusSeconds(long seconds)
添加或者减去秒
public LocalDateTime plusWeeks(long weeks)
添加或者减去周
调用 plusYears()
方法,括号中传入增加或减少的年数
当传入的参数为正数时,表示增加年份
当传入的参数为负数时,表示减少年份
方法名
说明
public LocalDateTime minusYears(long years)
减去或者添加年
public LocalDateTime minusMonths(long months)
减去或者添加月
public LocalDateTime minusDays(long days)
减去或者添加日
public LocalDateTime minusHours(long hours)
减去或者添加时
public LocalDateTime minusMinutes(long minutes)
减去或者添加分
public LocalDateTime minusSeconds(long seconds)
减去或者添加秒
public LocalDateTime minusWeeks(long weeks)
减去或者添加周
调用 minusYears()
方法,括号中传入增加或减少的年数,minus
与 plus
不同的是:
当传入的参数为正数时,表示减少年份
当传入的参数为负数时,表示增加年份
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main ( String [] args ) {
LocalDate yyyyMMdd = LocalDate . now ();
LocalDate addOneDay = yyyyMMdd . plusDays ( 1L ); //添加一日
LocalDate addOneMonths = yyyyMMdd . plusMonths ( 1L ); //添加一月
LocalDate addOneYears = yyyyMMdd . plusYears ( 1L ); //添加一年
LocalDate addOneWeeks = yyyyMMdd . plusWeeks ( 1L ); //添加一周
LocalDate delOneDay = yyyyMMdd . minusDays ( 1L ); //减去一日
LocalDate delOneMonths = yyyyMMdd . minusMonths ( 1L ); //减去一月
LocalDate delOneYears = yyyyMMdd . minusYears ( 1L ); //减去一年
LocalDate delOneWeeks = yyyyMMdd . minusWeeks ( 1L ); //减去一周
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main ( String [] args ) {
LocalTime HHmmssSSs = LocalTime . now ();
LocalTime addOneHours = HHmmssSSS . plusHours ( 1L ); //添加1小时
LocalTime addOneMinutes = HHmmssSSS . plusMinutes ( 1L ); //添加1分钟
LocalTime addOneSeconds = HHmmssSSS . plusSeconds ( 1L ); //添加1秒
LocalTime addOneNanos = HHmmssSSS . plusNanos ( 1L ); //添加1纳秒
LocalTime delOneHours = HHmmssSSS . minusHours ( 1L ); //减去1小时
LocalTime delOneMinutes = HHmmssSSS . minusMinutes ( 1L ); //减去1分钟
LocalTime delOneSeconds = HHmmssSSS . minusSeconds ( 1L ); //减去1秒
LocalTime delOneNanos = HHmmssSSS . minusNanos ( 1L ); //减去1纳秒
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main ( String [] args ) {
LocalDateTime yyyyMMddHHmmssSSs = LocalDateTime . now ();
LocalDateTime localDateTimeaddOneDay = yyyyMMddHHmmssSSS . plusDays ( 1L ); //添加一日
LocalDateTime localDateTimeaddOneMonths = yyyyMMddHHmmssSSS . plusMonths ( 1L ); //添加一月
LocalDateTime localDateTimeaddOneYears = yyyyMMddHHmmssSSS . plusYears ( 1L ); //添加一年
LocalDateTime localDateTimeaddOneWeeks = yyyyMMddHHmmssSSS . plusWeeks ( 1L ); //添加一周
LocalDateTime localDateTimeaddOneHours = yyyyMMddHHmmssSSS . plusHours ( 1L ); //添加1小时
LocalDateTime localDateTimeaddOneMinutes = yyyyMMddHHmmssSSS . plusMinutes ( 1L ); //添加1分钟
LocalDateTime localDateTimeaddOneSeconds = yyyyMMddHHmmsssss . plusseconds ( 1L ); //添加1秒
LocalDateTime localDateTimeaddOneNanos = yyyyMMddHHmmssSSS . plusNanos ( 1L ); //添加1纳秒
LocalDateTime localDateTimedelOneDay = yyyyMMddHHmmssSSS . minusDays ( 1L ); //减去一日
LocalDateTime localDateTimedelOneMonths = yyyyMMddHHmmssSSS . minusMonths ( 1L ); //减去一月
LocalDateTime localDateTimedelOneYears = yyyyMMddHHmmssSSS . minusYears ( 1L ); //减去一年
LocalDateTime localDateTimedelOneWeeks = yyyyMMddHHmmssSSS . minusWeeks ( 1I ); //减去一周
LocalDateTime localDateTimedelOneHours = yyyyMMddHHmmssSSS . minusHours ( 1L ); //减去1小时
LocalDateTime localDateTimedelOneMinutes = yyyyMMddHHmmsssss . minusMinutes ( 1L ); //减去1分钟
LocalDateTime localDateTimedelOneSeconds = yyyyMMddHHmmsssss . minusseconds ( 1L ); //减去1秒
LocalDateTime localDateTimedelOneNanos = yyyyMMddHHmmssSSS . minusNanos ( 1L ); //减去1纳秒
}
将年月日等修改为指定的值,并返回新的日期(时间)对象
方法名
说明
public LocalDateTime withYear(int year)
直接修改年
public LocalDateTime withMonth(int month)
直接修改月
public LocalDateTime withDayOfMonth(int dayofmonth)
直接修改日期(一个月中的第几天)
public LocalDateTime withDayOfYear(int dayOfYear)
直接修改日期(一年中的第几天)
public LocalDateTime withHour(int hour)
直接修改小时
public LocalDateTime withMinute(int minute)
直接修改分钟
public LocalDateTime withSecond(int second)
直接修改秒
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main ( String [] args ) {
LocalDate yyyyMMdd = LocalDate . now ();
System . out . println ( "LocalDate yyyyMMdd 当前时间:" + yyyyMMdd );
LocalDate addDay = yyyyMMdd . plusDays ( 4 );
System . out . println ( "LocalDate yyyyMMdd 添加4天后的日期:" + addDay );
LocalDate directDesignationDate = yyyyMMdd . withDayofMonth ( 20 );
System . out . println ( "LocalDate yyyyMMdd 直接指定到当月第几号:" + directDesignationDate );
LocalDate directDesignationYearDate = yyyyMMdd . withDayofYear ( 20 );
System . out . println ( "LocalDate yyyyMMdd 直接指定到当年第几天:" + directDesignationYearDate );
LocalDate directDesignationYear = yyyyMMdd . withYear ( 2000 );
System . out . println ( "LocalDate yyyyMMdd 当前时间直接指定年份:" + directDesignationYear );
LocalDate directDesignationMonth = yyyyMMdd . withMonth ( 6 );
System . out . println ( "LocalDate yyyyMMdd 当前时间直接指定月份:" + directDesignationMonth );
}
注意:在进行日期时间修改的时候,原来的 LocalDate
对象是不会被修改,每次操作都是返回了一个新的 LocalDate
对象。
获取日期的年、月、周、时、分、秒
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public static void main ( String [] args ) {
LocalDateTime yyyyMMddHHmmssSss = LocalDateTime . now ();
//本年当中第多少天
int dayofYear = yyyyMMddHHmmsssss . getDayofYear ();
//本月当中第多少天
int dayofMonth = yyyyMMddHHmmsssss . getDayofMonth ();
//本周中星期几
DayofWeek dayofWeek = yyyyMMddHHmmsssss . getDayofweek ();
int value = dayofweek . getvalue ();
System . out . println ( "今天是" + yyyyMMddHHmmssSSS + "\n"
+ "本年当中第" + dayofYear + "天" + "\n"
+ "本月当中第" + dayofMonth + "天" + "\n"
+ "本周中星期" + value + "-即" + dayofWeek + "\n" );
//年
int year = yyyyMMddHHmmsssss . getYear ();
//月
Month month = yyyyMMddHHmmsssss . getMonth ();
//直接获取
int monthValue = yyyyMMddHHmmsssss . getMonthvalue ();
//日
int dayofMonth1 = yyyyMMddHHmmsssss . getDayofMonth ();
//时
int hour = yyyyMMddHHmmsssss . getHour ();
//分
int minute yyyyMMddHHmmsssss . getMinute ();
//秒
int second = yyyyMMddHHmmsssss . getsecond ();
//纳秒
int nano = yyyMMddHHmmsssss . getNano ();
System . out . println ( "今天是" + yyyyMMddHHmmssSSS + "\n"
+ "年:" + year + "\n"
+ "月:" + monthvalue + "-即" + month + "\n"
+ "日:" + dayofMonth1 + "\n"
+ "时:" + hour + "\n"
+ "分:" + minute + "\n"
+ "秒:" + second + "\n"
+ "纳秒:" + nano + "\n"
);
}
时间日期前后的比较与判断
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main ( String [] args ) {
LocalDate now = LocalDate . now ();
LocalDate of = LocalDate . of ( 2020 , 10 , 15 );
//判断of是否在now时间之前
boolean before = of . isBefore ( now );
System . out . println ( "判断of是否在now时间之前" + before );
//判断of是否在now时间之后
boolean after = of . isAfter ( now );
System . out . println ( "判断of是否在now时间之后" + after );
//判断两个时间是否相等
boolean equal = of . isEqual ( now );
System . out . println ( "判断两个时间是否相等" + equal );
//判断是否为闰年
boolean leapYear = now . isLeapYear ();
System . out . println ( "判断是否为闰年" + leapYear );
}
Java 8 时钟 clock
1
2
3
4
5
6
public static void main ( String [] args ) {
//返回当前时间,根据系统时间和UTC
Clock clock = Clock . systemUTC ();
System . out . println ( clock );
//运行结果:Systemclock[z]
}
时间戳
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 时间戳
* 事实上Instant就是java8以前的Date,
* 可以使用以下两个类中的方法在这两个类型之间进行转换,
* 比如 Date.from(Instant) 就是用来把Instant转换成java.util.date的,
* 而 new Date().toInstant() 就是将Date转换成Instant的
*/
@Test
public void instant () {
Instant instant = Instant . now ();
System . out . println ( instant );
Date date = Date . from ( instant );
Instant instant2 = date . toInstant ();
System . out . println ( date );
System . out . println ( instant2 );
}
在 JDK8
中给我们新增一个 Instant
类 (时间戳/时间线),内部保存了从 1970年1月1日 00:00:00
以来的秒和纳秒
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* Instant时间戳
* 可以用来统计时间消耗
*/
@Test
public void test7 () throws Exception {
Instant now = Instant . now ();
System . out . println ( "now =" + now );
//获取从1970年一月一日00:00:00到现在的纳秒
System . out . println ( now . getNano ());
Thread . sleep ( 5 );
Instant now1 = Instant . now ();
System . out . println ( "耗时:" + ( now1 . getNano () - now . getNano ()));
}
计算时间、日期间隔
使用 Period.between(开始时间,结束时间) 方法获取时间间隔的年月日
注:Period.between
中传入的参数是 LocalDate
型的对象,LocalDate
型只包含年月日
步骤:
先创建两个 LocalDate
对象
再使用 Period
调用 between
方法,传入两个 LocalDate
对象参数,再传给 Period
对象
再使用 period
对象调用获取相应时间的方法
使用 Duration.between(开始时间,结束时间) 方法获取时间间隔的秒、毫秒、纳秒:
注:Duration.between
中传入的参数是 LocalDateTime
型的对象,LocalDateTime
型包含年月日时分秒
步骤:
先创建两个 LocalDateTime
对象
再使用 Duration
调用 between
方法,传入两个 LocalDateTime
对象参数,再传给 Duration
对象
再使用 Duration
对象调用获取相应时间的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* 计算时间、日期间隔
* Duration: 用于计算两个 "时间" 间隔
* Period: 用于计算两个 "日期" 间隔
*/
@Test
public void durationorPeriod () {
LocalDateTime now = LocalDateTime . now ();
System . out . println ( "duration当前时间:" + now );
LocalDateTime of = LocalDateTime . of ( 2020 , 10 , 15 , 10 , 24 );
System . out . println ( "duration自定义时间:" + of );
//Duration: 用于计算两个"时间"间隔
Duration duration = Duration . between ( now , of );
System . out . println ( now + "与" + of + "间隔" + "\n"
+ "天:" + duration . toDays () + "\n"
+ "时:" + duration . toHours () + "\n"
+ "分:" + duration . toMinutes () + "\n"
+ "毫秒:" + duration . toMillis () + "\n"
+ "纳秒:" + duration . toNanos () + "\n"
);
LocalDate nowDate = LocalDate . now ();
System . out . println ( "period当前时间:" + now );
LocalDate ofDate = LocalDate . of ( 2020 , 10 , 15 );
System . out . println ( "period自定义时间:" + of );
//Period:用于计两个"日期"间隔
Period period = Period . between ( nowDate , ofDate );
Sy3tem . out . printIn ( "Period相差年数:" + period . getYears ());
System . out . println ( "Period相差月数:" + period . getMonths ());
System . out . println ( "Period相差日数:" + period . getDays ());
//还可以这样获取相差的年月日
System . out . println ( "-----" );
long years = period . get ( ChronoUnit . YEARS );
long months = period . get ( ChronoUnit . MONTHS );
long days = period . get ( ChronoUnit . DAYS );
System . out . println ( "Period相差的年月日分别为:" + years + "," + months + "," + days );
//注意,当获取两个日期的间隔时,并不是单纯的年月日对应的数字相加减,而是会先算出具体差多少天,在折算成相差几年几月几日的
}
(图2
)
LocalDate-日期格式化
将时间 对象
转化为日期 字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 将时间对象转化为日期字符串
*
时间日期的格式化(格式化后返回的类型是String) 自定格式 使用 DateTimeFormatter.ofPattern("yyyy-M-ddHH:mm:ss:SSS");
* 注:自定义转化的格式一定要与日期类型对应
* LocalDate只能设置仅含年月日的格式
* LocalTime只能设置仅含时分秒的格式
* LocalDateTime可以设置含年月日时分秒的格式
*/
@Test
public void formatterl () {
LocalDateTime now = LocalDateTime . now ();
DateTimeFormatter dtf = DateTimeFormatter . ofPattern ( "yyyy-MM-dd HH:mm:ss:SSS" );
String format = now . format ( dft );
System . out . println ( format );
//输出:2020-10-16 14:41:01:086
}
将时间 字符串
转化为日期 对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 将时间字符串形式转化为日期对象
* <p>
* 注:格式的写法必须与字符串的形式一样
* 2018-01-13 21:27:30 对应 yyyy-MM-dd HH:m:ss
* 20180113213328 对应 yyyyMMddHHmmss
* 否则会报运行时异常!
* <p>
* 但要记住:得到的最终结果都是类以2018-01-13T21:27:30的格式
* 因为在输出LocalDateTime对象时,会调用其重写的toString方法。
*/
@Test
public void formatter2 () {
String datestr = "2020-11-12" ;
DateTimeFormatter dtf = DateTimeFormatter . ofPattern ( "yyyy-MM-dd" );
LocalDate formatterDate = LocalDate . parse ( datestr , dtf );
System . out . println ( formatterDate );
//输出2020-11-12
}
将时间 日期对象
转化为 格式化后
的时间 日期对象
1
2
3
4
5
6
7
8
9
10
11
12
/**
* 将时间日期对象转为格式化后的时间日期对象
*/
@Test
public void formatter3 () {
//新的格式化API中,格式化后的结果都默认是String,有时我们也需要返回经过格式化的同类型对象
LocalDateTime ldt1 = LocalDateTime . now ();
DateTimeFormatter dtfl = DateTimeFormatter . ofPattern ( "yyyy-MM-dd HH:mm:ss" );
String temp = ldt1 . format ( dftl );
LocalDateTime formatedDateTime = LocalDateTime . parse ( temp , dftl );
System . out . println ( formatedDateTime );
}
总结
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 日期格式化
*/
@Test
public void test6 () {
LocalDateTime now = LocalDateTime . now ();
//指定格式 使用系统默认的格式 2021-05-27T16:16:38.139
DateTimeFormatter isoLocalDateTime = DateTimeFormatter . ISO_LOCAL_DATE_TIME ;
//将日期时间转换为字符串
String format = now . format ( isoLocalDateTime );
System . out . println ( "format =" + format );
//通过ofPattern方法来指定特定的格式
DateTimeFormatter dateTimeFormatter = DateTimeFormatter . ofPattern ( "yyyy-MM-dd HH:mm:ss" );
String format1 = now . format ( dateTimeFormatter );
//2021-05-27 16:16:38
System . out . println ( "format1 =" + format1 );
//将字符串解析为一个日期时间类型
LocalDateTime parse = LocalDateTime . parse ( "1997-05-06 22:45:16" , dateTimeFormatter );
// parse = 1997-05-06T22:45:16
System . out . println ( "parse =" + parse );
}
LocalDate-时间类型转换
ZoneOffset
表示 UTC
时区的 偏移量 ,而 ZoneId
表示 UTC
的 时区
UTC
偏移量是协调世界时(UTC
)和特定地点的日期与时间差异,其单位为小时和分钟
ZoneOffset.systemDefault()
:此方法返回系统默认时区的偏移量。换句话说,它返回的是相对于 UTC
的偏移量,以小时、分钟和秒的形式表示。例如,如果系统默认时区是 America/New_York
,那么返回的 ZoneOffset
将是 -04:56:02
。
ZoneId.systemDefault()
:此方法返回系统默认的时区 ID
。例如,如果系统默认时区是 America/New_York
,那么返回的 ZoneId
就会是 America/New_York
。
方式一
localDate
转 Date
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* localDate 转 date
* localDateTime 转 date
*/
@Test
public void localDateToDate () {
LocalDate now = LocalDate . now ();
Date from = Date . from ( now . atStartOfDay ( ZoneOffset . systemDefault ()). toInstant ());
LocalDateTime localDateTime = LocalDateTime . now ();
Date date = Date . from ( localDateTime . atZone ( ZoneOffset . ofHours ( 8 )). toInstant ()) ;
System . out . println ( from );
System . out . println ( date );
}
Date
转 localDate
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* date 转 localDate
* date 转 localDateTime
*/
@Test
public void dateToLocalDate () {
Date date = new Date ();
LocalDate localDate = date . toInstant (). atZone ( ZoneOffset . systemDefault ()). toLocalDate ();
System . out . println ( localDate );
LocalDateTime localDateTime = date . toInstant (). atZone ( ZoneOffset . systemDefault ()). toLocalDateTime ();
System . out . println ( localDateTime );
}
方式二
localDate
转 Date
1
2
3
4
5
6
public static void main ( String [] args ) {
LocalDate date = LocalDate . of ( 2006 , 07 , 26 );
ZoneId zone = ZoneId . systemDefault ();
Instant instant = date . atStartOfDay (). atZone ( zone ). toInstant ();
java . util . Date da = Date . from ( instant );
}
Date
转 localDate
1
2
3
4
5
6
public static void main ( String [] args ) {
Instant instant = new Date (). toInstant ();
ZoneId zone = ZoneId . systemDefault ();
LocalDateTime localDateTime = LocalDateTime . ofInstant ( instant , zone );
LocalDate localDate = localDateTime . toLocalDate ();
}
方式三
Date
转 localDate
1
new Date (). toInstant (). atZone ( ZoneId . systemDefault ()). toLocalDate ()
LocalDate
转 时间戳
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* LocalDate 转 时间戳
* LocalDateTime 转 时间戳
*/
@Test
public void localDateToInstant () {
LocalDate localDate = LocalDate . now () ;
long instant = localDate . atStartOfDay ( Zoneoffset . systemDefault ()). toInstant (). toEpochMilli ();
System . out . println ( instant );
LocalDateTime now = LocalDateTime . now ();
long instant1 = now . toInstant ( ZoneOffset . ofHours ( 8 )). toEpochMilli ();
System . out . println ( instant1 );
}
时间戳
转 localDate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 时间戳 转 LocalDate
* 时间戳 转 LocalDateTime
*/
@Test
public void instantToLocalDate () {
long time = new Date (). getTime ();
LocalDateTime localDateTime = Instant . ofEpochMilli ( time ). atZone ( ZoneOffset . systemDefault ()). toLocalDateTime ();
System . out . println ( localDateTime );
LocalDate localDate = Instant . ofEpochMilli ( time ). atZone ( ZoneOffset . systemDefault ()) toLocalDate ();
System . out . println ( localDate );
}
LocalDate-时间校正器
有时候我们需要调整,将日期调整到 下个月的第一天
等操作。这时我们通过时间校正器效果可能会更好。
TemporalAdjuster
:时间校正器。
TemporalAdjusters
:通过该类静态方法提供了大量的常用 TemporalAdjuster
的实现。
(图3
)
LocalDate-日期时间的时区
Java8
中加入了对时区的支持,LocalDate
、LocalTime
、LocalDateTime
是不带时区的,带时区的日期时间类分别为:ZonedDate
、ZonedTime
、ZonedDateTime
。 其中每个时区都对应着 ID
,ID
的格式为 区域/城市
。例如:Asia/Shanghai
等。 ZoneId
:该类中包含了所有的时区信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main ( String [] args ) {
//1.获取所有的时区id
ZoneId . getAvailableZoneIds (). forEach ( System . out :: println );
//获取当前时间 中国使用的 东八区的时区,比标准时间早8个小时
LocalDateTime now = LocalDateTime . now ();
System . out . print1n ( "now=" + now ); //2021-05-27T17:17:06.951
//获取标准时间
ZonedDateTime bz = ZonedDateTime . now ( Clock . systemUTC ());
System . out . print1n ( "bz=" + bz ); //2021-05-27T09:17:86.952z
//使用计算机默认的时区,创建日期时间
ZonedDateTime now1 = ZonedDateTime . now ();
System . out . println ( "now1 =" + now1 ); //2021-05-27 T17:17:06.952 + 08:00[Asia Shanghai]
//使用指定的时区创建日期时间
ZonedDateTime now2 = ZonedDateTime . now ( ZoneId . of ( "America/Marigot" ));
System . out . println ( "now2 =" + now2 );
}
(图4
)
(图5
)
转换符
详细说明
示例
%s
字符串类型
“值得点赞”
%c
字符类型
‘h’
%b
布尔类型
true
%d
整数类型(十进制)
88
%x
整数类型(十六进制)
FF
%o
整数类型(八进制)
77
%f
浮点类型
7.777
%a
十六进制浮点类型
FF.35AE
%e
指数类型
9.38e+5
%g
通用浮点类型(f和e类型中较短的)
%h
散列码
%d%
百分比类型
%n
换行符
%tx
日期与时间类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public static void main ( String [] args ) {
String str ;
// %s
str = String . format ( "Hi,%s" , "布鲁斯" );
System . out . println ( str );
// %c %n
str = String . format ( "字母c的大写是:%c %n" , 'C' );
System . out . println ( str );
// %b
str = String . format ( "布尔结果是:%b" , 3 > 2 );
System . out . println ( str );
// %d
str = String . format ( "100的一半是:%d" , 100 / 2 );
System . out . println ( str );
// %x
str = String . format ( "100的16进制数是:%x" , 100 );
System . out . println ( str );
// %o
str = String . format ( "100的8进制数是:%o" , 100 );
System . out . println ( str );
// %f
str = String . format ( "50元的书打8.5折扣是:%f 元" , 50 * 0 . 85 );
System . out . println ( str );
// %a
str = String . format ( "上面价格的16进制数是:%a" , 50 * 0 . 85 );
System . out . println ( str );
// %e
str = String . format ( "上面价格的指数表示:%e" , 50 * 0 . 85 );
System . out . println ( str );
// %g
str = String . format ( "上面价格的指数和浮点数结果的长度较短的是:%g" , 50 * 0 . 85 );
System . out . println ( str );
// %d%
str = String . format ( "上面的折扣是:%d%%" , 85 );
System . out . println ( str );
// %h
str = String . format ( "字母A的散列码是:%h" , 'A' );
System . out . println ( str );
}
(图6
)
标识
说明
+
为正数或负数添加符号
0
在数字位数不够的地方补上0
空格
在位数不够的地方补上空格
,
对数字分组,三位一隔,只可以用于十进制
(
使用括号将去掉负号的负数包含进来
#
让十六进制的数字加上OX,八进制的数字加上o; 辅助%x和%o的使用,相当于一种对数字进制的补充说明提示
<
格式化前一个转换符锁描述的参数
-
左对齐,不够位数的地方补上空格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public static void main ( String [] args ) {
// +
String str ;
str = String . format ( "数字的正负表示:%+d %d %+d %d" , 8 , 8 , - 8 , - 8 );
System . out . println ( str );
// -
str = String . format ( "左对齐:%-6d" , 8 );
System . out . println ( str );
// 0
str = String . format ( "缺位补零:%06d" , 8 );
System . out . println ( str );
// 空格
str = String . format ( "缺位补空格:% 6d" , 8 );
System . out . println ( str );
str = String . format ( "缺位补空格:% 6d" , - 8 );
System . out . println ( str );
// ,
str = String . format ( "数字分组:%,d" , 123456789 );
System . out . println ( str );
// (
str = String . format ( "括号用法:%(d" , - 8888 );
System . out . println ( str );
str = String . format ( "括号用法:%(d" , 8888 );
System . out . println ( str );
// #
str = String . format ( "#括号用法(十六进制):%#x" , 12 );
System . out . println ( str );
str = String . format ( "#括号用法(八进制):%#o" , 12 );
System . out . println ( str );
// <
str = String . format ( "<括号用法:%f %<3.1f" , 3 . 14 , 3 . 2 );
// "%<3.1f"作用的对象是前一个"%f"所作用的对象,3.1f
// f:代表接收的是浮点型参数;.1:保留一位小数;3:占三位字符 (包括小数点和小数部分)
//3.1 就是三位字符
System . out . println ( str );
}
(图7
)
标志
说明
c
包括全部日期和时间信息
F
“年-月-日"格式
D
‘月/日/年’格式
r
“HH:MM:SS PM”格式(12时制)
T
“HH:MM:SS”格式(24时制)
R
“HH:MM”格式(24时制)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main ( String [] args ) {
String str ;
// c
str = String . format ( "全部日期和时间信息:%tc" , new Date ());
System . out . println ( str );
// F
str = String . format ( "年-月-日格式:%tF" , new Date ());
System . out . println ( str );
//D
str = String . format ( "月/日/年格式:%tD" , new Date ());
System . out . println ( str );
//r
str = String . format ( "HH:MM:SS PM格式(12时制):%tr" , new Date ());
System . out . println ( str );
//T
str = String . format ( "HH:MM:SS格式(24时制):%tT" , new Date ());
System . out . println ( str );
//R
str = String . format ( "HH:MM格式(24时制):%tR" , new Date ());
System . out . println ( str );
// %.2f保留两位小数
str = String . format ( "3.14保留两位小数:%.2f" , 3 . 141 );
System . out . println ( str );
}
(图8
)
集合概述-集合与数组的对比
场景:
有一个长度为 3
的数组,此时存储 4
个元素,前三个元素可以正常存放,第四个元素无法存放(这是因为数组的长度是不可变的)
有一个长度为 3
的集合,此时存储 4
个元素,前三个元素没有任何问题,但是还有第四个元素,此时,集合会进行自动扩容,从长度 3
变为长度 4
(集合长度可变)
数组可以存 基本数据类型 和 引用数据类型
集合只能 存引用数据类型 不能 存基本数据类型
如果集合 要存储基本数据类型 ,那么实际 存储的是他们的包装类
(图9
)
集合和数组的对比:
数组的长度是不可变的,集合的长度是可变的
数组可以存储基本数据类型和引用数据类型
集合只能存储引用数据类型,如果要存储基本数据类型,需要存对应的包装类
集合概述-集合体系结构
(图10
)
List
和 Set
都是接口,平时所说的 List
集合、Set
集合说的都是他们的实现类,而我们在实际创建对象时,创建的也是他们的实现类
mindmap
root((集合))
Collection: 单列集合顶层接口, 集合中一次只能存取一个元素
List: 有序,存储和遍历的顺序一致, 有索引, 元素可以重复
ArrayList: 1.底层结构是数组, 查询快, 增删慢; 2.线程不安全, 效率高;
LinkedList: 1.底层数据结构是链表, 查询慢, 增删快; 2.线程不安全, 效率高;
Set: 无序,存储和遍历的顺序不一致, 无索引, 元素不可以重复
HashSet: 底层是hash
LinkedHashSet: 底层是 链表+hash表, 是Set集合体系中唯一有序的集合
TreeSet: 底层是树形结构
Map: 双列集合顶层接口, 集合中一次存取一对元素, 元素必须成对出现
HashMap: 键的底层是hash表, HashMap的键就是HashSet
LinkedHashSet: 键的底层是 链表+hash表, 是Map集合体系中唯一有序的集合
LinkedHashMap: 键的底层是 链表+hash表, 是Map集合体系中唯一有序的集合
TreeMap: 键的底层是树形结构, TreeMap的键就是TreeSet
mindmap
root((集合))
Collection: 单列集合顶层接口, 集合中一次只能存取一个元素
List: 有序,存储和遍历的顺序一致, 有索引, 元素可以重复
ArrayList: 1.底层结构是数组, 查询快, 增删慢; 2.线程不安全, 效率高;
LinkedList: 1.底层数据结构是链表, 查询慢, 增删快; 2.线程不安全, 效率高;
Set: 无序,存储和遍历的顺序不一致, 无索引, 元素不可以重复
HashSet: 底层是hash
LinkedHashSet: 底层是 链表+hash表, 是Set集合体系中唯一有序的集合
TreeSet: 底层是树形结构
Map: 双列集合顶层接口, 集合中一次存取一对元素, 元素必须成对出现
HashMap: 键的底层是hash表, HashMap的键就是HashSet
LinkedHashSet: 键的底层是 链表+hash表, 是Map集合体系中唯一有序的集合
LinkedHashMap: 键的底层是 链表+hash表, 是Map集合体系中唯一有序的集合
TreeMap: 键的底层是树形结构, TreeMap的键就是TreeSet