Java日期类总结

JDK8之前——旧时间日期类

java.lang.System类

System类提供了一个公共的静态方法currentTimesMillis()来返回当前时间距离1970年1月1日0时0分0秒之间以毫秒为单位的时间差,也叫时间戳。

1
2
3
4
public static void main(String[] args){
long time = System.currentTimeMillis();
System.out.println(time);// 打印:1652875534552
}

java.util.Date 和 java.sql.Date

java.util.Date

java.util.Date的构造函数主要有下面4种:

1
2
3
4
public Date() {}//系统当前时间戳
public Date(long date) {}//从1970年1月1日0时开始的毫秒数
public Date(int year, int month, int date){}//传入年(最小1900)月(0-11)日(1-31)参数
public Date(int year, int month, int date, int hrs, int min, int sec) {}//年月日时分秒,秒可选参数,同样都是从0开始

常用的方法有2个toString()getTime()

1
2
3
Date date = new Date();
System.out.println(date.toString());// Wed May 18 20:17:23 CST 2022
System.out.println(date.getTime());// 1652876243161

java.sql.Date

除了java.sql.Date之外,还有java.sql.Time和java.sql.Timestamp。它们3个都是继承自java.util.Date类,主要用于处理数据库相关的日期格式,这里简单介绍下java.sql.Date。

  1. java.sql.Date常用的构造器就是public Date(long date)(),传一个毫秒时间戳。

  2. java.sql.Date和java.util.Date最主要的区别就是,截取了时间信息,只保留日期信息

    1
    2
    3
    java.sql.Date date = new java.sql.Date(1652876243161L);// 传入时间戳
    System.out.println(date.toString());//2022-05-18
    System.out.println(date.getTime());//1652876243161
  3. java.sql.Date和java.util.Date之间的转换?

    1
    2
    3
    4
    5
    6
    7
    8
    // 方式一: 多态的做法,强转
    Date date1 = new java.sql.Date(1652876243161L);
    java.sql.Date date2 = (java.sql.Date)date1;

    // 方式二:构造函数传参
    Date date3 = new Date();
    java.sql.Date date4 = new java.sql.Date(date3.getTime());
    System.out.println(date4.toString());

java.text.SimpleDateFormat类

这个类主要用于日期的格式化和解析,即字符串和日期之间的相互转换。下面通过一个例子,看看如何创建SimpleDateFormat对象,以及如何解析和格式化日期。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 1.实例化:使用默认的构造器
SimpleDateFormat sdf = new SimpleDateFormat();
// 2.创建Date对象
Date date = new Date();
System.out.println(date); // Wed May 18 20:45:51 CST 2022
// 3.格式化
String date2 = sdf.format(date); //参数是Date类型的
System.out.println(date2); // 22-5-18 下午8:45
// 4.解析
String str = "22-5-18 下午8:45";
Date date3 = sdf.parse(str);
System.out.println(date3);//Wed May 18 20:45:00 CST 2022

//***************************
//使用带参的构造器
//hh:mm:ss表示12小时制,HH:mm:ss表示24小时制
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String s = simpleDateFormat.format(new Date());
System.out.println(s);//2022-05-18 08:45:51
//解析
String s1 = "2022-05-18 08:45:51";
Date date4 = simpleDateFormat.parse(s1);
System.out.println(date4);//Wed May 18 08:45:51 CST 2022

java.util.Calendar日历类

Calendar是一个抽象基类, 通过Calendar对象,我们可以像有个“日历”一样使用日期数据。比如,某个日期是那一年中的第几天?是那个月份的第几天?是那一周的第几天?等等。我们还可以通过Calendar对象实现一些简单的计算,比如add操作,给日期加几天或者减几天等等。

因为Calendar是抽象类,我们不能直接new一个日历对象,需要通过getInstance()获取一个日历对象,该方法默认返回一个GregorianCalendar实例。下面我们通过一个例子,简单了解下Canlendar的使用。

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
46
47
48
49
50
51
52
53
54
55
56
//获取一个日历实例
Calendar cal = Calendar.getInstance(); // GregorianCalendar
System.out.println("Calendar's toString() is : " + cal + "\n");
System.out.println("Time zone is: " + cal.getTimeZone() + "\n");

