2008-10-05

Java Type - 時間型別之間之差異 以PostgreSQL對應

測試平台:JDK SE 6

測試目標:

java.util.Date
java.util.Calendar
java.sql.Date
java.sql.Time
java.sql.Timestamp

測試目的:
對於五種都是所謂的時間類別,有什麼區別。


1.是否能自己產生時間:
java.util.Date:

在java.util.Date建構子上,預設的情況,public Date() { this(System.currentTimeMillis()); } ,預設會調用System.currentTimeMillis()的方法。

System.currentTimeMillis()在API的內容:

currentTimeMillis

public static long currentTimeMillis()
返回以毫秒為單位的當前時間。注意,當返回值的時間單位是毫秒時,值的粒度取決於底層作業系統,並且粒度可能更大。例如,許多作業系統以幾十毫秒為單位測量時間。

請參閱 Date 類別的描述,瞭解可能發生在“計算機時間”和協調世界時(UTC)之間的細微差異的討論。

返回:
當前時間與協調世界時 1970 年 1 月 1 日午夜之間的時間差(以毫秒為單位測量)。
另請參見:
Date
表示說在java.util.Date建構時,也會順便初始本地時間。也可以明確了解,java.util.Date能夠自己產生本地時間。


java.util.Calendar:
java.util.Calendar為抽象類別,建構方式透過Calendar.getInstance()初始, public static Calendar getInstance() { Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault()); cal.sharedZone = true; return cal; } ,在預設的情況下會順便invoked TimeZone.getDefault(),以及Loale.getDefault()這兩個方法。

TimeZone.getDefault()在API的內容:

getDefault

public static TimeZone getDefault()
獲取此主機的預設 TimeZone。預設 TimeZone 的來源可能隨實作的變化而變化。


返回:
預設的 TimeZone
另請參見:
setDefault(java.util.TimeZone)
Locale.getDefault()在API的內容:

getDefault

public static Locale getDefault()
獲得此 Java 虛擬機器實例的當前預設語言環境值。

Java 虛擬機器根據主機的環境在啟動期間設置預設語言環境。如果沒有明確地指定語言環境,則很多語言環境敏感的方法都使用該方法。可使用 setDefault 方法更改該值。


返回:
此 Java 虛擬機器實例的預設語言環境。
因為這些方法,java.util.Calendar在透過getInstance()後,會順便初始時間及時區,也就可以得知,java.util.Calendar能夠自己產生時間。


java.sql.Date:
在API的內容:

public class Date
extends Date

一個套件裝了毫秒值的瘦外覆類別 (thin wrapper),它允許 JDBC 將毫秒值標識為 SQL DATE 值。毫秒值表示自 1970 年 1 月 1 日 00:00:00 GMT 以來經過的毫秒數。

為了與 SQL DATE 的定義一致,由 java.sql.Date 實例包裹的毫秒值必須通過將小時、分鐘、秒和毫秒設置為與該實例相關的特定時區中的零來“規範化”。



可以得知,java.sql.Date屬於一個wrapper class,專門用來承接時間數據,轉為與資料庫中的date型態相符合的型態。
所以java.sql.Date,並無法自己產生出時間。


java.sql.Time:
在API的內容:

public class Time
extends Date

一個與 java.util.Date 類別有關的瘦外覆類別 (thin wrapper),它允許 JDBC 將該類別標識為 SQL TIME 值。Time 類別添加格式化和解析操作以支持時間值的 JDBC 轉義語法。

應該將日期元件設置為 1970 年 1 月 1 日的 "zero epoch" 值並且不應存取該值。


可以得知,java.sql.Time屬於一個wrapper class,專門用來承接時間數據,轉為與資料庫中的time型態相符合的型態。
所以java.sql.Time,並無法自己產生出時間。


java.sql.Timestamp:
在API的內容:

public class Timestamp
extends Date

一個與 java.util.Date 類別有關的瘦外覆類別 (thin wrapper),它允許 JDBC API 將該類別標識為 SQL TIMESTAMP 值。它通過允許小數秒到納秒級精度的規範來添加保存 SQL TIMESTAMP 小數秒值的能力。Timestamp 也提供支持時間戳值的 JDBC 轉義語法的格式化和解析操作的能力。

