Java的日期API

一、JDK8之前的时间API

1️⃣java.lang.System类

System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0分0秒之间以毫秒为单位的时间差
📌此方法适用于计算程序的运行时间 (时间戳)

public class DateTest {
    @Test
    public void test1(){
        long start=System.currentTimeMillis();
        //需要计算运行时间的程序
        process();
        long end=System.currentTimeMillis();
        System.out.println("程序运行时间为:"+(end-start)+"毫秒");
    }

    public void process(){
        for(int i=0;i<100;i++){
            if(i%2==0) System.out.println(i);
        }
    }
}

2️⃣java.util.Date类

表示特定的瞬间,精确到毫秒

  • 构造器
    Date() 使用无参构造器创建的对象可以获取本地当前的时间
    Date(long date) 将距离1970年1月1日0分0秒的毫秒数转化为年月日的形式
  • 常用方法
    getTime() 返回自1970年1月1日 00:00:00以来此Date对象表示的毫秒数
    toString() 把此Date对象转换为以下形式的String: dow mon dd hh:mm:ss zzz yyyy(dow是一周中的某一天,zzz是时间标准)
@Test
    public void test2(){
        Date date=new Date();
        System.out.println(date.toString());
        long dateMilli=date.getTime();
        System.out.println(dateMilli);


        //sleep
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Date date1=new Date(dateMilli);
        System.out.println(date1);
        Date date2=new Date();
        System.out.println(date2.toString());
    }

3️⃣java.sql.Date类

是java.util.Date的子类,所以自然支持多态。java.sql.Date对应着数据库中日期类型的变量

  • 构造器
    Date(long date) 将距离1970年1月1日0分0秒的毫秒数转化为年月日的形式
  • 常用方法
    getTime() 返回自1970年1月1日 00:00:00以来此Date对象表示的毫秒数
    toString() 转换成标准格式
  • 从数据库取出的sql.Date转换为程序中要使用的util.Date 多态
  • 将程序中的util.Date转换为数据库中的sql.Date
@Test
    public void test3(){
        Date date=new Date();
        java.sql.Date sqlDate=new java.sql.Date(date.getTime());
        System.out.println(date);
        System.out.println(sqlDate);
    }

4️⃣java.text.SimpleDateFormat类

Date类的API不易于国际化(格式单一且都是英文表示),大部分废弃了,java.text.SimpleDateFormat类是一个不与语言环境相关的方式来格式化和解析日期的具体类

  • 允许进行格式化和解析
  • 构造器
    SimpleDateFormat() 默认的模式和语言环境创建对象
    SimpleDateFormat(String pattern) 使用pattern指定的格式创建一个对象,可以使用API已有的,也可以自己指定格式
  • 格式化:Date -> String
    public String format(Date date) 格式化,将date变为指定pattern的字符串形式
  • 解析:String -> Date
    public Date parse(String str) 将给定的字符串(符合格式要求的)变为date形式,需要异常处理,防止没有按照要求写String
@Test
    public void testSimpleDateFormat() throws ParseException {
        //实例化SimpleDateFormat:使用默认的构造器
        SimpleDateFormat date = new SimpleDateFormat();
        Date date1=new Date();
        System.out.println(date1.toString());

        //格式化:date变为字符串
        String format=date.format(date1);
        System.out.println(format);

        //解析:格式化的逆过程,字符串变为date
        String str1="20-11-23 下午7:49";
        Date date2=date.parse(str1);
        System.out.println(date2.toString());

        System.out.println("********************");


        //*******调用带参的构造器按照指定的方式进行格式化*******
        SimpleDateFormat date3 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa");
                                                      //也可以按照自己指定的方式进行格式化
        String date3ToString = date3.format(date1);
        System.out.println(date3ToString);


        String str2="02020.十一月.23 公元 08:15 下午";
        Date str2ToDate = date3.parse(str2);
        System.out.println(str2ToDate.toString());

    }
📐练习题1

将字符串"2020-09-08"转换为sql.Date类型的

@Test
    /*
     *
     * @Description: 将字符串"2020-09-08"转换为sql.Date类型的
     *
     * @auther: ssy
     * @date: 10:42 2020/11/24
     * @param: []
     * @return: void
     *
     */
    public void test2() throws ParseException {
        String str="2020-09-08";
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        Date date=sdf.parse(str);
        System.out.println(date.toString());
        java.sql.Date res = new java.sql.Date(date.getTime());
        System.out.println(res.toString());
    }
📐练习题2

从1997-01-01开始,“三天打渔两天晒网”,到xxxx-xx-xx(键盘输入),在打渔还是筛网

  • 两个点
    ① 计算两个时间之间有多少天
    方法一:计算之间从1997-01-01到(xxxx-1)-12-31有几年(注意闰年),再计算剩下的月数,天数
    方法二:计算两者之间的毫秒时间差,除以一天的毫秒数,得到差的天数
    ②总天数取余5,结果为1/2/3则打渔,否则晒网
    代码采用的是方法二
