1. 程式人生 > 實用技巧 >JavaEE - 09常用類2

JavaEE - 09常用類2

JavaEE - 09常用類2

(2)JDK8之前的日期時間API

(2.1)java.lang.System類

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

計算世界時間的主要標準有:

  • UTC(Coordinated Universal Time)
  • GMT(Greenwich Mean Time)
  • CST(Central Standard Time)
    @Test
    public void test2(){
        Long t1 = System.currentTimeMillis();
        System.out.println(t1);  
//1606721150824 }

(2.2)java.util.Date類

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

> 構造器

  • Date():使用無參構造器建立的物件可以獲取本地當前時間。
  • Date(long date)

> 常用方法

  • getTime(): 返回自1970年1月1日00:00:00 GMT以來此Date物件表示的毫秒數。
  • toString():把Date物件轉換成以下形式的String:dow mon dd hh:mm:ss zzz yyyy。其中dow指一週中的某天,zzz是時間標準。
  • 其他很多方法都已過時。
    @Test
    public void test1(){
        Date d1 
= new Date(); // 構造器一:Date() System.out.println(d1.toString()); // Mon Nov 30 15:16:18 CST 2020 System.out.println(d1.getTime()); // 1606720578367 Date d2 = new Date(1606720363143L); // 構造器二 System.out.println(d2.toString()); // Mon Nov 30 15:12:43 CST 2020      // java.sql.Date 對應著資料庫中的日期型別的變數,繼承於 java.util.Date
java.sql.Date d3 = new java.sql.Date(1606720363143L); System.out.println(d3); // 2020-11-30 Date d4 = new java.sql.Date(1606720363143L); // 2020-11-30 java.sql.Date d5 = (java.sql.Date) d4; // 2020-11-30 Date d6 = new Date(); java.sql.Date d7 = new java.sql.Date(d6.getTime()); // 2020-11-30 }

(2.3)java.text.SimpleDateFormat類

  • Date類的API不易於國際化,大部分被廢棄,java.text.SimpleDateFormat類是一個與語言環境無關的方式來格式化和解析日期的具體類。
  • 它允許進行 格式化:日期 -> 文字、解析:文字 ->日期

格式化:

  • SimpleDateFormat():預設的模式和語言環境建立物件
  • public SimpleDateFormat(String pattern):該構造方法用引數pattern指定的格式建立一個物件
  • public String format(Date date):該方法格式化時間物件date

解析:

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

    @Test
    public void test1() throws ParseException {
        // 例項化 SimpleDateFormat
        SimpleDateFormat sdf = new SimpleDateFormat();

        // 格式化: 日期 --> 字串
        Date date = new Date();
        System.out.println(date);  //Mon Nov 30 16:04:46 CST 2020
        String format = sdf.format(date);
        System.out.println(format);   //20-11-30 下午4:04
        // 解析: 字串 --> 日期
        String str = "20-10-05 下午3:43";
        Date d1 = sdf.parse(str);
        System.out.println(d1);  //M on Oct 05 15:43:00 CST 2020
    }

    @Test
    public  void test2() throws ParseException {
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date date = new Date();
        String format1 = sdf1.format(date);
        System.out.println(format1);  // 2020-11-30 04:08:37
        Date d2 = sdf1.parse("2019-11-08 13:33:42");
        System.out.println(d2); // Fri Nov 08 13:33:42 CST 2019
    }

    @Test
    public  void test3() throws ParseException {
        String birth = "2020-09-09";
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf1.parse(birth);
        System.out.println(date); // Wed Sep 09 00:00:00 CST 2020
        
        java.sql.Date birthDate = new java.sql.Date(date.getTime());  
        System.out.println(birthDate); //2020-09-09
    }

(2.4)java.util.Calendar(日曆)類

Calendar是一個抽象基類,用於完成日期欄位之間相互操作的功能。 Object -> Calendar -> GregorianCalendar -> BuddhistCalendar

> 獲取Calendar例項的方法

  • 使用Calendar.getInstance()方法
  • 呼叫它的子類GregorianCalendar的構造器

> 一個Calendar的例項是系統時間的抽象表示,通過get(int field)方法來獲取想要的資訊。比如YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY、MINUTE、SECOND。獲取月份時,一月是0,二月是1,...,12月是11;獲取星期時,週日是1,週一是2,...,週六是7

  • public void set(int field, int value)
  • public void add(int field, int amount)
  • public final Date getTime()
  • public final void setTime(Date date)

    @Test
    public void test1(){
        Calendar calendar = Calendar.getInstance();
        System.out.println(calendar.getClass());   // class java.util.GregorianCalendar
        int days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days); // 30
        int days2 = calendar.get(Calendar.DAY_OF_YEAR);
        System.out.println(days2);  //335
        // set()
        calendar.set(Calendar.DAY_OF_MONTH,22);
        days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days);  // 22
        System.out.println(calendar.getTime()); //Sun Nov 22 16:28:50 CST 2020
        // add()
        calendar.add(Calendar.DAY_OF_MONTH,-3);
        days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(calendar.getTime());  //Thu Nov 19 16:32:49 CST 2020
        System.out.println(days);  //19
        // getTime()
        Date date = calendar.getTime();
        System.out.println(date);  //Thu Nov 19 16:32:49 CST 2020
        // setTime()
        Date date1 = new Date();
        calendar.setTime(date1);
        days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days);  //30
    }

