Java常用API(二)

9.4.2 第二代日期時(shí)間(JDK1.1)

1、java.util.TimeZone

通常,使用 getDefault 獲取 TimeZonegetDefault 基于程序運(yùn)行所在的時(shí)區(qū)創(chuàng)建 TimeZone。

也可以用 getTimeZone 及時(shí)區(qū) ID 獲取 TimeZone 。例如美國太平洋時(shí)區(qū)的時(shí)區(qū) ID 是 "America/Los_Angeles"。

時(shí)區(qū).gif
package com.atguigu.datetime.two;
import org.junit.Test;
import java.util.TimeZone;
public class TestTimeZone {
    @Test
    public void test1(){
        TimeZone t = TimeZone.getDefault();
        System.out.println(t);
    }
    @Test
    public void test2(){
        TimeZone t = TimeZone.getTimeZone("UTC");
        System.out.println(t);
    }
    @Test
    public void test3(){
        TimeZone t = TimeZone.getTimeZone("America/Los_Angeles");
        System.out.println(t);
    }
    @Test
    public void test4(){
        String[] all = TimeZone.getAvailableIDs();
        for (int i = 0; i < all.length; i++) {
            System.out.println(all[i]);
        }
    }
}

常見時(shí)區(qū)ID:

Asia/Shanghai
UTC
America/New_York
America/Los_Angeles

2、java.util.Locale

Locale 對象表示了特定的地理、政治和文化地區(qū)。需要 Locale 來執(zhí)行其任務(wù)的操作稱為*語言環(huán)境敏感的* 操作,它使用 Locale 為用戶量身定制信息。

語言參數(shù)是一個(gè)有效的 **ISO 語言代碼**。這些代碼是由 ISO-639 定義的小寫兩字母代碼。

國家/地區(qū)參數(shù)是一個(gè)有效的 **ISO 國家/地區(qū)代碼**。這些代碼是由 ISO-3166 定義的大寫兩字母代碼。

Locale 類提供了一些方便的常量,可用這些常量為常用的語言環(huán)境創(chuàng)建 Locale 對象。

import org.junit.Test;
import java.util.Locale;
public class TestLocale {
    @Test
    public void test01(){
        Locale[] all = Locale.getAvailableLocales();
        for (int i = 0; i < all.length; i++) {
            System.out.println(all[i]);
        }
    }
    
    @Test
    public void test02(){
        Locale china = Locale.CHINA;
        System.out.println("china = " + china);
    }
}

3、java.util.Calendar

Calendar 類是一個(gè)抽象類,它為特定瞬間與一組諸如 YEAR、MONTHDAY_OF_MONTH、HOUR日歷字段之間的轉(zhuǎn)換提供了一些方法,并為操作日歷字段(例如獲得下星期的日期)提供了一些方法。瞬間可用毫秒值來表示,它是距*歷元*(即格林威治標(biāo)準(zhǔn)時(shí)間 1970 年 1 月 1 日的 00:00:00.000,格里高利歷)的偏移量。與其他語言環(huán)境敏感類一樣,Calendar 提供了一個(gè)類方法 getInstance,以獲得此類型的一個(gè)通用的對象。

image-20220123184906903-16769854303492.png

修改和獲取 YEAR、MONTH、DAY_OF_MONTH、HOUR日歷字段對應(yīng)的時(shí)間值。

void add(int field,int amount)
int get(int field)
void set(int field, int value)  

示例代碼:

package com.atguigu.datetime.two;
import org.junit.Test;
import java.util.Calendar;
import java.util.TimeZone;
public class TestCalendar {
    @Test
    public void test1(){
        Calendar c = Calendar.getInstance();
        System.out.println(c);
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DATE);
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        int second = c.get(Calendar.SECOND);
        System.out.println(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second);
    }
    @Test
    public void test2(){
        TimeZone t = TimeZone.getTimeZone("America/Los_Angeles");
        
        Calendar c = Calendar.getInstance(t);
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DATE);
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        int second = c.get(Calendar.SECOND);
        System.out.println(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second);
    }
}

