# Java 日期時間
java.util包提供了Date類來封裝當前的日期和時間。 Date類提供兩個構造函數來實例化Date對象。
第一個構造函數使用當前日期和時間來初始化對象。
```
Date( )
```
第二個構造函數接收一個參數,該參數是從1970年1月1日起的微秒數。
```
Date(long millisec)
```
Date對象創建以后,可以調用下面的方法。
| 方法 | 描述 |
| --- | --- |
| **boolean after(Date date)** | 若當調用此方法的Date對象在指定日期之后返回true,否則返回false。 |
| **boolean before(Date date)** | 若當調用此方法的Date對象在指定日期之前返回true,否則返回false。 |
| **Object clone( )** | 返回此對象的副本。 |
| **int compareTo(Date date)** | 比較當調用此方法的Date對象和指定日期。兩者相等時候返回0。調用對象在指定日期之前則返回負數。調用對象在指定日期之后則返回正數。 |
| **int compareTo(Object obj)** | 若obj是Date類型則操作等同于compareTo(Date) 。否則它拋出ClassCastException。 |
| **boolean equals(Object date)** | 當調用此方法的Date對象和指定日期相等時候返回true,否則返回false。 |
| **long getTime( )** | 返回自 1970 年 1 月 1 日 00:00:00 GMT 以來此 Date 對象表示的毫秒數。 |
| **int hashCode( )** | ?返回此對象的哈希碼值。 |
| **void setTime(long time)** | 用自1970年1月1日00:00:00 GMT以后time毫秒數設置時間和日期。 |
| **String toString( )** | 轉換Date對象為String表示形式,并返回該字符串。 |
## 獲取當前日期時間
Java中獲取當前日期和時間很簡單,使用Date對象的 toString()方法來打印當前日期和時間,如下所示:
```
import java.util.Date;
public class DateDemo {
public static void main(String args[]) {
// 初始化 Date 對象
Date date = new Date();
// 使用 toString() 函數顯示日期時間
System.out.println(date.toString());
}
}
```
以上實例編譯運行結果如下:
```
Mon May 04 09:51:52 CDT 2013
```
## 日期比較
Java使用以下三種方法來比較兩個日期:
* 使用getTime( ) 方法獲取兩個日期(自1970年1月1日經歷的微妙數值),然后比較這兩個值。
* 使用方法before(),after()和equals()。例如,一個月的12號比18號早,則new Date(99, 2, 12).before(new Date (99, 2, 18))返回true。
* 使用compareTo()方法,它是由Comparable接口定義的,Date類實現了這個接口。
## 使用SimpleDateFormat格式化日期
SimpleDateFormat是一個以語言環境敏感的方式來格式化和分析日期的類。SimpleDateFormat允許你選擇任何用戶自定義日期時間格式來運行。例如:
```
import java.util.*;
import java.text.*;
public class DateDemo {
public static void main(String args[]) {
Date dNow = new Date( );
SimpleDateFormat ft =
new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
System.out.println("Current Date: " + ft.format(dNow));
}
}
```
以上實例編譯運行結果如下:
```
Current Date: Sun 2004.07.18 at 04:14:09 PM PDT
```
## 簡單的DateFormat格式化編碼
時間模式字符串用來指定時間格式。在此模式中,所有的ASCII字母被保留為模式字母,定義如下:
| **字母** | **描述** | **示例** |
| --- | --- | --- |
| G | 紀元標記 | AD |
| y | 四位年份 | 2001 |
| M | 月份 | July or 07 |
| d | 一個月的日期 | 10 |
| h | ?A.M./P.M. (1~12)格式小時 | 12 |
| H | 一天中的小時 (0~23) | 22 |
| m | 分鐘數 | 30 |
| s | 秒數 | 55 |
| S | 微妙數 | 234 |
| E | 星期幾 | Tuesday |
| D | 一年中的日子 | 360 |
| F | 一個月中第幾周的周幾 | 2 (second Wed. in July) |
| w | 一年中第幾周 | 40 |
| W | 一個月中第幾周 | 1 |
| a | A.M./P.M. 標記 | PM |
| k | 一天中的小時(1~24) | 24 |
| K | ?A.M./P.M. (0~11)格式小時 | 10 |
| z | 時區 | Eastern Standard Time |
| ' | 文字定界符 | Delimiter |
| " | 單引號 | ` |
## 使用printf格式化日期
printf方法可以很輕松地格式化時間和日期。使用兩個字母格式,它以t開頭并且以下面表格中的一個字母結尾。例如:
```
import java.util.Date;
public class DateDemo {
public static void main(String args[]) {
// 初始化 Date 對象
Date date = new Date();
// 使用toString()顯示日期和時間
String str = String.format("Current Date/Time : %tc", date );
System.out.printf(str);
}
}
```
以上實例編譯運行結果如下:
```
Current Date/Time : Sat Dec 15 16:37:57 MST 2012
```
如果你需要重復提供日期,那么利用這種方式來格式化它的每一部分就有點復雜了。因此,可以利用一個格式化字符串指出要被格式化的參數的索引。
索引必須緊跟在%后面,而且必須以$結束。例如:
```
import java.util.Date;
public class DateDemo {
public static void main(String args[]) {
// 初始化 Date 對象
Date date = new Date();
// 使用toString()顯示日期和時間
System.out.printf("%1$s %2$tB %2$td, %2$tY",
"Due date:", date);
}
}
```
以上實例編譯運行結果如下:
```
Due date: February 09, 2004
```
或者,你可以使用<標志。它表明先前被格式化的參數要被再次使用。例如:
```
import java.util.Date;
public class DateDemo {
public static void main(String args[]) {
// 初始化 Date 對象
Date date = new Date();
// 顯示格式化時間
System.out.printf("%s %tB %<te, %<tY",
"Due date:", date);
}
}
```
以上實例編譯運行結果如下:
```
Due date: February 09, 2004
```
## 日期和時間轉換字符
| **字符** | **描述** | **例子** |
| --- | --- | --- |
| c | 完整的日期和時間 | Mon May 04 09:51:52 CDT 2009 |
| F | ISO 8601 格式日期 | 2004-02-09 |
| D | U.S. 格式日期 (月/日/年) | 02/09/2004 |
| T | 24小時時間 | 18:05:19 |
| r | 12小時時間 | 06:05:19 pm |
| R | 24小時時間,不包含秒 | 18:05 |
| Y | 4位年份(包含前導0) | 2004 |
| y | 年份后2位(包含前導0) | 04 |
| C | 年份前2位(包含前導0) | 20 |
| B | 月份全稱 | February |
| b | 月份簡稱 | Feb |
| n | 2位月份(包含前導0) | 02 |
| d | 2位日子(包含前導0) | 03 |
| e | 2位日子(不包含前導0) | 9 |
| A | 星期全稱 | Monday |
| a | 星期簡稱 | Mon |
| j | 3位年份(包含前導0) | 069 |
| H | 2位小時(包含前導0), 00 到 23 | 18 |
| k | 2位小時(不包含前導0), ?0 到 23 | 18 |
| I | 2位小時(包含前導0), 01 到 12 | 06 |
| l | 2位小時(不包含前導0), ?1 到 12 | 6 |
| M | 2位分鐘(包含前導0) | 05 |
| S | 2位秒數(包含前導0) | 19 |
| L | 3位毫秒(包含前導0) | 047 |
| N | 9位納秒(包含前導0) | 047000000 |
| P | 大寫上下午標志 | PM |
| p | 小寫上下午標志 | pm |
| z | 從GMT的RFC 822數字偏移 | -0800 |
| Z | 時區 | PST |
| s | 自 1970-01-01 00:00:00 GMT的秒數 | 1078884319 |
| Q | 自 1970-01-01 00:00:00 GMT的毫妙 | 1078884319047 |
還有其他有用的日期和時間相關的類。對于更多的細節,你可以參考到Java標準文檔。
## 解析字符串為時間
SimpleDateFormat 類有一些附加的方法,特別是parse(),它試圖按照給定的SimpleDateFormat 對象的格式化存儲來解析字符串。例如:
```
import java.util.*;
import java.text.*;
public class DateDemo {
public static void main(String args[]) {
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd");
String input = args.length == 0 ? "1818-11-11" : args[0];
System.out.print(input + " Parses as ");
Date t;
try {
t = ft.parse(input);
System.out.println(t);
} catch (ParseException e) {
System.out.println("Unparseable using " + ft);
}
}
}
```
以上實例編譯運行結果如下:
```
$ java DateDemo
1818-11-11 Parses as Wed Nov 11 00:00:00 GMT 1818
$ java DateDemo 2007-12-01
2007-12-01 Parses as Sat Dec 01 00:00:00 GMT 2007
```
Java 休眠(sleep)
你可以讓程序休眠一毫秒的時間或者到您的計算機的壽命長的任意段時間。例如,下面的程序會休眠10秒:
```
import java.util.*;
public class SleepDemo {
public static void main(String args[]) {
try {
System.out.println(new Date( ) + "\n");
Thread.sleep(5*60*10);
System.out.println(new Date( ) + "\n");
} catch (Exception e) {
System.out.println("Got an exception!");
}
}
}
```
以上實例編譯運行結果如下:
```
Sun May 03 18:04:41 GMT 2009
Sun May 03 18:04:51 GMT 2009
```
## 測量時間
下面的一個例子表明如何測量時間間隔(以毫秒為單位):
```
import java.util.*;
public class DiffDemo {
public static void main(String args[]) {
try {
long start = System.currentTimeMillis( );
System.out.println(new Date( ) + "\n");
Thread.sleep(5*60*10);
System.out.println(new Date( ) + "\n");
long end = System.currentTimeMillis( );
long diff = end - start;
System.out.println("Difference is : " + diff);
} catch (Exception e) {
System.out.println("Got an exception!");
}
}
}
```
以上實例編譯運行結果如下:
```
Sun May 03 18:16:51 GMT 2009
Sun May 03 18:16:57 GMT 2009
Difference is : 5993
```
## Calendar類
我們現在已經能夠格式化并創建一個日期對象了,但是我們如何才能設置和獲取日期數據的特定部分呢,比如說小時,日,或者分鐘? 我們又如何在日期的這些部分加上或者減去值呢? 答案是使用Calendar 類。
Calendar類的功能要比Date類強大很多,而且在實現方式上也比Date類要復雜一些。
Calendar類是一個抽象類,在實際使用時實現特定的子類的對象,創建對象的過程對程序員來說是透明的,只需要使用getInstance方法創建即可。
### 創建一個代表系統當前日期的Calendar對象
```
Calendar c = Calendar.getInstance();//默認是當前日期
```
### 創建一個指定日期的Calendar對象
使用Calendar類代表特定的時間,需要首先創建一個Calendar的對象,然后再設定該對象中的年月日參數來完成。
```
//創建一個代表2009年6月12日的Calendar對象
Calendar c1 = Calendar.getInstance();
c1.set(2009, 6 - 1, 12);
```
### Calendar類對象字段類型
Calendar類中用一下這些常量表示不同的意義,jdk內的很多類其實都是采用的這種思想
| 常量 | 描述 |
| --- | --- |
| 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 | 星期幾 |
### Calendar類對象信息的設置
**Set設置**
如:
```
Calendar c1 = Calendar.getInstance();
```
調用:
```
public final void set(int year,int month,int date)
```
```
c1.set(2009, 6 - 1, 12);//把Calendar對象c1的年月日分別設這為:2009、6、12
```
利用字段類型設置
如果只設定某個字段,例如日期的值,則可以使用如下set方法:
```
public void set(int field,int value)
```
把 c1對象代表的日期設置為10號,其它所有的數值會被重新計算
```
c1.set(Calendar.DATE,10);
```
把c1對象代表的年份設置為2008年,其他的所有數值會被重新計算
```
c1.set(Calendar.YEAR,2008);
```
其他字段屬性set的意義以此類推
**Add設置**
```
Calendar c1 = Calendar.getInstance();
```
把c1對象的日期加上10,也就是c1所表的日期的10天后的日期,其它所有的數值會被重新計算
```
c1.add(Calendar.DATE, 10);
```
把c1對象的日期加上10,也就是c1所表的日期的10天前的日期,其它所有的數值會被重新計算
```
<pre>c1.add(Calendar.DATE, -10);
```
其他字段屬性的add的意義以此類推
### Calendar類對象信息的獲得
```
Calendar c1 = Calendar.getInstance();
// 獲得年份
int year = c1.get(Calendar.YEAR);
// 獲得月份
int month = c1.get(Calendar.MONTH) + 1;
// 獲得日期
int date = c1.get(Calendar.DATE);
// 獲得小時
int hour = c1.get(Calendar.HOUR_OF_DAY);
// 獲得分鐘
int minute = c1.get(Calendar.MINUTE);
// 獲得秒
int second = c1.get(Calendar.SECOND);
// 獲得星期幾(注意(這個與Date類是不同的):1代表星期日、2代表星期1、3代表星期二,以此類推)
int day = c1.get(Calendar.DAY_OF_WEEK);
```
## GregorianCalendar類
Calendar類實現了公歷日歷,GregorianCalendar是Calendar類的一個具體實現。
Calendar 的getInstance()方法返回一個默認用當前的語言環境和時區初始化的GregorianCalendar對象。GregorianCalendar定義了兩個字段:AD和BC。這些代表公歷定義的兩個時代。
下面列出GregorianCalendar對象的幾個構造方法:
| **構造函數** | **說明** |
| --- | --- |
| **GregorianCalendar()** | 在具有默認語言環境的默認時區內使用當前時間構造一個默認的 GregorianCalendar。 |
| **GregorianCalendar(int year, int month, int date)** | 在具有默認語言環境的默認時區內構造一個帶有給定日期設置的 GregorianCalendar |
| **GregorianCalendar(int year, int month, int date, int hour, int minute)** | 為具有默認語言環境的默認時區構造一個具有給定日期和時間設置的 GregorianCalendar。 |
| **GregorianCalendar(int year, int month, int date, int hour, int minute, int second)** | ? 為具有默認語言環境的默認時區構造一個具有給定日期和時間設置的 GregorianCalendar。 |
| **GregorianCalendar(Locale aLocale)** | 在具有給定語言環境的默認時區內構造一個基于當前時間的 GregorianCalendar。 |
| **GregorianCalendar(TimeZone zone)** | 在具有默認語言環境的給定時區內構造一個基于當前時間的 GregorianCalendar。 |
| **GregorianCalendar(TimeZone zone, Locale aLocale)** | ?在具有給定語言環境的給定時區內構造一個基于當前時間的 GregorianCalendar。 |
這里是GregorianCalendar 類提供的一些有用的方法列表:
| **方法** | **說明** |
| --- | --- |
| **void add(int field, int amount)** | 根據日歷規則,將指定的(有符號的)時間量添加到給定的日歷字段中。 |
| **protected void computeFields()** | 轉換UTC毫秒值為時間域值 |
| **protected void computeTime()** | 覆蓋Calendar ,轉換時間域值為UTC毫秒值 |
| **boolean equals(Object obj)** | 比較此 GregorianCalendar 與指定的 Object。 |
| **int get(int field)** | 獲取指定字段的時間值 |
| **int getActualMaximum(int field)** | 返回當前日期,給定字段的最大值 |
| **int getActualMinimum(int field)** | 返回當前日期,給定字段的最小值 |
| **int getGreatestMinimum(int field)** | ?返回此 GregorianCalendar 實例給定日歷字段的最高的最小值。 |
| **Date getGregorianChange()** | 獲得格里高利歷的更改日期。 |
| **int getLeastMaximum(int field)** | 返回此 GregorianCalendar 實例給定日歷字段的最低的最大值 |
| **int getMaximum(int field)** | 返回此 GregorianCalendar 實例的給定日歷字段的最大值。 |
| **Date getTime()** | 獲取日歷當前時間。 |
| **long getTimeInMillis()** | 獲取用長整型表示的日歷的當前時間 |
| **TimeZone getTimeZone()** | 獲取時區。 |
| **int getMinimum(int field)** | 返回給定字段的最小值。 |
| **int hashCode()** | 重寫hashCode. |
| **boolean isLeapYear(int year)** | 確定給定的年份是否為閏年。 |
| **void roll(int field, boolean up)** | 在給定的時間字段上添加或減去(上/下)單個時間單元,不更改更大的字段。 |
| **void set(int field, int value)** | 用給定的值設置時間字段。 |
| **void set(int year, int month, int date)** | 設置年、月、日的值。 |
| **void set(int year, int month, int date, int hour, int minute)** | 設置年、月、日、小時、分鐘的值。 |
| **void set(int year, int month, int date, int hour, int minute, int second)** | 設置年、月、日、小時、分鐘、秒的值。 |
| **void setGregorianChange(Date date)** | 設置 GregorianCalendar 的更改日期。 |
| **void setTime(Date date)** | 用給定的日期設置Calendar的當前時間。 |
| **void setTimeInMillis(long millis)** | 用給定的long型毫秒數設置Calendar的當前時間。 |
| **void setTimeZone(TimeZone value)** | 用給定時區值設置當前時區。 |
| **String toString()** | 返回代表日歷的字符串。 |
### 實例
```
import java.util.*;
public class GregorianCalendarDemo {
public static void main(String args[]) {
String months[] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"};
int year;
// 初始化 Gregorian 日歷
// 使用當前時間和日期
// 默認為本地時間和時區
GregorianCalendar gcalendar = new GregorianCalendar();
// 顯示當前時間和日期的信息
System.out.print("Date: ");
System.out.print(months[gcalendar.get(Calendar.MONTH)]);
System.out.print(" " + gcalendar.get(Calendar.DATE) + " ");
System.out.println(year = gcalendar.get(Calendar.YEAR));
System.out.print("Time: ");
System.out.print(gcalendar.get(Calendar.HOUR) + ":");
System.out.print(gcalendar.get(Calendar.MINUTE) + ":");
System.out.println(gcalendar.get(Calendar.SECOND));
// 測試當前年份是否為閏年
if(gcalendar.isLeapYear(year)) {
System.out.println("當前年份是閏年");
}
else {
System.out.println("當前年份不是閏年");
}
}
}
```
以上實例編譯運行結果如下:
```
Date: Apr 22 2009
Time: 11:25:27
當前年份不是閏年
```
關于Calender 類的完整列表,你可以參考標準的Java文檔。
- Java 基礎
- Java 簡介
- Java開發環境配置
- Java基礎語法
- Java對象和類
- Java基本數據類型
- Java變量類型
- Java修飾符
- Java運算符
- Java循環結構 - for, while 及 do...while
- Java分支結構 - if...else/switch
- Java Number類
- Java Character類
- Java String類
- Java StringBuffer和StringBuilder類
- Java 數組
- Java 日期時間
- Java正則表達式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 異常處理
- Java 面向對象
- Java 繼承
- Java 重寫(Override)與重載(Overload)
- Java 多態
- Java 抽象類
- Java 接口
- Java 包(package)
- Java 高級教程
- Java 數據結構
- Java Enumeration接口
- Java Bitset類
- Java Vector 類
- Java Stack 類
- Java Dictionary 類
- Java Hashtable 接口
- Java Properties 接口
- Java 集合框架
- Java 泛型
- Java序列化
- Java 網絡編程
- Java 發送郵件
- Java 多線程編程
- Java Applet基礎
- Java 文檔注釋
- Servlet 教程
- Servlet 簡介
- Servlet 環境設置
- Servlet 生命周期
- Servlet 實例
- Servlet 表單數據
- Servlet 客戶端 HTTP 請求
- Servlet 服務器 HTTP 響應
- Servlet HTTP 狀態碼
- Servlet 編寫過濾器
- Servlet 異常處理
- Servlet Cookies 處理
- Servlet Session 跟蹤
- Servlet 數據庫訪問
- Servlet 文件上傳
- Servlet 處理日期
- Servlet 網頁重定向
- Servlet 點擊計數器
- Servlet 自動刷新頁面
- Servlet 發送電子郵件
- Servlet 包
- Servlet 調試
- Servlet 國際化
- JSP 基礎
- JSP 簡介
- JSP 開發環境搭建
- JSP 結構
- JSP 生命周期
- JSP 語法
- JSP 指令
- JSP 動作元素
- JSP 動作元素
- JSP 隱含對象
- JSP 客戶端請求
- JSP 服務器響應
- JSP HTTP 狀態碼
- JSP 表單處理
- JSP 過濾器
- JSP Cookies 處理
- JSP Session
- JSP 文件上傳
- JSP 日期處理
- JSP 頁面重定向
- JSP 點擊量統計
- JSP 自動刷新
- JSP 發送郵件
- JSP 高級教程
- JSP 標準標簽庫(JSTL)
- JSP 連接數據庫
- JSP XML 數據處理
- JSP JavaBean
- JSP 自定義標簽
- JSP 表達式語言
- JSP 異常處理
- JSP 調試
- JSP 國際化
- 免責聲明