Java 常用類-程式設計師頭大的日期時間API

EternityNoah發表於2020-10-02

第二節、日期時間API

一、JDK8之前日期時間API

1.1 java.lang.System類

System類提供的public static long currentTimeMillis()用來返回當前時間與1970年1月1日0時0分0秒之間以毫秒為單位的時間差

  • 此方法適於計算時間差

     @Test
        public void test1() {
            // 獲取當前時間;
            // 返回的是距離1970年的一個long型的數【毫秒數】,這種毫秒數通常稱為時間戳,通常用於生成訂單
            long timeMillis = System.currentTimeMillis();
            System.out.println(timeMillis);
        }
    // 執行結果
    1601090613188
    

1.2 java.util.Date類

java.util.Date類還有一個子類java.sql.Date類,對應著資料庫中的日期型別的變數。也就是說我們需要用java.sql.Date來表示資料庫中的date型別

表示特定的瞬間,精確到毫秒

  • 構造器:
    1. Date():使用無參構造器建立的物件可以獲取本地當前時間。
    2. Date(long date) :建立指定毫秒數的Date物件
  • 常用方法
    1. getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT 以來此 Date 物件 表示的毫秒數。(時間戳)
    2. toString():把此 Date 物件轉換為以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一週中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat),zzz是時間標準。
    3. 其它很多方法都過時了
@Test
    public void test2() {
        // 獲取當前時間
        Date date = new Date();
        System.out.println(date.toString());
        // 將日期時間格式轉為時間戳格式
        long time = date.getTime();
        System.out.println(time);
    }

1.3 java.text.SimpleDateFormat類

  1. 理論:

    • Date類的API不易於國際化,大部分被廢棄了,java.text.SimpleDateFormat 類是一個不與語言環境有關的方式來格式化和解析日期的具體類。

    • 它允許進行格式化:日期——>文字。解析:文字——>日期

    • 格式化

      • SimpleDateFormat() :預設的模式和語言環境建立物件

      • public SimpleDateFormat(String pattern):該構造方法可以用引數pattern 指定的格式建立一個物件,該物件呼叫:

      • public String format(Date date):方法格式化時間物件date

    • 解析:

    • public Date parse(String source):從給定字串的開始解析文字,以生成 一個日期

  2. 程式碼:

     @Test
        public void test7() throws ParseException {
            // 1.0 將日期格式化為指定格式
            Date date = new Date();
            System.out.println(date);
            /**
             * 構造器的引數可以有參也可以無參,無參那個缺乏靈活性。通常都用有參的這個構造器,自己制定格式,如:
             * 1. yyyy-MM-dd hh:mm:ss           年4位 月2位【為了和分鐘區別開,建議大寫】 日2位    時分秒各2位
             * 2. yyyy年MM月dd日 hh時mm分ss秒
             */
    //        SimpleDateFormat formatPattern = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            SimpleDateFormat formatPattern = new SimpleDateFormat("yyyy年MM月dd日 hh時mm分ss秒");
            String formatDate = formatPattern.format(date);
            System.out.println(formatDate);
    
            System.out.println("--------------我是分割線---------------");
    
            // 2.0 將字串解析為日期
            String strDate = "2020/10/01";
            // 注意:這裡需要指定型別,並且型別與字串型別需一致。不然會報一個ParseException異常。
            SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
            Date parse = format.parse(strDate);
            System.out.println(parse);
        }
    
  3. 問題

    如何將String str = "2020-11-11" 轉換為java.sql.Date格式?

    思路1:先把str轉為java.util.Date下的日期格式,再強制型別轉換

      @Test
        public void test8() throws ParseException {
            String str = "2020-11-11";
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            // 思路1:強制型別轉換
            java.sql.Date parse = (java.sql.Date)format.parse(str);
            System.out.println(parse);
        }
    

    報錯:java.lang.ClassCastException: java.util.Date cannot be cast to java.sql.Date 無法強制型別轉為java.sql.Date格式。

    分析原因:平常我們做的強制型別轉換是父類引用指向子類物件,再加強轉即可【多型】。如:

    Date date = new java.sql.Date(1601090613188L);
    java.sql.Date date1 = (java.sql.Date) date;
    System.out.println(date1);
    

    ​ 現在這個之所以會失敗,是因為我們相當於new了一個父類,直接將父類強制轉換為子類,這當然是錯的。【子類中有其他屬性、方法,父類中沒有,當然這種強制型別當然會失敗】

    思路2:通過時間戳

        @Test
        public void test9() throws ParseException {
            String str = "2020-11-11";
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            // 思路2:通過時間戳。【無論util下的Date還是sql下的Date都有時間戳,讓時間戳做中間商】
            Date parse = format.parse(str);
            long time = parse.getTime();
            java.sql.Date date = new java.sql.Date(time);
            System.out.println(date);
        }
    