(3)JDK8中新日期時間API

JDK1.0中包含了java.util.Date類,但是它大多數方法在JDK1.1引入Calendar類之後被棄用了。

而Calendar並不比Date好多少。面臨的問題有:

  • 可變性:像日期和時間這樣的類應該是不可變的。
  • 偏移性: Date中的年份是從1900開始的,而月份是從0開始。
  • 格式化:格式化只對Date有用,Calendar則不行。
  • 此外,它們也不是執行緒安全的;不能處理閏秒等。

    @Test
    public void test3(){
        Date d1 = new Date(2020,9,10);
        System.out.println(d1);  // Sun Oct 10 00:00:00 CST 3920
        Date d2 = new Date(2020 - 1900,9,10);  // year 為偏移量
        System.out.println(d2);  // Sun Oct 10 00:00:00 CST 2020
    }

Java8 吸收了Joda-Time的精華,引入了java.time API,糾正了過去的缺陷。

java.time中包括了本地日期(LocalDate)、本地時間(LocalTime)、本地日期時間(LocalDateTime)、時區(ZonedDateTime)和持續時間(Duration)的類。Date類新增了toInstant()方法,用於把Date轉換成新的表示形式。

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

(3.1)LocalDate、LocalTime、LocalDateTime

它們的例項是不可變的物件,分別表示使用ISO-8601日曆系統(公曆)的日期、時間、日期和時間。它們提供了簡單的本地日期或時間,但並不包含當前的時間資訊,也不包含與時區相關的資訊。

  • LocalDate代表ISO格式(yyyy-MM-dd)的日期,可以儲存生日、紀念日等日期
  • LocalTime代表一個時間,而不是日期。
  • LocalDateTime表示時間和日期的。
方法 描述
now() / now(ZoneId zone) 靜態方法,根據當前時間建立物件/指定時區的物件
of() 靜態方法,根據指定日期/時間建立物件
getDayOfMonth() / getDayOfYear() 獲取月份天數(1-31)/獲得年份天數(1-366)
getDayOfWeek() 獲取星期幾(返回一個DayOfWeek列舉值)
getMonth() 獲取月份,返回一個Month列舉值
getMonthValue() / getYear() 獲取月份(1-12)/獲取年份
getHour()/getMinute()/getSecond() 獲得當前物件對應的小時、分鐘、秒
withDayOfMonth() / withDayOfYear() / withMonth() / withYear() 將月份天數、年份天數、月份、年份修改為指定的值並返回新的物件
plusDays() / plusWeeks() /plusMonths() / plusYears() / plusHours() 向當前物件新增幾天、幾周、幾個月、幾年、幾小時
minusDays() / minusWeeks() /minusMonths() / minusYears() / minusHours() 從當前物件減去幾天、幾周、幾個月、幾年、幾小時

    @Test
    public void test1(){
        LocalDate localDate = LocalDate.now();
        LocalTime localTime = LocalTime.now();
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDate);  //2020-11-30
        System.out.println(localTime);  //17:06:40.418
        System.out.println(localDateTime); //2020-11-30T17:06:40.418

        LocalDateTime ldt = LocalDateTime.of(2020,12,12,14,23,44);
        System.out.println(ldt);   //2020-12-12T14:23:44
        System.out.println(localDateTime.getDayOfYear());  //335
        System.out.println(localDateTime.getDayOfMonth()); //30
        System.out.println(localDateTime.getDayOfWeek());  //MONDAY
        System.out.println(localDateTime.getMonth());      //NOVEMBER
        System.out.println(localDateTime.getMonthValue()); //11
        System.out.println(localDateTime.getYear());       //2020
        // 體現不可變性
        LocalDate localDate1 = localDate.withDayOfMonth(22);
        System.out.println(localDate);   //2020-11-30
        System.out.println(localDate1);  //2020-11-22

        LocalDateTime ldt3 = localDateTime.plusMonths(3);
        System.out.println(localDateTime); //2020-11-30T17:09:57.045
        System.out.println(ldt3);          //2021-02-28T17:09:57.045

        LocalDateTime ldt4 = localDateTime.minusDays(7);
        System.out.println(localDateTime); //2020-11-30T17:09:57.045
        System.out.println(ldt4);          //2020-11-23T17:09:57.045
    }

