簡介

這篇主要探討怎麼把當地時間轉換成GMT(UTC)時間,不在意一秒誤差的話這兩者基本上是一樣的。
主要用到下列三個元件

  • Date:
    • 最基礎的時間紀錄
    • 無法呈現任何有意義的資訊(例如年月的int,或格式化過的字串)
  • SimpleDateFormat
    • 擅長格式化字串與Date之間的轉換
  • Calendar
    • 擅長對時間作操作(比較,加減)
    • 擅長單獨取出欄位(年、月、日、時、分、秒等)

格式化字串

這邊示範如果取得一個Date或一個Calendar,應該如何將其格式化為字串。
格式統一採用 “年-月-日 時:分:秒”。

Date

Date本身沒辦法呈現任何有意義的資訊,只是一個時間記錄器而已。
因此必須依靠SimpleDateFormat來將Date格式化為有意義的字串。

1
2
3
4
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單獨取值的方法走了不一樣的路徑。

1
2
3
4
5
6
7
8
9
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都可以直接取得現在時間,程式碼分別如下。

1
2
Date date = new Date(); // 直接初始化即可取得現在時間
Calendar calendar = Calendar.getInstance(); // getInstance可以取得現在時間

要記得,如果單獨使用Date的話基本上是無法呈現任何有用資訊的。
可以配合剛剛的format method來印出格式化資訊觀看。

1
2
3
Date currentTime = new Date(); // 現在時間的Date物件
String display = formatDate(currentTime);
System.out.println( display );
1
2
3
Calendar currentTime = Calendar.getInstance(); // 現在時間的Calendar物件
String display = formatCalendar(calendar)
System.out.println( display );

顯示現在GMT時間

Date

默念三次

Date本身是絕對時間
Date本身是絕對時間
Date本身是絕對時間

格式化Date為有意義的字串是SimpleDateFormat提供的功能。
SimpleDateFormat會以使用者所在的時區當作預設顯示時區,若要調整可以在兩個地方修改。

  1. 初始化時指定地區
  2. 初始化後再set時區

下面選的是第二種。

1
2
3
4
5
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時間了。

1
2
3
Date date = new Date();
String display = formatDateInGMT(date);
System.out.println(display);

Calendar

Calendar本身就可以設定時區。
因此若要顯示現在的GMT時間的話,只要在取得Calendar實例後更改時區即可。

1
2
3
4
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

1
2
3
4
5
6
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函式。

1
2
3
4
5
6
7
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

1
2
3
4
5
6
7
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。

1
2
3
4
5
6
7
public Calendar convertGMTStringToCalendar(String time) throws ParseException {
	// 假設input的字串是 "年-月-日 時:分:秒" 格式
	Date date = convertGMTStringToDate(time);
	Calendar calendar = Calendar.getInstance();
	calendar.setTime(date);
	return calendar;
}

驗證一樣可以用

  • formatCalendar()

來格式化結果。要記得若要觀看不同時區的結果,必須先設定Calendar。

快速複製區

剛剛講解中一些重要函式的快速複製區,提供給以後的自己使用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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;
}