开发中经常涉及到时间与日期,记录下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的使用需要掌握两个点:

  1. 如何实例化?
  2. 如何进行格式化和解析?
    @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是用来表示日期和时间的,这是一个最常用的类之一。

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

image.png

示例:

@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);
    }

syushin
948 声望316 粉丝