(3.2)瞬時: Instant

  • Instant:時間線上的一個瞬時點。可以被用來記錄應用程式中的事件時間戳。
  • 處理時間和日期時,年月日時分秒是面向人類的時間模型,通用模型是面向機器的。在UNIX中,從1970年開始,以秒為單位,Java中以毫秒為單位。
  • java.time包通過值型別Instant提供機器檢視。不需要任何上下文資訊,如時區。表示從1970年1月1日00:00:00開始的秒數。精度可以達到納秒級。
  • 1秒 = 1000毫秒 = 10^6毫秒 = 10^9納秒

方法 描述
now() 靜態方法,返回預設UTC時區的Instant類的物件
ofEpochMilli(long epochMilli) 靜態方法,返回在1970-01-01 00:00:00基礎上加上指定毫秒數之後的Instant類的物件
atOffSet(ZoneOffset offset) 結合即時的偏移來建立一個 OffsetDateTime
toEpochMilli() 返回1970-01-01 00:00:00到當前時間的毫秒數,即為時間戳

時間戳是指格林威治時間1970-01-01 00:00:00(北京時間1970-01-01 08:00:00)起至現在的總秒數。

    @Test
    public void  test2(){
        Instant instant = Instant.now();
        System.out.println(instant);  // 2020-11-30T09:26:13.897Z
        System.out.println(System.currentTimeMillis()); //1606728374034
        // 新增時間的偏移量
        OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
        System.out.println(offsetDateTime); //2020-11-30T17:28:50.039+08:00
        // 獲取自1970-01-01 00:00:00(UTC)開始的毫秒數
        long milli = instant.toEpochMilli();
        System.out.println(milli); //1606728530039
        // 通過給定的毫秒數,獲取Instant物件
        Instant instant1 = Instant.ofEpochMilli(1606728374034L);
        System.out.println(instant1);  // 2020-11-30T09:26:14.034Z
    }

(3.3)格式化與解析日期、時間

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

  • 預定義的標準格式。如:ISO_LOCAL_DATE_TIME; ISO_LOCAL_DATE; ISO_LOCAL_TIME。
  • 本地化相關的格式。如:ofLocalizedDateTime(FormatStyle.LONG/MEDIUM/SHORT)、ofLocalizedDate(FormatStyle.FULL/LONG/MEDIUM/SHORT)
  • 自定義的格式。如:ofPattern("yyyy-MM-dd hh:mm:ss E")
方法 描述
ofPattern(String pattern) 靜態方法,返回一個指定字串格式的DateTimeFormatter
format(TemporalAccessor t) 格式化一個日期、時間,返回字串
parse(Charequence text) 將指定格式的字元序列解析為一個日期、時間

    @Test
    public void test3(){
        DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;  // 預定義的標準格式。
        LocalDateTime ldt = LocalDateTime.now();
        String str = formatter.format(ldt);  
        System.out.println(ldt);  //2020-11-30T17:39:31.719
        System.out.println(str);  //2020-11-30T17:39:31.719
        // 解析: 字串 --> 日期
        TemporalAccessor parse = formatter.parse("2020-02-18T17:40:12.897");
        System.out.println(parse);  //{},ISO resolved to 2020-02-18T17:40:12.897
        // 本地化格式 
        DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
        String str2 = formatter2.format(LocalDate.now());
        System.out.println(str2);  //2020年11月30日 星期一
        // 自定義格式 ofPattern
        DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String str3 = formatter3.format(LocalDateTime.now());
        System.out.println(str3);  //2020-11-30 17:46:20

        TemporalAccessor accessor = formatter3.parse("2020-09-08 17:09:07");
        System.out.println(accessor); //{},ISO resolved to 2020-09-08T17:09:07
    }