//通过getTime获取时间戳,返回Date对象
Date date = cal.getTime();
//Current date and time in Date's toString() is : Wed May 18 21:07:49 CST 2022
System.out.println("Current date and time in Date's toString() is : " + date + "\n");

// 获取各种field信息
//Year : 2022
System.out.println("Year : " + cal.get(Calendar.YEAR));
//Month : 4,注意月份是从0开始,4表示5月
System.out.println("Month : " + cal.get(Calendar.MONTH));
//Day of Month : 18
System.out.println("Day of Month : " + cal.get(Calendar.DAY_OF_MONTH));
//Day of Week : 4,周日是1,4表示星期三
System.out.println("Day of Week : " + cal.get(Calendar.DAY_OF_WEEK));
//Day of Year : 138
System.out.println("Day of Year : " + cal.get(Calendar.DAY_OF_YEAR));
//Week of Year : 21
System.out.println("Week of Year : " + cal.get(Calendar.WEEK_OF_YEAR));
//Week of Month : 3
System.out.println("Week of Month : " + cal.get(Calendar.WEEK_OF_MONTH));
//Day of the Week in Month : 3
System.out.println("Day of the Week in Month : " + cal.get(Calendar.DAY_OF_WEEK_IN_MONTH));
//Hour : 9,12小时制
System.out.println("Hour : " + cal.get(Calendar.HOUR));
//AM PM : 1
System.out.println("AM PM : " + cal.get(Calendar.AM_PM));
//Hour of the Day : 21,24小时制
System.out.println("Hour of the Day : " + cal.get(Calendar.HOUR_OF_DAY));
//Minute : 7
System.out.println("Minute : " + cal.get(Calendar.MINUTE));
//Second : 49
System.out.println("Second : " + cal.get(Calendar.SECOND));

// 加上若干天,可以是负数
Calendar calTemp;
calTemp = (Calendar) cal.clone();
calTemp.add(Calendar.DAY_OF_YEAR, -365);
//365 days ago, it was: Tue May 18 21:07:49 CST 2021
System.out.println("365 days ago, it was: " + calTemp.getTime());

//加上若干个小时
calTemp = (Calendar) cal.clone();
calTemp.add(Calendar.HOUR_OF_DAY, 11);
//After 11 hours, it will be: Thu May 19 08:07:49 CST 2022
System.out.println("After 11 hours, it will be: " + calTemp.getTime());

// Roll,回滚若干个小时
calTemp = (Calendar) cal.clone();
calTemp.roll(Calendar.HOUR_OF_DAY, 11);
System.out.println("Roll 11 hours, it will be: " + calTemp.getTime());
System.out.println();

JDK8之后——新时间日期类

为什么引进新日期类

JDK 1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少。它们面临的问题是:

  • 可变性:像日期和时间这样的类应该是不可变的。
  • 偏移性:Date中的年份是从1900开始的,而月份都从0开始。
  • 格式化:格式化只对Date有用,Calendar则不行。
  • 此外,它们也不是线程安全的;不能处理闰秒等。

JDK8中引进了新的时间API是java.time,新的 java.time 中包含了所有关于本地日期(LocalDate)本地时间(LocalTime)本地日期时间(LocalDateTime)时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 方法,用于把 Date 转换成新的表示形式。这些新增的本地化时间日期 API 大大简化了日期时间和本地化的管理。

LocalDate、LocalTime和LocalDateTime

LocalDate、LocalTime、LocalDateTime 类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。

  • LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。
  • LocalTime表示一个时间,而不是日期。
  • LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一。

同样,使用一个类还是从如何实例化和有什么方法使用开始。常用方法如下:

