[Java] Date SimpleDateFormat Calendar之轉換與時區(UTC/GMT)問題
Contents
簡介
這篇主要探討怎麼把當地時間轉換成GMT(UTC)時間,不在意一秒誤差的話這兩者基本上是一樣的。
主要用到下列三個元件
- Date:
- 最基礎的時間紀錄
- 無法呈現任何有意義的資訊(例如年月的int,或格式化過的字串)
- SimpleDateFormat
- 擅長格式化字串與Date之間的轉換
- Calendar
- 擅長對時間作操作(比較,加減)
- 擅長單獨取出欄位(年、月、日、時、分、秒等)
格式化字串
這邊示範如果取得一個Date或一個Calendar,應該如何將其格式化為字串。
格式統一採用 “年-月-日 時:分:秒”。
Date
Date本身沒辦法呈現任何有意義的資訊,只是一個時間記錄器而已。
因此必須依靠SimpleDateFormat來將Date格式化為有意義的字串。
String formatDate(Date date){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // HH是24小時制,hh是12小時制
return sdf.format(date);
}
Calendar
Calendar有一個method叫getTime,可以取出此Calendar目前的Date。在有formatDate
此函式的情況下,其實只要先getTime再丟給formatDate即可。
只是這邊為了展示calendar單獨取值的方法走了不一樣的路徑。
String formatCalendar(Calendar calendar){
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1; // 1月的值為0
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY); // HOUR_OF_DAY是24小時制,HOUR是12小時制
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
return String.format("%d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
}
hint: 這兩個function在後續的程式碼中會常常用到
取得現在時間
使用Date和Calendar都可以直接取得現在時間,程式碼分別如下。
Date date = new Date(); // 直接初始化即可取得現在時間
Calendar calendar = Calendar.getInstance(); // getInstance可以取得現在時間
要記得,如果單獨使用Date的話基本上是無法呈現任何有用資訊的。
可以配合剛剛的format method來印出格式化資訊觀看。
Date currentTime = new Date(); // 現在時間的Date物件
String display = formatDate(currentTime);
System.out.println( display );
Calendar currentTime = Calendar.getInstance(); // 現在時間的Calendar物件
String display = formatCalendar(calendar)
System.out.println( display );
顯示現在GMT時間
Date
默念三次
Date本身是絕對時間
Date本身是絕對時間
Date本身是絕對時間
格式化Date為有意義的字串是SimpleDateFormat提供的功能。
SimpleDateFormat會以使用者所在的時區當作預設顯示時區,若要調整可以在兩個地方修改。
- 初始化時指定地區
- 初始化後再set時區
下面選的是第二種。
String formatDateInGMT(Date date){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // HH是24小時制,hh是12小時制
sdf.setTimeZone(TimeZone.getTimeZone("GMT") );
return sdf.format(date);
}
接下來只要獲得現在的Date,就可以印出對應的GMT時間了。
Date date = new Date();
String display = formatDateInGMT(date);
System.out.println(display);
Calendar
Calendar本身就可以設定時區。
因此若要顯示現在的GMT時間的話,只要在取得Calendar實例後更改時區即可。
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
String display = formatCalendar(calendar);
System.out.println(display);
由字串取得時間
SimpleDateFormat可以很方便的在格式化字串和Date之間做轉換,但遺憾的是無法將格式化字串直接轉換為Calendar,必須要用Date來設定Calendar才行。
格式化字串轉換為Date
下方的範例利用SimpleDateFormat將字串轉換為Date
public Date convertStringToDate(String time) throws ParseException {
// 假設input的字串是 "年-月-日 時:分:秒" 格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(time);
return date;
}
觀看有沒有成功一樣可以使用formatDate來觀看,這邊就不說明了。
格式化字串為Calendar
先取得Date,再設定Calendar,會用到上方的convertStringToDate函式。
public Calendar convertStringToCalendar(String time) throws ParseException {
// 假設input的字串是 "年-月-日 時:分:秒" 格式
Date date = convertStringToDate(time);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar;
}
由GMT字串取得時間
先默念三次
Date是絕對時間
Date是絕對時間
Date是絕對時間
因此要從字串轉換為Date時,該告知的是SimpleDateFormat此時間字串是在GMT時區,如此SimpleDateFormat轉出來的Date才會正確。
格式化GMT字串為Date
public Date convertGMTStringToDate(String time) throws ParseException {
// 假設input的字串是 "年-月-日 時:分:秒" 格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT") ); // 告知接下來的字串時區位在GMT
Date date = sdf.parse(time);
return date;
}
驗證一樣可以用
- formatDate
- formatDateInGMT
這兩個函式來格式化結果並印出觀看。
格式化GMT字串為Calendar
轉換為Calendar也是同理,先取得Date,再設定Calendar。
public Calendar convertGMTStringToCalendar(String time) throws ParseException {
// 假設input的字串是 "年-月-日 時:分:秒" 格式
Date date = convertGMTStringToDate(time);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar;
}
驗證一樣可以用
- formatCalendar()
來格式化結果。要記得若要觀看不同時區的結果,必須先設定Calendar。
快速複製區
剛剛講解中一些重要函式的快速複製區,提供給以後的自己使用。
String formatDate(Date date){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // HH是24小時制,hh是12小時制
return sdf.format(date);
}
String formatDateInGMT(Date date){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // HH是24小時制,hh是12小時制
sdf.setTimeZone(TimeZone.getTimeZone("GMT") );
return sdf.format(date);
}
String formatCalendar(Calendar calendar){
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1; // 1月的值為0
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY); // HOUR_OF_DAY是24小時制,HOUR是12小時制
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
return String.format("%d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
}
public Date convertStringToDate(String time) throws ParseException {
// 假設input的字串是 "年-月-日 時:分:秒" 格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(time);
return date;
}
public Calendar convertStringToCalendar(String time) throws ParseException {
// 假設input的字串是 "年-月-日 時:分:秒" 格式
Date date = convertStringToDate(time);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar;
}
public Date convertGMTStringToDate(String time) throws ParseException {
// 假設input的字串是 "年-月-日 時:分:秒" 格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT") ); // 告知接下來的字串時區位在GMT
Date date = sdf.parse(time);
return date;
}
public Calendar convertGMTStringToCalendar(String time) throws ParseException {
// 假設input的字串是 "年-月-日 時:分:秒" 格式
Date date = convertGMTStringToDate(time);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar;
}