Java时间API总结

154 阅读6分钟

@[TOC]

在做项目中入数据库的时候,碰到的问题:

需要获取系统时间,并且获取系统 24h 后的时间(作为数据的失效时间)

文后将用 Java8 的时间 API 给出这个问题的方案

Date 类

Date 类主要封装了系统的日期和时间的信息,表示系统的特定时间戳,可以精确到毫秒。Date 对象表示时间的默认顺序是星期、月、日、小时、分、秒、年。

构造方法

Java8 的构造方法使用下来这两个,Date() + Date(long date) ;其他的构造方法都被标记为:@Deprecated

public Date() {
     this(System.currentTimeMillis());
 }
//所以当我们只需要使用毫秒时,我们可以直接使用 System.currentTimeMillis()

public Date(long date) {
     fastTime = date;
	}
// 上面的构造函数最终也是调用下面的构造函数,

Date()

使用此构造方法分配的对象可以获取本地的当前时间(精确到秒)

Date date = new Date();
System.out.println(date);
//Thu Aug 01 20:54:32 CST 2019

simpleDateFormat

//格式化,可以转换成我们想要的任意格式
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(df.format(date));
//2019-08-01 20:59:19

Date(long date)

此种形式表示从 GMT 时间(格林尼治时间)1970年1月1日0时0分0秒开始经过参数 date 指定的毫秒数。

Date date = new Date(1000);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
System.out.println(df.format(date));
//1970-01-01 08:00:01

为什么小时是 08,而不是 00;因为使用 CST(China Standard Time)时区的时间,刚好比格林尼治时间多 8 个小时

常用方法

long getTime():返回子1970.1.1.00:00:00 GMT 以来,此 Date 对象表示的毫秒数。

Boolean after(Date when):判断此日期是否在指定日期之后

Boolean before(Date when):判断此日期是否在指定日期之前

Calendar 类

Calendar 类是一个抽象类,它为特定瞬间与 YEAR、MONTH、DAY_OF_MONTH、HOUR 等日历字段之间的转换提供了一些方法,并为之操作日历字段(如获得下星期日的日期)提供了一些方法。

创建 Calender 对象不能使用 new 关键字「抽象类」,但是它提供了一个 getInstance() 方法来获得 Calendar 类对象。

getInstance() 方法(静态方法)返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化。

Calendar calendar = Calendar.getInstance();
System.out.println(calendar);
System.out.println(calendar.getTime());
//

下面是打印 calendar 的结果:

java.util.GregorianCalendar[time=1577415516152,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=29,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=11,WEEK_OF_YEAR=52,WEEK_OF_MONTH=4,DAY_OF_MONTH=27,DAY_OF_YEAR=361,DAY_OF_WEEK=6,DAY_OF_WEEK_IN_MONTH=4,AM_PM=0,HOUR=10,HOUR_OF_DAY=10,MINUTE=58,SECOND=36,MILLISECOND=152,ZONE_OFFSET=28800000,DST_OFFSET=0]

Fri Dec 27 10:58:36 CST 2019

常用方法

int get(int field) :返回指定日历字段的值

Calendar calendar = Calendar.getInstance();
System.out.println(calendar.get(Calendar.YEAR));
//2019


//Calendar#getTime 源码;就是调用了 Date 的构造函数
 public final Date getTime() {
        return new Date(getTimeInMillis());
    }

Date getTime():返回一个表示此 Calendar 时间值(从格林威治时间 1970.01.01.00:00:00 到现在的毫秒偏移量)的Date对象

格式化时间

SimpleDateFormat:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//可指定任意的格式

java 8 时间API

日期时间

//获取当前日期
System.out.println(LocalDate.now());  //打印:2019-12-27

//获取当前时间
System.out.println(LocalTime.now());  //打印:11:19:28.735

//获取当前日期+时间
System.out.println(LocalDateTime.now());  //打印:2019-12-27T11:21:06.145

LocalDate

在 ISO-8601 日历系统中没有时区的日期;如 2019-12-27

此类不可变,并且是线程安全的

// 创建 LocalDate 的两种实例方式:
 LocalDate localDate1=LocalDate.now();
 LocalDate localDate2=LocalDate.of(1996,12,10);