方法 描述
now() / now(ZoneId zone) 静态方法,根据当前时间创建对象或者指定时区
of() 静态方法,根据指定日期/时间创建对象
getDayOfMonth()/getDayOfYear() 获取所在月份中第几天(1~31)/所在年中第几天(1 ~ 366)
getDayOfWeek() 获得星期几,返回枚举值,比如“WEDNESDAY”,可以通过getValue()转成3
getMonth() 获得月份,返回枚举值,比如“MAY”,同样可以通过getValue()转成5
getMonthValue()/getYear() 获得月份的值,比如“18”,表示第18天
getHour()/getMinute()/getSecond() 返回小时、分钟和秒
withDayOfMonth()/withDayOfYear()/withMonth()/withYear() 将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象
plusDays()/plusWeeks()/plusMonths()/plusYears()/plusHours() 向当前对象添加几天、几周、几个月、几年、几小时
minusMonths()/minusWeeks()/minusDays()/minusYears()/minusHours() 从当前对象减去几天、几周、几个月、几年、几小时

Instant类

Instant类类似于Date类, java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间单位。Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒数。因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳秒级。

Instant的实例化和常用方法如下:

方法 说明
now() 静态方法,返回默认UTC时区的Instant类的对象
ofEpochMilli(long EpochMilli) 静态方法,返回在1970-01-01 00:00:00基础上加上指定毫秒数之后的Instant类的对象
atOffset(ZoneOffset offset) 结合即时的偏移来创建一个 OffsetDateTime
toEpochMilli() 返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void test2(){
// now():获取本初子午线当地的标准时间
Instant instant = Instant.now();
System.out.println(instant); // 2019-10-31T06:01:04.921252200Z

// 在UTC时区的基础上加上8个时区(北京时间)
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime); // 2019-10-31T14:01:04.921252200+08:00

// 获取时间戳
System.out.println(instant.toEpochMilli()); // 1572501664921

// ofEpochMilli():通过给定的时间戳,获取Instant的实例
Instant instant1 = Instant.ofEpochMilli(1572415933220L);
System.out.println(instant1); // 2019-10-30T06:12:13.220Z
}

DateTimeFormatter类

DateTimeFormatter类类似于SimpleDateFormat类,用于格式化与解析日期或时间。java.time.format.DateTimeFormatter 类:该类提供了三种格式化方法:

  • 预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
  • 本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
  • 自定义的格式。如:ofPattern(“yyyy-MM-dd HH:mm:ss”),常用是这种。
方 法 描 述
ofPattern(String pattern) 静态方法,返回一个指定字符串格的DateTimeFormatter
format(TemporalAccessor t) 格式化一个日期、时间,返回字符串
parse(CharSequence text) 将指定格式的字符序列解析为一个日期、时间
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
@Test
public void testDateTimeFormatter(){
// 实例化方式一 预定义的标准格式。如:`ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME`
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
LocalDateTime localDateTime = LocalDateTime.now();

// 格式化:将日期转换为字符串,需要传入一个TemporalAccessor类型的,而LocalDate、LocalTime和LocalDateTime都是
String str1 = formatter.format(localDateTime);
System.out.println(localDateTime); // 2019-10-31T14:16:15.801854
System.out.println(str1); // 2019-10-31T14:16:15.801854
// 使用标准格式的格式化出来结果是:2019-10-31T14:16:15.801854

// 解析:解析的字符串也必须是标准格式的字符创
TemporalAccessor parse = formatter.parse("2020-10-31T14:16:15.801854");
System.out.println(parse); // {},ISO resolved to 2020-10-31T14:16:15.801854

// 实例化方式二:本地化相关的格式
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);// 使用FormatStyle.SHORT进行格式化
// 格式化
String str2 = formatter1.format(localDateTime);
System.out.println(str2); // 格式化后的格式:2019/10/31 下午2:22

// 实例化方式三:自定义格式
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 格式化
String str3 = formatter2.format(LocalDateTime.now());
System.out.println(str3);//2022-05-18 22:10:32
// 解析
TemporalAccessor parse1 = formatter2.parse("2019-10-31 02:30:29");
System.out.println(parse1);
}

参考资料

  1. https://www3.ntu.edu.sg/home/ehchua/programming/java/DateTimeCalendar.html
  2. https://segmentfault.com/a/1190000020869634
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2022 Yin Peng
  • 引擎: Hexo   |  主题:修改自 Ayer
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信