文章目錄
Java 原本提供了 Date 和 Calendar 用于處理日期、時間的類,包括建立日期 、 時間對象,擷取系統目前日期、時間等操作 。 但 Date 不僅無法實作國際化 ,而且它對不同屬性也使用了前後沖突的偏移量 ,比如月份與小時都是從 0 開始的,月份中的天數則是從 1 開始的,年又是從 1900 開始的,而java.util.Calendar 則顯得過于複雜 ,從下面介紹中會看到傳統 Java 對日期、時間處理的不足 。 Java 8 吸取了 Joda-Time 庫( 一個被廣泛使用的日期、 時間庫)的經驗 , 提供了一套全新的日期時間庫 。
在計算機中隻需要存儲一個整數表示某一時刻。當需要顯示為某一地區的當地時間時,就把它格式化為一個字元串
- Date(): 生成一個代表目前日期時間的 Date 對象 。 該構造器在底層調用 System .currentTimeMillis()獲得 long 整數作為日期參數。
- Date(long date): 根據指定的 long 型整數來生成一個 Date 對象 。該構造器的參數表示建立的 Date對象和 GMT 1970 年 1 月 1 日 00:00:00 之間的時間差 ,以毫秒作為計時機關 。與 Date 構造器相同的是, Date 對象的大部分方法也 Deprecated 了, 剩下為數不多的幾個方法。
- boolean after(Date when): 測試該日期是否在指定日期 when 之後 。
- boolean before(Date when): 測試該日期是否在指定日期 when 之前 。
-
long getTime(): 傳回該時間對應的 long 型整數 ,即從 GMT 1970-01-0100:00:00 到該 Date 對象
之間的時間差,以毫秒作為計時機關。
- void setTime(long time): 設定該 Date 對象的時間。
下面程式示範了 Date 類的用法 :
DateTest.java
public class DateTest
{
public static void main(String[] args)
{
Date d1 = new Date();
// 擷取目前時間之後100ms的時間
Date d2 = new Date(System.currentTimeMillis() + 100);
System.out.println(d2);
System.out.println(d1.compareTo(d2));
System.out.println(d1.before(d2));
//自定義輸出時間日期
// 擷取目前時間:
Date d3 = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(d3));
}
}
Date對象有幾個嚴重的問題:它不能轉換時區,除了toGMTString()可以按GMT+0:00輸出外,Date總是以目前計算機系統的預設時區為基礎進行輸出。此外,我們也很難對日期和時間進行加減,計算兩個日期相差多少天,計算某個月第一個星期一的日期等。
API: java.util.Date
因為 Date 類在設計上存在一些缺陷,是以 Java 提供了 Calendar 類來更好地處理日期和時間 。
Calendar 類本身是一個抽象類,它是所有月曆類的模闆,并提供了一些所有月曆通用的方法 。
它本身不能直接執行個體化,程式隻能建立 Calendar 子類的執行個體, Java 本身提供了 一個 GregorianCalendar 類,一個代表格裡高利月曆的子類,它代表了通常所說的公曆 。
當然,也可以建立自己的 Calendar 子類,然後将它作為 Calendar 對象使用。
Calendar 類是一個抽象類,是以不能使用構造器來建立 Calendar 對象 。 但它提供了幾個靜态getInstance()方法來擷取 Calendar 對象。
Calendar 與 Date 都是表示日期的工具類,它們 直接可以自由轉換,如下代碼所示 :
// 建立一個預設的 Calendar 對象
Calendar calendar = Calendar.getlnstance();
// 從 Calendar 對象中取出 Date 對象
Date date = calendar .getTime();
// 通過 Date 對象獲得對應的 Calendar 對象
// 因為 Calendar / GregorianCalendar 沒有構造函數可以接收 Date 對象
// 是以必須先獲得一個 C alendar 執行個體,然後調用其 setTime () 方法
Calendar calendar2 = Calendar . getInstance();
calendar2.setTime(date);
Calendar 類提供了大量通路、修改日期時間的方法,常用 方法如下 。
- void add(int field, int amount): 根據月曆的規則,為給定的月曆宇段添加或減去指定的時間量 。
- int get(int field): 傳回指定月曆宇段的值 。
- int getActualMaximum(int field): 傳回指定月曆字段可能擁有的最大值 。 例如月,最大值為 11 。
- int getActualMinimum(int field): 傳回指定月曆字段可能擁有的最小值 。 例如月,最小值為 0 。
-
void roll(int field, int amount): 與 addO方法類似,差別在于加上 amount 後超過了該字段所能表
示的最大範圍時,也不會向上一個字段進位 。
- void set(int field, int value): 将給定的月曆宇段設定為給定值 。
- void set(int year, int month, int date): 設定 Calendar 對象的年、月、日 三個字段的值 。
- void set(int year, int month, int date, int hourOfDa弘 int minute, int second): 設定 Calendar 對象的年、月、日、時、分、秒 6 個字段的值 。
上面的很多方法都需要一個 int 類型的 field 參數, field 是 Calendar 類的類變量 :
類變量 | 描述 |
Calendar.YEAR | 年份 |
Calendar.MONTH | 月份 |
Calendar.DATE | 日期 |
Calendar.DAY_OF_MONTH | 日期,和上面的字段意義完全相同 |
Calendar.HOUR | 12小時制的小時 |
Calendar.HOUR_OF_DAY | 24小時制的小時 |
Calendar.MINUTE | 分鐘 |
Calendar.SECOND | 秒 |
Calendar.DAY_OF_WEEK | 星期幾 |
CalendarTest.java
public class CalendarTest
{
public static void main(String[] args)
{
Calendar c = Calendar.getInstance();
// 取出年
System.out.println(c.get(YEAR));
// 取出月份
System.out.println(c.get(MONTH));
// 取出日
System.out.println(c.get(DATE));
// 分别設定年、月、日、小時、分鐘、秒
c.set(2003 , 10 , 23 , 12, 32, 23); //2003-11-23 12:32:23
System.out.println(c.getTime());
// 将Calendar的年前推1年
c.add(YEAR , -1); //2002-11-23 12:32:23
System.out.println(c.getTime());
// 将Calendar的月前推8個月
c.roll(MONTH , -8); //2002-03-23 12:32:23
System.out.println(c.getTime());
Calendar cal1 = Calendar.getInstance();
cal1.set(2003, 7, 23, 0, 0 , 0); // 2003-8-23
cal1.add(MONTH, 6); //2003-8-23 => 2004-2-23
System.out.println(cal1.getTime());
Calendar cal2 = Calendar.getInstance();
cal2.set(2003, 7, 31, 0, 0 , 0); // 2003-8-31
// 因為進位到後月份改為2月,2月沒有31日,自動變成29日
cal2.add(MONTH, 6); // 2003-8-31 => 2004-2-29
System.out.println(cal2.getTime());
Calendar cal3 = Calendar.getInstance();
cal3.set(2003, 7, 23, 0, 0 , 0); //2003-8-23
// MONTH字段“進位”,但YEAR字段并不增加
cal3.roll(MONTH, 6); //2003-8-23 => 2003-2-23
System.out.println(cal3.getTime());
Calendar cal4 = Calendar.getInstance();
cal4.set(2003, 7, 31, 0, 0 , 0); //2003-8-31
// MONTH字段“進位”後變成2,2月沒有31日,
// YEAR字段不會改變,2003年2月隻有28天
cal4.roll(MONTH, 6); //2003-8-31 => 2003-2-28
System.out.println(cal4.getTime());
}
}
java.util.Calnedar java.util.GregorianCalendar
Java 8 開始專 門新增了 一個 java.time 包, 該包下包含了 如下常用的類 :
-
Clock: 該類用于擷取指定時區的目前 日期、時間 。 該類可取代 System 類的 currentTimeMillis()方法,而且提供了更多方法來擷取目前日期、時間 。 該類提供了大量靜态方法來擷取 Clock 對
象 。
- Duration: 該類代表持續時間 。 該類可 以非常友善地擷取一段時間 。
- Instant: 代表一個具體的時刻,可以精确到納秒 。 該類提供了靜态 的 now()方法來擷取目前時刻,也提供了 靜态的 now(Clock clock)方法來擷取 clock 對應的時刻 。 除此之外, 它還提供了 一系列minusXxx()方法在目前時刻基礎上減去一段時間 , 也提供了 plusXxx()方法在目前時刻基礎上加上一段時 間 。
- LocalDate: 該類代表不帶時區的日期 ,例如 2007-12-03 。 該類提供了靜态的 now()方法來擷取目前日期,也提供了靜态的 now(Clock clock)方法來擷取 clock 對應的日期 。 除此之外 , 它還提供了 rninusXxxO方法在目前年份基礎上減去幾年、幾月、幾周或幾日等,也提供了 plusXxx()方法在目前年份基礎上加上幾年、幾月、幾周或幾日等 。
-
LocalTime: 該類代表不帶時 區的 時間,例如 10:15 : 30 。 該類提供了靜态的 now()方法來擷取當
前時間,也提供了靜态的 now(Clock clock)方法來擷取 clock 對應的時間 。 除此之外,它還提供
了 rninusXxx()方法在目前年份基礎上減去幾小時、幾分、幾秒等,也提供了plusXxx()方法在目前年份基礎上加上幾小時、幾分、 幾秒等。
- LocalDateTime: 該類代表不帶時區的日期 、時間, 例如 2007-12-03Tl 0: 15 :3 0 。 該類提供了靜态的 now()方法來擷取目前日期、 時間,也提供 了靜态的 now(Clock clock)方法來擷取 clock 對應的日期、時間 。 除此之外,它還提供了 minusXxx()方法在目前年份基礎上減去幾年 、幾月 、幾日、幾小時、幾分、 幾秒等, 也提供 了 plusXxxO方法在目前年份基礎上加上幾年、幾月 、幾日、幾小時、幾分 、 幾秒等 。
- MonthDay: 該類僅代表月日 ,例如一04-12 。 該類提供了靜态 的 nowO方法來擷取目前月日 ,也提供了靜态的 now(Clock clock)方法來擷取 clock 對應的月日 。
- Year: 該類僅代表年,例如 2014 。 該類提供了靜态的 now()方法來擷取目前年份 ,也提供了靜态的 now(Clock clock)方法來擷取 clock 對應的年份 。 除此之外,它還提供了 rninusYears()方法在目前年份基礎上減去幾年 ,也提供了 plusYearsO方法在目前年份基礎上加上幾年 。
- YearMonth: 該類僅代表年月 ,例如 2014-04 。 該類提供了靜态的 nowO方法來擷取目前年月,也提供了靜态的 now(Clock clock)方 法來擷取 clock 對 應的年月 。 除此之外 ,它還提供了rninusXxx()方法在目前年月基礎上減去幾年 、幾月 ,也提供了 plusXxx()方法在目前年月基礎上加上幾年、幾月 。
- ZonedDateTime: 該類代表一個時區化的日期 、時間 。
- Zoneld: 該類代表一個時區 。
- DayOtweek: 這是一個枚舉類,定義了周日到周六的枚舉值 。
-
Month: 這也是一個枚舉類,定義了 一月到十二月的枚舉值 。
NewDatePackageTest.java
public class NewDatePackageTest
{
public static void main(String[] args)
{
// -----下面是關于Clock的用法-----
// 擷取目前Clock
Clock clock = Clock.systemUTC();
// 通過Clock擷取目前時刻
System.out.println("目前時刻為:" + clock.instant());
// 擷取clock對應的毫秒數,與System.currentTimeMillis()輸出相同
System.out.println(clock.millis());
System.out.println(System.currentTimeMillis());
// -----下面是關于Duration的用法-----
Duration d = Duration.ofSeconds(6000);
System.out.println("6000秒相當于" + d.toMinutes() + "分");
System.out.println("6000秒相當于" + d.toHours() + "小時");
System.out.println("6000秒相當于" + d.toDays() + "天");
// 在clock基礎上增加6000秒,傳回新的Clock
Clock clock2 = Clock.offset(clock, d);
// 可看到clock2與clock1相差1小時40分
System.out.println("目前時刻加6000秒為:" +clock2.instant());
// -----下面是關于Instant的用法-----
// 擷取目前時間
Instant instant = Instant.now();
System.out.println(instant);
// instant添加6000秒(即100分鐘),傳回新的Instant
Instant instant2 = instant.plusSeconds(6000);
System.out.println(instant2);
// 根據字元串中解析Instant對象
Instant instant3 = Instant.parse("2014-02-23T10:12:35.342Z");
System.out.println(instant3);
// 在instant3的基礎上添加5小時4分鐘
Instant instant4 = instant3.plus(Duration
.ofHours(5).plusMinutes(4));
System.out.println(instant4);
// 擷取instant4的5天以前的時刻
Instant instant5 = instant4.minus(Duration.ofDays(5));
System.out.println(instant5);
// -----下面是關于LocalDate的用法-----
LocalDate localDate = LocalDate.now();
System.out.println(localDate);
// 獲得2014年的第146天
localDate = LocalDate.ofYearDay(2014, 146);
System.out.println(localDate); // 2014-05-26
// 設定為2014年5月21日
localDate = LocalDate.of(2014, Month.MAY, 21);
System.out.println(localDate); // 2014-05-21
// -----下面是關于LocalTime的用法-----
// 擷取目前時間
LocalTime localTime = LocalTime.now();
// 設定為22點33分
localTime = LocalTime.of(22, 33);
System.out.println(localTime); // 22:33
// 傳回一天中的第5503秒
localTime = LocalTime.ofSecondOfDay(5503);
System.out.println(localTime); // 01:31:43
// -----下面是關于localDateTime的用法-----
// 擷取目前日期、時間
LocalDateTime localDateTime = LocalDateTime.now();
// 目前日期、時間加上25小時3分鐘
LocalDateTime future = localDateTime.plusHours(25).plusMinutes(3);
System.out.println("目前日期、時間的25小時3分之後:" + future);
// 下面是關于Year、YearMonth、MonthDay的用法示例-----
Year year = Year.now(); // 擷取目前的年份
System.out.println("目前年份:" + year); // 輸出目前年份
year = year.plusYears(5); // 目前年份再加5年
System.out.println("目前年份再過5年:" + year);
// 根據指定月份擷取YearMonth
YearMonth ym = year.atMonth(10);
System.out.println("year年10月:" + ym); // 輸出XXXX-10,XXXX代表目前年份
// 目前年月再加5年,減3個月
ym = ym.plusYears(5).minusMonths(3);
System.out.println("year年10月再加5年、減3個月:" + ym);
MonthDay md = MonthDay.now();
System.out.println("目前月日:" + md); // 輸出--XX-XX,代表幾月幾日
// 設定為5月23日
MonthDay md2 = md.with(Month.MAY).withDayOfMonth(23);
System.out.println("5月23日為:" + md2); // 輸出--05-23
}
}
java.time
Java Review系列目錄 ⇐⇐Java Review (二十、基礎類庫----常用類:Object、String、StringBuffer、StringBuilder、Math) Java Review (二十二、正規表達式)⇒⇒ |
參考:
【1】:《瘋狂Java講義》
【2】:
Date和Calendar【3】:
Java 日期時間【4】:
LocalDateTime詳解【5】:
ZonedDateTime詳解【6】:
DateTimeFormatter詳解【7】:
Java日期時間新舊API轉換、在資料庫中存儲日期和時間