計算 Timestamp 物件的精度為二者之一:

  • 19 ,其為 yyyy-mm-dd hh:mm:ss 格式下的字元數
  • 20 + s ,其為 yyyy-mm-dd hh:mm:ss.[fff...] 格式下的字元數,s 表示給定 Timestamp 的標度(其小數秒精度)。

註:此型別由 java.util.Date 和單獨的毫微秒值組成。只有整數秒才會存儲在 java.util.Date 元件中。小數秒(毫微秒)是獨立存在的。傳遞不是 java.sql.Timestamp 實例的物件時,Timestamp.equals(Object) 方法永遠不會返回 true,因為日期的毫微秒元件是未知的。因此,相對於 java.util.Date.equals(Object) 方法而言,Timestamp.equals(Object) 方法是不對稱的。此外,hashcode 方法使用底層 java.util.Date 實作並因此在其計算中不包括毫微秒。

鑒於 Timestamp 類別和上述 java.util.Date 類別之間的不同,建議程式碼一般不要將 Timestamp 值視為 java.util.Date 的實例。Timestampjava.util.Date 之間的繼承關係實際上指的是實作繼承,而不是型別繼承。


可以得知,java.sql.Timestamp屬於一個wrapper class,專門用來承接時間數據,轉為與資料庫中的timestamp型態相符合的型態。所以java.sql.Timestamp,並無法自己產生出時間。


2.對應資料庫存取方法區別:
以下為API內容,選擇java.sql.PreparedStatement內的方法:

setDate

void setDate(int parameterIndex,
Date x)
throws SQLException
使用運行應用程序的虛擬機器的預設時區將指定參數設置為給定 java.sql.Date 值。在將此值發送到資料庫時,驅動程序將它轉換成一個 SQL DATE 值。


參數:
parameterIndex - 第一個參數是 1,第二個參數是 2,……
x - 參數值
拋出:
SQLException - 如果 parameterIndex 不對應於 SQL 語句中的參數標記;如果發生資料庫存取錯誤,或者在關閉的 PreparedStatement 上調用此方法

setTimestamp

void setTimestamp(int parameterIndex,
Timestamp x)
throws SQLException
將指定參數設置為給定 java.sql.Timestamp 值。在將此值發送到資料庫時,驅動程序將它轉換成一個 SQL TIMESTAMP 值。


參數:
parameterIndex - 第一個參數是 1,第二個參數是 2,……
x - 參數值
拋出:
SQLException - 如果 parameterIndex 不對應於 SQL 語句中的參數標記;如果發生資料庫存取錯誤,或者在關閉的 PreparedStatement 上調用此方法


setTime

void setTime(int parameterIndex,
Time x)
throws SQLException
將指定參數設置為給定 java.sql.Time 值。在將此值發送到資料庫時,驅動程序將它轉換成一個 SQL TIME 值。


參數:
parameterIndex - 第一個參數是 1,第二個參數是 2,……
x - 參數值
拋出:
SQLException - 如果 parameterIndex 不對應於 SQL 語句中的參數標記;如果發生資料庫存取錯誤,或者在關閉的 PreparedStatement 上調用此方法

由上面三個主要存取給資料庫型別date, time, timestamp 的方法,可以明確了解,在JDBC的要求上,透過java.sql.Date, java.sql.Time, java.sql.Timestamp,最為符合跟資料庫存取的規格,所以java.util.Date, java.util.Calendar,要存進資料庫時,得透過java.sql.Date, java.sql.Time, java.sql.Timestamp 的包覆,才便於存進資料庫。

整理表格如下:

Java Types 自己產生時間 存入PostgreSQL資料庫的對應型別
java.util.Date T 需要包覆
java.util.Calendar T 需要包覆
java.sql.Date F date
java.sql.Time F time
java.sql.Timestamp F timestamp

沒有留言:

網誌存檔

PostgreSQL & Google-Analytics Running...

::Planet PostgreSQL::

PostgreSQL Information Page

PostgreSQL日記(日本 石井達夫先生Blog)

PostgreSQL News

黑喵的家 - 資料庫相關

Google 網上論壇
PostgreSQL 8 DBA 專業指南中文版
書籍內容討論與更多下載區(造訪此群組)
目錄下載: PostgreSQL_8 _DBA_Index_zh_TW.pdf (更新:2007-05-18)

全球訪客分佈圖(Google)

全球訪客分佈圖(Google)