public static void main(String[] args) throws ParseException {
        String start="1997-01-01";
        System.out.println("请按照格式输入年月日(xxxx-xx-xx),例如2020-09-01");
        Scanner in=new Scanner(System.in);
        String end = in.nextLine();

        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        Date startDate=sdf.parse(start);
        Date endDate = sdf.parse(end);

        int day=(int)(endDate.getTime()-startDate.getTime())/(24*60*60*1000)+1;
        System.out.println(day);
        if(day%5==0 ||day%5==4){
            System.out.println("今天在晒网");
        }
        else{
            System.out.println("今天在打渔");
        }
    }

5️⃣java.util.Calendar类

Calendar是一个抽象基类(不能通过new的方式直接声明一个对象),主要用于完成日期字段之间的相互操作。

  • 获取Calendar实例的一个方法
    调用它的子类GregorianCalendar的构造器
    使用Calendar.getInstance()方法,实际上创建的仍为GregorianCalendar对象
  • 常用方法
    get(int field) 获取常用的一些属性信息(field属性包括,Year,Month,Day,DAY_OF_WEAK,HOUR_OF_DAY等,是static常量,使用类进行调用)
    set(int field, int value) 修改Calendar的一些属性信息
    append(int field, int count) 将Calendar的指定属性添加count
    Date getTime() 将Calendar转换为Date类型
    void serTime(Date date)将Date类型转换为Calendar类型
  • 注意问题,获取月份(0-11)时,1月份为0,获取星期(1-7)时,周日为1
@Test
    public void test5(){
        Calendar cal=Calendar.getInstance();//创建当前时间的calendar实例
        System.out.println(cal.getClass());

        //get
        int days=cal.get(Calendar.DAY_OF_YEAR);
        System.out.println(days);

        //set
        cal.set(Calendar.DAY_OF_YEAR,266);
        days=cal.get(Calendar.DAY_OF_YEAR);
        System.out.println(days);

        //add
        cal.add(Calendar.DAY_OF_WEEK,2);
        days=cal.get(Calendar.DAY_OF_WEEK);
        System.out.println(days);

        //getTime
        Date date=cal.getTime();
        System.out.println(date.toString());

        //setTime
        Date date1 = new Date();
        cal.setTime(date1);
        days=cal.get(Calendar.DAY_OF_WEEK);
        System.out.println(days);

    }

二、JDK8的新日期时间API

  • 新时间API出现的背景:JDK1.0包含了一个java.util.Date类,但是它的多数方法已经在JDK1.1引入Calendar类之后被弃用,而Calendar并不比Date好多少,他们面临的问题是:
    ①可变性:像日期和时间这样的类应该是不可变的(对日期进行修改,例如Calendar.set(),应该保持原有对象不变,return一个改变后的对象)
    ②偏移性:Date中的年份是从1900年开始,而月份都是从0开始的(查看Date已经废弃的构造器Date(year,month,day)会发现year会在原有基础上加上1900)
    ③格式化:格式化只对Date有用,Calendar则不行
    ④线程不安全的:不能处理闰秒等
  • Java8引入的java.time API已经纠正了过去的缺陷,将来很长一段时间它都会为我们服务
  • Java8吸收了Joda-Time(第三方,在Java8以前的版本如果想使用java.time的东西,可以自己导入)的精华,新的java.time中包含了所有关于本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类
  • 经常用到的java.time——包含值对象的基础包 java.time.format——格式化和解析时间和日期

6️⃣LocalDate、LocalTime、LocalDateTime类

LocalDate、LocalTime、LocalDateTime是其中比较重要的几个类,它们的实例时不可变的对象

  • LocalDate:代表IOS格式(yyyy-MM-dd)的日期,可以存储生日、纪念日等日期
    LocalTime:表示一个时间,而不是日期
    LocalDateTime:用来表示日期和时间的,是最常用的一个类
  • 对象的创建(三个类的方法相同)
    now() :静态方法,根据当前时间创建对象
    of():静态方法,根据指定日期/时间创建对象
@Test
    public void test1(){
        LocalDateTime time1=LocalDateTime.now();
        LocalDateTime time2=LocalDateTime.of(2020,11,25,9,24);
        System.out.println(time1);
        System.out.println(time2);
    }

  • get相关属性
    getDayOfMonth()/getDayOfYear() :获取月份天数(1-31)/ 获取年份天数(1-366)
    getDayOfWeek():获得星期几(返回一个DayOfWeek枚举值)
    getMonth()/getMonthValue():获得月份,返回一个Month枚举值/获得月份(1-12)
    getYear():获得年份
    getHour()/getMinute()/getSecond:获得时/分/秒