1.4 java.util.Calendar(日曆)類

  1. Calendar是一個抽象基類,主用用於完成日期欄位之間相互操作的功能。

  2. 獲取Calendar例項的方法

    • 使用Calendar.getInstance()方法
    • 呼叫它的子類GregorianCalendar的構造器
  3. 一個Calendar的例項是系統時間的抽象表示,通過get(int field)方法來取得想 要的時間資訊。。比如YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY 、 MINUTE、SECOND

    • public void set(int field,int value)
    • public void add(int field,int amount)
    • public final Date getTime()
    • public final void setTime(Date date)
  4. 注意:

    • 獲取月份時:一月是0,二月是1,以此類推,12月是11
    • 獲取星期時:週日是1,週二是2 , 。。。。週六是7
  5. 程式碼

      @Test
        public void test10() {
            // 獲取Calendar例項
            Calendar calendar = Calendar.getInstance();
    
            // 獲取今天是今年的第幾天
            int yearDay = calendar.get(Calendar.DAY_OF_YEAR);
            System.out.println("今天是今年的第:"+yearDay+"天");
            // 獲取今天是這個月的第幾天
            int monthDay = calendar.get(Calendar.DAY_OF_MONTH);
            System.out.println("今天是這個月的第:"+monthDay+"天");
            // 獲取今天是本週的第幾天【注意這裡加了1的】
            int weekDay = calendar.get(Calendar.DAY_OF_WEEK);
            System.out.println("今天是本週的第幾:"+(weekDay-1)+"天");
    
            // public void set(int field,int value) 改值
            calendar.set(Calendar.DAY_OF_YEAR,1);
            int yearDayChange = calendar.get(Calendar.DAY_OF_YEAR);
            System.out.println("我把今天是今年的第"+yearDay+"天,改為今天是今年的第"+yearDayChange+"天");
    
            //  public void add(int field,int amount) 在原本的基礎上加
            calendar.set(Calendar.DAY_OF_MONTH,5);
            int monthAddDay = calendar.get(Calendar.DAY_OF_MONTH);
            System.out.println("今天是這個月的第:"+monthAddDay+"天,然而我加了5天時間");
    
            System.out.println("================不是分割線================");
    
            // getTime()   相當於把日曆——>new Date();
            Date time = calendar.getTime();
            System.out.println(time);
    
            // setTime()  相當於new Date()——>日曆
            Date date = new Date();
            calendar.setTime(date);
            System.out.println(date);
        }
    

二、JDK8中的日期時間API

  1. 第三次引入的API是成功的,並且Java 8中引入的java.time API 已經糾正了 過去的缺陷,將來很長一段時間內它都會為我們服務。
  2. Java 8 吸收了 Joda-Time 的精華,以一個新的開始為 Java 建立優秀的 API。 新的 java.time 中包含了所有關於本地日期(LocalDate)本地時間 (LocalTime)、本地日期時間(LocalDateTime)、時區(ZonedDateTime) 和持續時間(Duration)的類。歷史悠久的 Date 類新增了 toInstant() 方法, 用於把 Date 轉換成新的表示形式。這些新增的本地化時間日期 API 大大簡 化了日期時間和本地化的管理。