9.4.3 第三代日期時(shí)間(JDK1.8)

Java1.0中包含了一個(gè)Date類,但是它的大多數(shù)方法已經(jīng)在Java 1.1引入Calendar類之后被棄用了。而Calendar并不比Date好多少。它們面臨的問題是:

  • 可變性:像日期和時(shí)間這樣的類對象應(yīng)該是不可變的。Calendar類中可以使用三種方法更改日歷字段:set()、add() 和 roll()。
  • 偏移性:Date中的年份是從1900開始的,而月份都是從0開始的。
  • 格式化:格式化只對Date有用,Calendar則不行。
  • 此外,它們也不是線程安全的,不能處理閏秒等。

可以說,對日期和時(shí)間的操作一直是Java程序員最痛苦的地方之一。第三次引入的API是成功的,并且java 8中引入的java.time API 已經(jīng)糾正了過去的缺陷,將來很長一段時(shí)間內(nèi)它都會為我們服務(wù)。

Java 8 吸收了 Joda-Time的精華,以一個(gè)新的開始為 Java 創(chuàng)建優(yōu)秀的 API。

  • java.time – 包含值對象的基礎(chǔ)包
  • java.time.chrono – 提供對不同的日歷系統(tǒng)的訪問。
  • java.time.format – 格式化和解析時(shí)間和日期
  • java.time.temporal – 包括底層框架和擴(kuò)展特性
  • java.time.zone – 包含時(shí)區(qū)支持的類

Java 8 吸收了 Joda-Time的精華,以一個(gè)新的開始為 Java 創(chuàng)建優(yōu)秀的 API。新的 java.time 中包含了所有關(guān)于時(shí)鐘(Clock),本地日期(LocalDate)、本地時(shí)間(LocalTime)、本地日期時(shí)間(LocalDateTime)、時(shí)區(qū)(ZonedDateTime)和持續(xù)時(shí)間(Duration)的類。

1、本地日期時(shí)間:LocalDate、LocalTime、LocalDateTime

序號方法描述
1now() / now(ZoneId zone)靜態(tài)方法,根據(jù)當(dāng)前時(shí)間創(chuàng)建對象/指定時(shí)區(qū)的對象
2of()靜態(tài)方法,根據(jù)指定日期/時(shí)間創(chuàng)建對象
3getDayOfMonth()/getDayOfYear()獲得月份天數(shù)(1-31) /獲得年份天數(shù)(1-366)
4getDayOfWeek()獲得星期幾(返回一個(gè) DayOfWeek 枚舉值)
5getMonth()獲得月份, 返回一個(gè) Month 枚舉值
6getMonthValue() / getYear()獲得月份(1-12) /獲得年份
7getHours()/getMinute()/getSecond()獲得當(dāng)前對象對應(yīng)的小時(shí)、分鐘、秒
8withDayOfMonth()/withDayOfYear()/withMonth()/withYear()將月份天數(shù)、年份天數(shù)、月份、年份修改為指定的值并返回新的對象
9with(TemporalAdjuster t)將當(dāng)前日期時(shí)間設(shè)置為校對器指定的日期時(shí)間
10plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours()向當(dāng)前對象添加幾天、幾周、幾個(gè)月、幾年、幾小時(shí)
11minusMonths() / minusWeeks()/minusDays()/minusYears()/minusHours()從當(dāng)前對象減去幾月、幾周、幾天、幾年、幾小時(shí)
12plus(TemporalAmount t)/minus(TemporalAmount t)添加或減少一個(gè) Duration 或 Period
13isBefore()/isAfter()比較兩個(gè) LocalDate
14isLeapYear()判斷是否是閏年(在LocalDate類中聲明)
import org.junit.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class TestLocalDateTime {
    @Test
    public void test7(){
        LocalDate now = LocalDate.now();
        LocalDate before = now.minusDays(100);
        System.out.println(before);//2019-02-26
    }
    @Test
    public void test06(){
        LocalDate lai = LocalDate.of(2019, 5, 13);
        LocalDate go = lai.plusDays(160);
        System.out.println(go);//2019-10-20
    }
    @Test
    public void test05(){
        LocalDate lai = LocalDate.of(2019, 5, 13);
        System.out.println(lai.getDayOfYear());
    }
    @Test
    public void test04(){
        LocalDate lai = LocalDate.of(2019, 5, 13);
        System.out.println(lai);
    }
    @Test
    public void test03(){
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);
    }
    @Test
    public void test02(){
        LocalTime now = LocalTime.now();
        System.out.println(now);
    }
    @Test
    public void test01(){
        LocalDate now = LocalDate.now();
        System.out.println(now);
    }
}

