引言
最近偶遇apache開發的工作java工具包,一使用,就發現自己愛上它了。不多說了,下面介紹org.apache.commons.lang3.time包中處理java程序員為之頭疼的時間的類。
附上官網jar包下載地址:http://commons.apache.org/proper/commons-lang/download_lang.cgi
在這之前還是先簡單說一下java本身的時間處理類。
Calendar 類是一個抽象類,它為特定瞬間與一組諸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日歷字段之間的轉換提供了一些方法,並為操作日歷字段(例如獲得下星期的日期)提供了一些方法。瞬間可用毫秒值來表示,它是距歷元(即格林威治標准時間 1970 年 1 月 1 日的 00:00:00.000,格裡高利歷)的偏移量。
該類還為實現包范圍外的具體日歷系統提供了其他字段和方法。這些字段和方法被定義為 protected。
具體可見API手冊。
SimpleDateFromat不是線程安全的,這是因為它繼承了DateFormat中的一個Calendar成員,每次在執行format操作時,都會改成成員calendar的狀態。這就是不安全的根源。
多線程下,很可能對Calendar的寫 和 讀 操作不同步(不是被同一個線程執行的),就會發生意外。
class DateFromat {
protected Calendar calendar;
//... } SimpleDateFromat extends DateFromat { private StringBuffer format(Date date, StringBuffer toAppendTo,FieldDelegate delegate) { // Convert input date to time field list calendar.setTime(date); //.... //.... }
}
下面開始介紹文章的主角類。
提供了對時間對象的運算操作,就像和操作 int 一樣。
工具類,不允許創建實例
//-------------------靜態字段-------------------
public static final long MILLIS_PER_DAY = 86400000L 一天的毫秒數
public static final long MILLIS_PER_HOUR = 3600000L 一個小時的毫秒數
public static final long MILLIS_PER_MINUTE = 60000L 一分鐘的毫秒數
public static final long MILLIS_PER_SECOND = 1000L 一秒鐘的毫秒數
//-------------------靜態方法------------------
Date的運算和修改
static Date addDays(Date date, int amount) 返回一個date 時間對象 添加 amount 天 後的新的Date 對象
static Date addHours(Date date, int amount) 返回一個date 時間對象 添加 amount h 後的新的Date 對象
static Date addMilliseconds(Date date, int amount) 返回一個date 時間對象 添加 amount 毫秒 後的新的Date 對象
static Date addMinutes(Date date, int amount) 返回一個date 時間對象 添加 amount 分鐘 後的新的Date 對象
static Date addMonths(Date date, int amount) 返回一個date 時間對象 添加 amount 月 後的新的Date 對象
static Date addSeconds(Date date, int amount) 返回一個date 時間對象 添加 amount 秒 後的新的Date 對象
static Date addWeeks(Date date, int amount) 返回一個date 時間對象 添加 amount 周 後的新的Date 對象
static Date addYears(Date date, int amount) 返回一個date 時間對象 添加 amount 年 後的新的Date 對象
static Date setDays(Date date, int amount) 修改一個Date 對象的 天數 並返回新的Date對象。
static Date setHours(Date date, int amount) 修改一個Date 對象的 小時字段並返回新的Date
static Date setMilliseconds(Date date, int amount) 修改一個Date 對象的 毫秒,並返回新的Date 對象
static Date setMinutes(Date date, int amount) 修改一個Date 對象的 分鐘
static Date setMonths(Date date, int amount) 修改月份
static Date setSeconds(Date date, int amount) 修改秒
static Date setYears(Date date, int amount) 修改 年
字符串------>Date
從一個字符串str中按照 給定的字符串時間格式(見文章最後的SimpleDateFormat表),解析出一個時間對象。
可以給定多個字符串時間格式,依次嘗試解析,如果都不能正確解析,則拋出java.text.ParseException異常。
如
DateUtils.parseDate("10-05-2016 12:45",Locale.CHINA, "dd-MM-yyyy HH:mm")
static Date parseDate(String str, Locale locale, String... parsePatterns)
static Date parseDateStrictly(String str, Locale locale, String... parsePatterns)
static Date parseDateStrictly(String str, String... parsePatterns)
對時間的向上取整,截斷,四捨五入,和 對浮點數的操作機制一樣。
對一個時間對象的某個字段進行向上取整。 filed指定取整的字段,可以取的值為
Calendar.SECOND
Calendar.MINUTE
Calendar.HOUR_OF_DAY
Calendar.DAY_OF_MONTH
Calendar.MONTH
Calendar.YEAR 等...
如時間為:2016-2-12 22:17:48,若對年進行向上取整(ceiling),則看傳入的參數的月份,為2,向上取值為年底,則會變為2017年
2017-1-1 0:00:00
如時間為:2016-2-25 22:17:48,若對月進行截斷取整(truncate),則看傳入的參數的天,為12,直接丟棄,則會變為本月第一天
2016-2-1 0:00:00
static Calendar ceiling(Calendar date, int field)
static Date ceiling(Date date, int field)
static Calendar round(Calendar date, int field) 和ceil同理,round 是四捨五入
static Date round(Date date, int field)
static Calendar truncate(Calendar date, int field) 對一個時間對象的某個字段進行截斷。
static Date truncate(Date date, int field)
static int truncatedCompareTo(Calendar cal1, Calendar cal2, int field) 2個時間對象截斷某個字段後比較,前者小返回-1,相同返回0,否則返回1
static int truncatedCompareTo(Date date1, Date date2, int field)
static boolean truncatedEquals(Calendar cal1, Calendar cal2, int field) 2個時間對象截斷某個字段後比較,相同返回true,否則返回false
static boolean truncatedEquals(Date date1, Date date2, int field)
將Date 轉換為Calendar
static Calendar toCalendar(Date date)
時間 對象的 想等/相近 比較
static boolean isSameDay(Calendar cal1, Calendar cal2) 是否是同一天,而不在乎具體時間,如 2月12 18:00 和 2月12 23:35 都是一天
static boolean isSameDay(Date date1, Date date2) 是否是同一天,而不在乎具體時間,如 2月12 18:00 和 2月12 23:35 都是一天
static boolean isSameInstant(Calendar cal1, Calendar cal2) 是否完全代表同一個時刻,相同。
static boolean isSameInstant(Date date1, Date date2) 是否完全代表同一個時刻,相同。
將時間轉化為字符串的工具類。不可實例化對象。
線程安全。
這個類中的所有重載的format 實質都是調了下面2個函數。而這2個函數中又借用了FastDateFormat的API。
FastDateFormat是apache time util 優於Java SimpleDateFormat 的核心類。它是線程安全的。
public static String format(final Date date, final String pattern, final TimeZone timeZone, final Locale locale) { final FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale); return df.format(date); } public static String format(final Calendar calendar, final String pattern, final TimeZone timeZone, final Locale locale) { final FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale); return df.format(calendar); }
時間參數 可以是Date 對象 ,Calender 對象 ,或者一個相對於1970年的long整數 pattern ,如:"yyyy-MM-dd HH:mm:ss" 參見文章最後SimpleDateFormat格式表 Locale:地理,政治和文化地區 如Locale.CHINA TimeZone:時區偏移量. TimeZone.getTimeZone("GMT+:08:00"); 北京時間 TimeZone.getDefault() 默認 static String format(Calendar calendar, String pattern) static String format(Calendar calendar, String pattern, Locale locale) static String format(Calendar calendar, String pattern, TimeZone timeZone) static String format(Calendar calendar, String pattern, TimeZone timeZone, Locale locale) static String format(Date date, String pattern) static String format(Date date, String pattern, Locale locale) static String format(Date date, String pattern, TimeZone timeZone) static String format(Date date, String pattern, TimeZone timeZone, Locale locale) static String format(long millis, String pattern) static String format(long millis, String pattern, Locale locale) static String format(long millis, String pattern, TimeZone timeZone) static String format(long millis, String pattern, TimeZone timeZone, Locale locale) static String formatUTC(Date date, String pattern) static String formatUTC(Date date, String pattern, Locale locale) static String formatUTC(long millis, String pattern) static String formatUTC(long millis, String pattern, Locale locale)
DateUtils 在parse時內部利用了java自身的SimpleDateFormat(即便如此,DateUtils的操作都是是線程安全的,因為SimpleDateFromat是作為方法的局部變量使用的),而 DateFormatUtils 利用了apache開發的線程安全的FastDateFromat。因此,DateUtils和DateFormatUtils可以滿足簡單的時間操作了。如果需要更多的定制化操作,就可能需要
下面介紹的FastDateFormat了。
FastDateFormat是一個快速 且 線程安全的時間操作類,它完全可以替代SimpleDateFromat。
因為是線程安全的,所以你可以把它作為一個類的靜態字段使用
構造函數為protected,不允許直接構造它的對象,可以通過工廠方法獲取。
FastDateFormat之所以是線程安全的,是因為這個類是無狀態的:內部的成員在構造時就完成了初始化,並在對象存活期,不提供任何API供外界修改他們。
FastDateFormat內部有很重要的2個對象:
分別完成解析和format工作。他們也都是線程安全的,都修飾為final。有興趣的可以取讀源代碼。
靜態字段
用於構造時,控制時間或者日期顯示的完整性,FULL最完整,SHORT最次。
static int FULL 表示完全顯示
static int LONG
static int MEDIUM
static int SHORT
構造
static FastDateFormat getDateInstance(int style)
static FastDateFormat getDateInstance(int style, Locale locale)
static FastDateFormat getDateInstance(int style, TimeZone timeZone)
static FastDateFormat getDateInstance(int style, TimeZone timeZone, Locale locale)
只控制日期顯示格式
使用style指定的日期顯示的完整性,靜態字段提供
timeZone 指定時區,若不指定,則使用系統默認的
locale 指定 國家區域,若不指定,則使用系統默認的
static FastDateFormat getInstance()
static FastDateFormat getInstance(String pattern)
static FastDateFormat getInstance(String pattern, Locale locale)
static FastDateFormat getInstance(String pattern, TimeZone timeZone)
static FastDateFormat getInstance(String pattern, TimeZone timeZone, Locale locale)
通過String類型的pattern自定義顯示格式
String類型的pattern 指定format格式,參見SimpleDateFormat
timeZone 指定時區,若不指定,則使用系統默認的
locale 指定 國家區域,若不指定,則使用系統默認的
static FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle)
static FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale)
static FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle, TimeZone timeZone)
static FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle, TimeZone timeZone, Locale locale)
同時控制 日期和 時間的顯示格式
使用style指定的日期和時間顯示的完整性,靜態字段提供
StringBuffer format(Date date, StringBuffer buf)
StringBuffer format(long millis, StringBuffer buf)
StringBuffer format(Calendar calendar, StringBuffer buf)
將格式化後的字符串寫入到一個StringBuffer對象中
String format(long millis)
String format(Date date)
String format(Calendar calendar)
Date parse(String source)
Date parse(String source, ParsePosition pos)
從字符串解析一個Date,解析的模式是構造時決定的
String getPattern() 獲取fommat時的pattern
TimeZone getTimeZone()
Locale getLocale()
例子:
import java.util.Date; import java.util.Locale; import org.apache.commons.lang3.time.FastDateFormat; /** * 當使用FastDateFormat.getInstance()構造時,需要和SimpleDateFomat一樣,自定義格式化字符串。 * 當使用FastDateFormat.getDateTimeInstance() 構造時,需要 FastDateFormat的4個靜態字段指定日期 和 時間顯示的具體程度 * 當使用FastDateFormat.getDateInstance() 構造時,意為著你只想顯示日期,需要 FastDateFormat的4個靜態字段指定日期的顯示的具體程度 * */ public class Test { public static void showCustom() { String pattern = "yyyy-MM-dd HH:mm:ss"; final FastDateFormat df = FastDateFormat.getInstance(pattern); System.out.println(df.format(new Date())); } public static void showDateAndTime() { final FastDateFormat df = FastDateFormat.getDateTimeInstance(FastDateFormat.FULL, FastDateFormat.FULL, Locale.CHINA); System.out.println(df.format(new Date())); } public static void showDate() { final FastDateFormat df = FastDateFormat.getDateInstance(FastDateFormat.LONG, Locale.CHINA); System.out.println(df.format(new Date())); } public static void main(String[] args) { showCustom(); showDateAndTime(); showDate(); /*Output * * 2016-10-15 16:18:49 2016年10月15日 星期六 下午04時18分49秒 CST 2016年10月15日 */ } }
SimpleDateFormat的時間字符串表達模式定義表
G
Era designator
Text
AD
y
Year
Year
1996
; 96
Y
Week year
Year
2009
; 09
M
Month in year (context sensitive)
Month
July
; Jul
; 07
L
Month in year (standalone form)
Month
July
; Jul
; 07
w
Week in year
Number
27
W
Week in month
Number
2
D
Day in year
Number
189
d
Day in month
Number
10
F
Day of week in month
Number
2
E
Day name in week
Text
Tuesday
; Tue
u
Day number of week (1 = Monday, ..., 7 = Sunday)
Number
1
a
Am/pm marker
Text
PM
H
Hour in day (0-23)
Number
0
k
Hour in day (1-24)
Number
24
K
Hour in am/pm (0-11)
Number
0
h
Hour in am/pm (1-12)
Number
12
m
Minute in hour
Number
30
s
Second in minute
Number
55
S
Millisecond
Number
978
z
Time zone
General time zone
Pacific Standard Time
; PST
; GMT-08:00
Z
Time zone
RFC 822 time zone
-0800
X
Time zone
ISO 8601 time zone
-08
; -0800
; -08:00