@Test
    public void test2(){
        LocalDateTime time = LocalDateTime.now(); //获得当前日期时间
        System.out.println(time);  //2020-11-25T09:39:51.535
        System.out.println(time.getDayOfMonth());   //25
        System.out.println(time.getDayOfYear());    //330
        System.out.println(time.getDayOfWeek());    //WEDNESDAY
        System.out.println(time.getMonth());       //NOVEMBER
        System.out.println(time.getMonthValue());  //11
        System.out.println(time.getYear());        //2020
        System.out.println(time.getHour());        //9
        System.out.println(time.getMinute());      //39
        System.out.println(time.getSecond());      //51
    }
  • 对日期时间的修改
    withDayOfMonth()/withDayOfYear()/withMonth()/withYear():将相关属性修改为指定的值并返回新的对象
    plusDays()/plusWeeks()/plusMonths: 向当前对象添加几天、几周、几月并返回新的对象
    minusDays()/minusWeeks()/minusMonths: 从当前对象减去几天、几周、几月并返回新的对象
@Test
    public void test3(){
        LocalDateTime time = LocalDateTime.now();
        System.out.println(time);
        LocalDateTime time1=time.withDayOfMonth(11);
        System.out.println(time1);
        LocalDateTime time2=time.plusHours(3);
        System.out.println(time2);
        LocalDateTime time3=time.minusMonths(2);
        System.out.println(time3);
    }

7️⃣Instant类

时间线上的一个瞬时点,可能被用来记录应用程序中的事件时间戳,从(格林威治时间)1970年1月1日00:00:00开始,以毫秒为单位记录。Instant提供的是机器视图,不提供处理人类意义上的时间单位。Instant的精度可以达到纳秒。Instant相当于Date类

  • now():静态方法,返回默认UTC时区的Instant类对象
  • ofEpochMilli(long epochMilli):静态方法,返回在1970-01-01 00:00:00基础上加上指定毫秒数之后的Instant类对象
  • atOffset(ZonOffset offset):结合即时的偏移来创建一个OffsetDateTime
  • toEpochMilli():返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳
@Test
    public void test4(){
        //获取本初字符线对应的标准时间
        Instant instant1=Instant.now();
        System.out.println(instant1);
        System.out.println(instant1.toEpochMilli());
        Instant instant2=Instant.ofEpochMilli(1606269515960L);
        System.out.println(instant2);

        //添加时间偏移量
        OffsetDateTime offsetDateTime=instant1.atOffset(ZoneOffset.ofHours(8));
        System.out.println(offsetDateTime);
        System.out.println(offsetDateTime.toInstant().toEpochMilli());

    }

8️⃣java.time.format.DateTimeFormatter

该类提供了三种格式化方法:

  • 预定义的标准格式
    ISO_LOCAL_DATE_TIME,ISO_LOCAL_TIME,ISO_LOCAL_DATE
  • 本地化相关的格式
    如:ofLocalizedDateTime(FormatStyle.LONG)
    FormatStyle有多个 LONG,MEDIUM,SHORT,FULL
    FULL不适用于ofLocalizedDateTime,适用于ofLocalizedDate
  • 自定义方法
    ofPattern(String pattern)
  • String format(TemporalAccessor t):格式化一个日期、时间,返回字符串
  • TemporalAccessor parse(CharSequence text):将指定格式的字符序列解析为一个日期、时间,返回一个接口
@Test
    public void test5(){

        //预定义格式
        DateTimeFormatter formatter=DateTimeFormatter.ISO_LOCAL_DATE_TIME;

        //格式化: 日期->String
        LocalDateTime time = LocalDateTime.now();
        String str=formatter.format(time);   //format的参数要与formatter定义时的格式对应起来
        System.out.println(time);
        System.out.println(str);

        //解析:  String->日期
        String str1="2020-11-11T10:26:07.991";
        TemporalAccessor parse1 = formatter.parse(str1);  //使用接口承接,因为不同的formatter的格式定义不同
        System.out.println(parse1);

        //本地化相关的格式
        DateTimeFormatter formatter1=DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
        LocalDate date=LocalDate.now();
        System.out.println(formatter1.format(date));

        //自定义的方式
        DateTimeFormatter formatter2=DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String str2="2020-09-18";
        System.out.println(formatter2.format(time));
        System.out.println(formatter2.parse(str2));

    }
  • 💌以上只是初步了解一下基础内容,还有很多东西没有讲到,比方解析为TemporalAccessor 接口之后如何开展后续工作,具体用到的时候还需要深入学习
@Test
    public void test6(){
        DateTimeFormatter formatter=DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        LocalDateTime time=LocalDateTime.parse("2020-11-11T10:26:07.991",formatter);
        System.out.println(time);
    }
@Test
    public void test7(){
        DateTimeFormatter formatter=DateTimeFormatter.ofPattern("dd-MM-yyyy");
        LocalDate date=LocalDate.parse("22-06-1997",formatter);
        System.out.println(date);

    }
@Test
    public void test8(){

        DateTimeFormatter formatter=DateTimeFormatter.ISO_LOCAL_DATE_TIME;

        //解析:  String->日期
        String str1="2020-11-11T10:26:07.991";
        TemporalAccessor parse1 = formatter.parse(str1);  //使用接口承接,因为不同的formatter的格式定义不同
        LocalDateTime localDateTime1=LocalDateTime.from(parse1);
        System.out.println(localDateTime1);

    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容