2、瞬時(shí):Instant、ZondId和ZonedDateTime

常見時(shí)區(qū)ID:

Asia/Shanghai
UTC
America/New_York
America/Los_Angeles

可以通過ZondId獲取所有可用的時(shí)區(qū)ID:

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;
public class TestZone {
    @Test
    public void test01() {
        //需要知道一些時(shí)區(qū)的id
        //Set<String>是一個(gè)集合,容器
        Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        //快捷模板iter
        for (String availableZoneId : availableZoneIds) {
            System.out.println(availableZoneId);
        }
    }
    @Test
    public void test02(){
        ZonedDateTime t1 = ZonedDateTime.now();
        System.out.println(t1);
        ZonedDateTime t2 = ZonedDateTime.now(ZoneId.of("America/New_York"));
        System.out.println(t2);
    }
    
    @Test
    public void test03(){
        Instant t = Instant.now();
        System.out.println(t);
    }
    
    @Test
    public void test4(){
        //以中國時(shí)區(qū)獲取當(dāng)前時(shí)間
        ZonedDateTime chinaNow = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
        //將中國時(shí)間轉(zhuǎn)換為美國紐約時(shí)間
        ZonedDateTime newYorkNow = chinaNow.withZoneSameInstant(ZoneId.of("America/New_York"));
        System.out.println("中國時(shí)區(qū)當(dāng)前時(shí)間:" + chinaNow);
        System.out.println("將中國時(shí)間轉(zhuǎn)換為美國紐約時(shí)間:"+newYorkNow);
    }
}

3、持續(xù)日期/時(shí)間:Period和Duration

Period:用于計(jì)算兩個(gè)“日期”間隔

Duration:用于計(jì)算兩個(gè)“時(shí)間”間隔

import org.junit.Test;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
public class TestPeriodDuration {
    @Test
    public void test01(){
        LocalDate t1 = LocalDate.now();
        LocalDate t2 = LocalDate.of(2018, 12, 31);
        Period between = Period.between(t1, t2);
        System.out.println(between);
        System.out.println("相差的年數(shù):"+between.getYears());
        System.out.println("相差的月數(shù):"+between.getMonths());
        System.out.println("相差的天數(shù):"+between.getDays());
        System.out.println("相差的總數(shù):"+between.toTotalMonths());
    }
    @Test
    public void test02(){
        LocalDateTime t1 = LocalDateTime.now();
        LocalDateTime t2 = LocalDateTime.of(2017, 8, 29, 0, 0, 0, 0);
        Duration between = Duration.between(t1, t2);
        System.out.println(between);
        System.out.println("相差的總天數(shù):"+between.toDays());
        System.out.println("相差的總小時(shí)數(shù):"+between.toHours());
        System.out.println("相差的總分鐘數(shù):"+between.toMinutes());
        System.out.println("相差的總秒數(shù):"+between.getSeconds());
        System.out.println("相差的總毫秒數(shù):"+between.toMillis());
        System.out.println("相差的總納秒數(shù):"+between.toNanos());
        System.out.println("不夠一秒的納秒數(shù):"+between.getNano());
    }
}

