开发中经常涉及到时间与日期,记录下Java中与时间和日期相关的API
JDK8之前与时间日期相关的类
java.lang.System类
System类提供了一个公共的静态方法currentTimesMillis()来返回当前时间距离1970年1月1日0时0分0秒之间以毫秒为单位的时间差,也叫时间戳。
@Test
public void test1(){
long time = System.currentTimeMillis();
System.out.println(time);// 打印:1572305456261
}
java.util.Date类和java.sql.Date类
一个类的使用通常需要了解如何实例化和使用常用的方法。java.util.Date类的实例化主要涉及到两个构造器无参的构造器和带参数的构造器,常用方法也有两个toString方法和getTime方法。代码看下具体的使用:
@Test
public void test2(){
// 构造器1
Date date1 = new Date();
System.out.println(date1.toString());// Tue Oct 29 07:35:09 CST 2019
System.out.println(date1.getTime());// 1572305836011
// 构造器2
Date date2 = new Date(1572305836011L);
System.out.println(date2.toString()); // Tue Oct 29 07:37:16 CST 2019
说明:
关于java.util.Date类需要会使用两个构造器和两个方法。
使用空参的构造器: 创建一个对应当前时间的Date对象
使用带参的构造器:创建指定毫秒数的Date对象
使用toString方法:显示当前的年,月,日,分,时,秒,时区
使用getTime方法,获取当前Data对象对应的时间戳
java.sql.Date类是java.util.Date类的子类,主要用于处理数据库相关的日期格式。这里,同样只需要了解怎么使用即可。
实例化,使用带参的构造器,参数是一个long型的。
@Test
public void tese1(){
// java.sql.Date类的使用
java.sql.Date date3 = new java.sql.Date(1572305836011L);// 传入时间戳
System.out.println(date3.toString());// 2019-10-29
System.out.println(date3.getTime());//1572305836011
// 如何将一个java.sql.Date对象转化为java.util.Date对象?多态
// 如何将一个java.util.Date对象转化为java.sql.Date对象?共同点:毫秒数
// 方式一: 多态的做法,强转
Date date4 = new java.sql.Date(1572305836011L);
java.sql.Date date5 = (java.sql.Date)date4;
// 方式二:
Date date6 = new Date();
java.sql.Date date7 = new java.sql.Date(date6.getTime());
System.out.println(date7.toString());
}
java.text.SimpleDateFormat类
Date类的API不易于国际化,大部分被废弃了,java.text.SimpleDateFormat类是一个不与语言环境有关的方式来格式化和解析日期的具体类。它允许进行 格式化:日期-->文本、 解析:文本-->日期。
对于SimpleDateFormat的使用需要掌握两个点:
如何实例化?
如何进行格式化和解析?
@Test
public void test1() throws ParseException {
// 1.实例化:使用默认的构造器
SimpleDateFormat sdf = new SimpleDateFormat();
// 2.创建Date对象
Date date = new Date();
System.out.println(date); // Tue Oct 29 13:42:21 CST 2019
// 3.格式化
String date2 = sdf.format(date); //参数是Date类型的
System.out.println(date2); // 2019/10/29 下午1:43
// 4.解析
String str = "2019/10/29 下午1:43";
Date date3 = sdf.parse(str);
System.out.println(date3);
//***************************
//使用带参的构造器
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String s = simpleDateFormat.format(new Date());
System.out.println(s);
//解析
String s1 = "2020-10-29 02:02:59";
Date date4 = simpleDateFormat.parse(s1);
System.out.println(date4);
}
说明:
使用SimpleDateFormat的默认构造器创建出来的对象,去调用format方法进行时间日期的格式化后出来的格式是固定的,并且是2019/10/29 下午1:43这样的形式,要解析的字符串也必须以这种格式,否则解析不了。
开发中,常用第二种构造器,可以指定我们想过要输出的日期格式。
java.util.Calender日历类(抽象类)
Calendar是一个抽象基类,主用用于完成日期字段之间相互操作的功能。获取一个Calendar实例的方法如下:
使用Calendar.getInstance()方法
调用它的子类GregorianCalendar的构造器。
Calender的常见使用如下:
@Test
public void test1(){
//1.类的实例化方式:调用Calendar.getInstance方法
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getClass());// class java.util.GregorianCalendar
//2.常用方法
//get()方法
int day1 = calendar.get(calendar.DAY_OF_MONTH);// 获取calender对象是当前月的第几天
int day2 = calendar.get(calendar.DAY_OF_YEAR);// 获取当前calender对象是当前年的第几天
System.out.println(day1);
System.out.println(day2);
//set()方法
calendar.set(calendar.DAY_OF_MONTH,22); // 将calender对象的DAY_OF_MONTH属性设置为22,将原先的属性改了(可变性)
day1 = calendar.get(calendar.DAY_OF_MONTH);
System.out.println(day1);
//add()方法
calendar.add(calendar.DAY_OF_MONTH,3); // +3天
day1 = calendar.get(calendar.DAY_OF_MONTH);
System.out.println(day1);
calendar.add(calendar.DAY_OF_MONTH,-3);// -3天
day1 = calendar.get(calendar.DAY_OF_MONTH);
System.out.println(day1);
//getTime()方法 将日历类转换为Date
Date date = calendar.getTime();
System.out.println(date); //Tue Oct 22 13:06:05 CST 2019
//setTime()方法 将Date类转换为日历类
Date date1 = new Date(); // 获取当前时间的Date
calendar.setTime(date1);// 将当前日历设置为date1对象对应的时间
day1 = calendar.get(calendar.DAY_OF_MONTH);
System.out.println(day1);
}
注意:使用Calender
获取月份时,一月是0,二月是1,以此类推,12月是11
获取星期时,周日是1,周一是2,以此类推,周六是7
JDK8之后新的日期时间API
为什么要引进新的时间日期API?
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是用来表示日期和时间的,这是一个最常用的类之一。
同样,使用一个类还是从如何实例化和有什么方法使用开始。常用方法如下:
示例:
@Test
public void test1(){
// now获取当前的日期、时间、日期+时间
LocalDate localDate = LocalDate.now();// 获取当前的本地日期
LocalTime localTime = LocalTime.now();// 获取当前的本地时间
LocalDateTime localDateTime = LocalDateTime.now();// 获取当前的本地日期和本地时间
System.out.println(localDate); // 2019-10-31
System.out.println(localTime);// 13:35:03.225722700
System.out.println(localDateTime);// 2019-10-31T13:35:03.225722700
// of方法:设置年月日时分秒,没有偏移量
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 24, 13, 23, 56);
System.out.println(localDateTime1); // 2020-10-24T13:23:56
//getXxx()方法 获取属性
System.out.println(localDateTime1.getDayOfMonth());// 24 获取当前对象对应的日期是这个月的第几天
System.out.println(localDateTime1.getDayOfWeek());// SATURDAY 获取当前对象对应的日期是星期几
System.out.println(localDateTime1.getDayOfYear());// 298 获取当前天是这一年的第几天
System.out.println(localDateTime1.getMonth());// OCTOBER 获取月份
System.out.println(localDateTime1.getSecond());// 56 获取秒数
// withXxx() 设置相关的属性(体现不可变性,原先对象的with操作不会改变原来对象的属性)
LocalDateTime localDateTime2 = localDateTime.withHour(4); // 设置小时数为04
System.out.println(localDateTime); // 2019-10-31T13:41:51.553487900
System.out.println(localDateTime2);// 2019-10-31T04:41:51.553487900
// plusXxx() 加操作
LocalDateTime localDateTime3 = localDateTime.plusDays(5); // 在现有时间加上5天
System.out.println(localDateTime); // 2019-10-31T13:45:29.363506800
System.out.println(localDateTime3);// 2019-11-05T13:45:29.363506800
// minusXxx() 减操作
LocalDateTime localDateTime4 = localDateTime.minusMonths(2); // 在现有时间减去2个月
System.out.println(localDateTime.getMonth()); // OCTOBER
System.out.println(localDateTime4.getMonth());// AUGUST
}
常用还是LocalDateTime类。
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到当前时间的毫秒数,即为时间戳
示例:
@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)
将指定格式的字符序列解析为一个日期、时间
示例如下:
@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);
// 解析
TemporalAccessor parse1 = formatter2.parse("2019-10-31 02:30:29");
System.out.println(parse1);
}