(3.4)其他API

  • ZoneId: 該類中包含了所有的時區資訊,一個時區的ID,如Europe/Paris
  • ZonedDateTime:一個在ISO-8601日曆系統時區的日期時間,如 2007-12-12T10:09:08+01:00 Europe/Paris。
    • 其中每個時區都對應著ID,地區ID都為"{區域}/{城市}"的格式,如:Asia/Shanghai等
  • Clock:使用時區提供對當前即時、日期和時間的訪問的時鐘。
  • Duration:持續時間,用於計算兩個"時間"間隔。
  • Period:日期間隔,用於計算兩個"日期"間隔。
  • TemporalAdjuster:時間校正器。如:將日期調整到"下一個工作日"等操作。
  • TemporalAdjusters:該類通過靜態方法firstDayOfXxx()/lastDayOfXxx()/nextXxx()提供了常用TemporalAdjuster的實現。

(3.5)參考:與傳統日期處理的轉換

To遺留類 From遺留類
java.time.Instant與java.util.Date Date.from(instant) date.toInstant()
java.time.Instant 與java.sql.Timestamp Timestamp.from(instant) timestamp.toInstant()
java.time.ZonedDateTime與java.util.GregorianCalendar GregorianCalendar.from(zonedDateTime) cal.toZonedDateTime()
java.time.LocalDate與java.sql.Time Date.valueOf(localDate) date.toLocalDate()
java.time.LocalTime與java.sql.Time Date.valueOf(localDate) date.toLocalTime()
java.time.LocalDateTime與java.sql.Timestamp Timestamp.valueOf(localDateTime) timestamp.toLocalDateTime()
java.time.ZoneId與java.util.TimeZone Timezone.getTimeZone(id) timeZone.toZoneId()
java.time.format.DateTimeFormatter與java.text.DateFormat formatter.toFormat()

時間

獲取自 1970年 1月1日 00時 00分 00秒 到 當前的毫秒數

java.lang.System
long now = System.currentTimeMillis();


【獲取當前時間】
java.util.Date
構造方法:
Date()
Date(long)

Date nowTime = new Date(); //Tue Jul 31 16:01:03 CST 2018

說明Date 已經重寫了 toString 方法。

【引入格式化日期】
java.util.Date --> String

y 年 M 月 d 日 H 小時 m 分鐘 s 秒 S 毫秒
java.text.SimpleDateFormat

// 建立日期格式化物件
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");

// 開始格式化(Date --> String)
String strTime = sdf.format(nowTime);

【獲取特定的日期】

String strTime = "2008年08月08日 08:08:08 888"
// 將字串轉化為日期

SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS"); //與字串格式相同

// 報錯 throws Exception
Date dateTime = sdf.parse(strTime); //Fri Aug 08 08:08:08 CST 2008

【獲取當前時間的前10分鐘的時間】
Date d = new Date(1000); //自 1970年 1月 1日 開始的毫秒數。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");

System.out.println(sdf.format(d));


-----

Date t2 = new Date(System.currentTimeMillis() - 10 * 60 * 1000);

sdf.format(t2);

【 日曆 Calendar 】
java.util.Calendar
// 獲取系統當前的日曆
Calendar c = Calendar.getInstance();

// get 返回 Integer
int i = c.get(Calendar.DAY_OF_WEEK);

int m = c.get(Calendar.DAY_OF_MONTH);


// 獲取 2008年8月8日 是 星期幾


String strTime = "2008,08,08";
Date d = new SimpleDateFormat("yyyy,MM,dd").parse(strTime);
c.setTime(d);
c.get(Calendar.DAY_OF_WEEK);