// LocalDate localDate3=LocalDate.of(1996, Month.OCTOBER,10);  Month 也可这样(枚举)

 System.out.println(localDate1+"    "+localDate2);

// 2019-12-29    1996-12-10

将时间加/减一天

LocalDate localDate1 = LocalDate.now().plusDays(1);
localDate1.minusDays(1);
LocalDate localDate11 = localDate1.minusDays(1);

System.out.println(localDate1);
System.out.println(localDate11);

/**
2019-12-30
2019-12-29

为什么中间已经将当天加上的时间减去了,再减一次,应该是比今天(当前)时间少一天才对啊
	因为,LocalDate 是被 final 修饰的(和 String 一样),我们去改动它,原来引用保存的对象还是不变,会    新生成一个 LocalDate 对象原来操作的对像内容不变。
*/

解答开篇:

LocalDate localDate1 = LocalDate.now().plusDays(1); //加一天
LocalDate localDate1 = LocalDate.now().minusDays(1); //减一天

我们有时候和数据库判断,如果只需要精确到天数,那么这个就可以了。

LocalTime

在 ISO-8601 日历系统中没有时区的时间

此类不可变,并且也是线程安全的

// 创建 LocalTime 实例的两种方式:
LocalTime localTime1=LocalTime.now();
LocalTime localTime2=LocalTime.of(15,59,10);

System.out.println(localTime1+"  "+localTime2);

// 15:13:52.009  15:59:10

从打印出来的形式,知道 LocalTime 支持毫秒

此时如果与数据库时间交互,需要精确到小时、分钟、秒,则需要此类(不过一般过期啥的都是整天吧)

LocalTime localTime1 = LocalTime.of(23,30);
LocalTime localTime2 = localTime1.plusHours(8);
// 晚上休息8个小时
System.out.println(localTime1 +"  "+ localTime2);
// 23:30  07:30

LocalDateTime

在 ISO-8601 日历系统中没有时区的日期时间

此类不可变,并且也是线程安全的

//创建 LocalDateTime 实例的方式
LocalDateTime localDateTime1 = LocalDateTime.now();
LocalDateTime localDateTime2 = LocalDateTime.of(2019, 12, 10, 15, 37, 50);

System.out.println(localDateTime1 + "  " + localDateTime2);

//2019-12-29T15:37:49.283  2019-12-10T15:37:50

支持毫秒,此类的也是有各种可以调整时间的函数,从年到毫秒都有

ZoneDateTime

在 ISO-8601 日历系统中带有时区的日期时间

此类不可变,并且也是线程安全的

ZonedDateTime zonedDateTime1 = ZonedDateTime.now();

ZoneId zoneId = ZoneId.of("Asia/Shanghai");
ZonedDateTime zonedDateTime2 = ZonedDateTime.of(2019,12,10,4,2,1,1, zoneId);

System.out.println(zonedDateTime1 + "  " + zonedDateTime2);

//2019-12-29T15:31:40.921+08:00[Asia/Shanghai]  
//2019-12-10T04:02:01.000000001+08:00[Asia/Shanghai]

此类的也是有各种可以调整时间的函数,从年到毫秒都有

DateTimeFormatter

格式化日期时间,不可变且线程安全

String sminus = LocalDateTime.now().minusDays(2).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
String splus = LocalDateTime.now().plusDays(1).format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));

System.out.println(sminus + "  " + splus);
// 后面是格式化日期:方便入库
// 2019-12-27 15:41:11  2019/12/30 15:41:11

总结

对于我们在系统中经常会存储时间到数据库

以前:

new date() 后必须用 simpleDateFormat 格式化,而且一般有 只有“日期”和“日期时间”两个格式

Java8:

LocalDate.now() 直接就是数据库中存储“日期”得格式

“日期时间”则需要 DateTimeFormatter 格式化。

上面讲到的 Java8 时间API,当然都是 Java8 才引入的,以前 JDK 版本不可用。

都是:

  • 被 final 修饰,不可修改
  • 线程安全

tips:JDBC 映射日期类型

SQL ——> java

date——>LocalDate

time——> LocalTime

timestamp——>LocalDateTime