4、日期時(shí)間格式化DateTimeFormatter

該類提供了三種格式化方法:

  • 預(yù)定義的標(biāo)準(zhǔn)格式。如:ISO_DATE_TIME;ISO_DATE
  • 本地化相關(guān)的格式。如:ofLocalizedDate(FormatStyle.MEDIUM)、ofLocalizedTime(FormatStyle.MEDIUM)、ofLocalizedDateTime(FormatStyle.MEDIUM)
  • 自定義的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
import org.junit.Test;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
public class TestDatetimeFormatter {
    @Test
    public void test1(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter df = DateTimeFormatter.ISO_DATE_TIME;//2019-06-06T16:38:23.756        String str = df.format(now);
        System.out.println(str);
    }
    
    @Test
    public void test2(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter df1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);//2019年6月6日 下午04時(shí)40分03秒
        DateTimeFormatter df2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);//2019-6-6 16:40:37
        DateTimeFormatter df3 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);//19-6-6 下午4:40
        DateTimeFormatter df4 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withZone(ZoneId.systemDefault());//注意
        
        String str1 = df1.format(now);
        String str2 = df2.format(now);
        String str3 = df3.format(now);
        String str4 = df4.format(now);
        
        System.out.println(str1);
        System.out.println(str2);
        System.out.println(str3);
        System.out.println(str4);
    }
    
    @Test
    public void test3(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy年MM月dd日 aHH點(diǎn)mm分ss秒SSS毫秒 E 是這一年的D天");
        String str = df.format(now);
        System.out.println(str);
    }
    
    @Test
    public void test4(){
        //String ==> LocalDateTime
        DateTimeFormatter dt = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
        String str = "2023年3月27日 下午07時(shí)26分43秒";
        LocalDateTime t = LocalDateTime.from(dt.parse(str));
        System.out.println(t);
    }
}

9.4.4 三代日期時(shí)間的轉(zhuǎn)換

1、第一代與第二代

import org.junit.Test;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class TestDateTimeChange1 {
    @Test
    public void test1(){
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"));
        Date now = calendar.getTime();
        System.out.println(now);
    }
    @Test
    public void test2(){
        Date d = new Date();
        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"));
        c.setTime(d);
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DATE);
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        int second = c.get(Calendar.SECOND);
        System.out.println(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second);
    }
}

2、第一代與第三代

- Date與Instant - Date與LocalDateTime

package com.atguigu.review;
import org.junit.Test;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
public class TestDateTimeChange2 {
    @Test
    public void test1(){
        //Date ==> Instant
        Date d = new Date();
        Instant instant = d.toInstant();
        System.out.println(instant);
    }
    @Test
    public void test2(){
        //Instant ==> Date
        Instant instant = Instant.now();
        Date d = Date.from(instant);
        System.out.println(d);
    }
    @Test
    public void test3(){
        //Date ==> LocalDateTime
        Date d = new Date();
        LocalDateTime t = LocalDateTime.ofInstant(d.toInstant(), ZoneId.systemDefault());
        System.out.println(t);
    }
    
    @Test
    public void test4(){
        LocalDateTime now = LocalDateTime.now();//本地的日期時(shí)間對象
        Instant instant = now.toInstant(ZoneOffset.of("+08:00"));
        Date date = Date.from(instant);//第一代的Date
        System.out.println(date);
    }
    @Test
    public void test5(){
        //LocalDateTime ==> Date
        LocalDateTime now = LocalDateTime.now();//本地的日期時(shí)間對象
        ZonedDateTime zonedDateTime = now.atZone(ZoneId.systemDefault());//時(shí)區(qū)的日期時(shí)間對象
        Instant instant = zonedDateTime.toInstant();//瞬時(shí)對象
        Date date = Date.from(instant);//第一代的Date
        System.out.println(date);
    }
    
    
}