2.1 新時間日期API

  1. java.time – 包含值物件的基礎包
  2. java.time.chrono – 提供對不同的日曆系統的訪問
  3. java.time.format – 格式化和解析時間和日期
  4. java.time.temporal – 包括底層框架和擴充套件特性
  5. java.time.zone – 包含時區支援的

說明:大多數開發者只會用到基礎包和format包,也可能會用到temporal包。因此,盡 管有68個新的公開型別,大多數開發者,大概將只會用到其中的三分之一。

2.2 LocalDate、LocalTime、LocalDateTime

  1. LocalDate、LocalTime、LocalDateTime 類是其中較重要的幾個類,它們的例項 是不可變的物件,分別表示使用 ISO-8601日曆系統的日期、時間、日期和時間。 它們提供了簡單的本地日期或時間,並不包含當前的時間資訊,也不包含與時區 相關的資訊。
    • LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以儲存 生日、紀念日等日期。
    • LocalTime表示一個時間,而不是日期。
    • LocalDateTime是用來表示日期和時間的,這是一個最常用的類之一。

2.3 常用方法

  1. now() 靜態方法,根據當前時間建立物件/指定時區的物件

    @Test
        public void test1() {
            // 1. 獲取當前日期
            LocalDate nowDate = LocalDate.now();
            // 2. 獲取當前時間
            LocalTime nowTime = LocalTime.now();
            // 3. 獲取當前日期時間
            LocalDateTime nowDateTime = LocalDateTime.now();
            System.out.println("當前日期是:"+nowDate);
            System.out.println("當前時間是:"+nowTime);
            System.out.println("當前日期時間是:"+nowDateTime);
        }
    
  2. of(),靜態方法,根據指定日期/時間建立物件

    @Test
        public void test2() {
            LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 12, 12, 12);
            System.out.println(localDateTime);
        }
    
  3. getDayOfMonth()/getDayOfYear(),獲得月份天數(1-31) /獲得年份天數(1-366)

      @Test
        public void test3() {
            LocalDateTime localDateTime = LocalDateTime.now();
            // 1.獲得該月的第幾天
            int dayOfMonth = localDateTime.getDayOfMonth();
            System.out.println("今天是該月的第:" + dayOfMonth + "天");
            // 2. 獲得該年的第幾天
            int dayOfYear = localDateTime.getDayOfYear();
            System.out.println("今天是該年的第:"+dayOfYear+"天");
        }
    
    

2.4 瞬時:Instant

  1. Instant:時間線上的一個瞬時點。 這可能被用來記錄應用程式中的事件時間戳。

  2. 在處理時間和日期的時候,我們通常會想到年,月,日,時,分,秒。然而,這只是 時間的一個模型,是面向人類的。第二種通用模型是面向機器的,或者說是連續的。在此模型中,時間線中的一個點表示為一個很大的數,這有利於計算機處理。在UNIX中,這個數從1970年開始,以秒為的單位;同樣的,在Java中, 也是從1970年開始,但以毫秒為單位。

  3. java.time包通過值型別Instant提供機器檢視,不提供處理人類意義上的時間 單位。Instant表示時間線上的一點,而不需要任何上下文資訊,例如,時區。 概念上講,它只是簡單的表示自1970年1月1日0時0分0秒(UTC)開始的秒 數。因為java.time包是基於納秒計算的,所以Instant的精度可以達到納秒級

  4. (1 ns = 10-9 s) 1秒 = 1000毫秒 =106微秒=109納秒

  5. API

2.5 格式化與解析日期或時間

java.time.format.DateTimeFormatter 類:該類提供了三種格式化方法:

預定義的標準格式。如

  • ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
  • 本地化相關的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
  • 自定義的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)

程式碼:

@Test
    public void test4() {
      // DateTimeFormatter 格式化與解析日期或時間
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
        LocalDateTime localDateTime = LocalDateTime.now();
      // 格式化
        String format = dateTimeFormatter.format(localDateTime);
        System.out.println(format);// 2020-10-02 10:52:13
      //解析
        TemporalAccessor parse = dateTimeFormatter.parse("2020-10-02 10:52:13");
        System.out.println(parse);
    }

相關文章