【時間和時區】Date與String

Date中保存的是什麼

在java中,只要我們執行

Date date = new Date();

就可以得到當前時間。如:

Date date = new Date();
System.out.println(date);

輸出結果是: Thu Aug 24 10:15:29 CST 2017

也就是我執行上述代碼的時刻:2017年8月24日10點15分29秒。是不是Date對象裏存了年月日時分秒呢?不是的,Date對象裏存的只是一個long型的變量,其值爲自1970年1月1日0點至Date對象所記錄時刻經過的毫秒數,調用Date對象getTime()方法就可以返回這個毫秒數,如下代碼:

Date date = new Date();
System.out.println(date + ", " + date.getTime());

輸出結果是: Thu Aug 24 10:48:05 CST 2017, 1503542885955

即上述程序執行的時刻是2017年8月24日10點48分05秒,該時刻距離1970年1月1日0點經過了1503542885955毫秒。反過來說,輸出的年月日時分秒其實是根據這個毫秒數來反算出來的。

 

時區的概念

全球分爲24個時區,相鄰時區時間相差1個小時。比如北京處於東八時區,東京處於東九時區,北京時間比東京時間晚1個小時,而英國倫敦時間比北京晚7個小時(英國採用夏令時時,8月英國處於夏令時)。比如此刻北京時間是2017年8月24日11:17:10,則東京時間是2017年8月24日12:17:10,倫敦時間是2017年8月24日4:17:10。調用Date對象getTime()方法就可以返回這個毫秒數。

 

Date的時區無關性

既然Date裏存放的是當前時刻距1970年1月1日0點時刻的毫秒數,如果此刻在倫敦、北京、東京有三個程序員同時執行如下語句:

Date date = new Date();

那這三個date對象裏存的毫秒數是相同的嗎?還是北京的比東京的小3600000(北京時間比東京時間晚1小時,1小時爲3600秒即3600000毫秒)?答案是,這3個Date裏的毫秒數是完全一樣的。

確切的說,Date對象裏存的是自格林威治時間( GMT)1970年1月1日0點至Date對象所表示時刻所經過的毫秒數。所以,如果某一時刻遍佈於世界各地的程序員同時執行new Date語句,這些Date對象所存的毫秒數是完全一樣的。也就是說,Date裏存放的毫秒數是與時區無關的

 

 

Date 與  Sting 格式互轉:

package utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * Date 和  String
 * 關於時間的格式,在應用中一般用 Stirng 和 Date 來表示,
 *
 * Date--> String 沒有時區的概念,Date中的內容都是 國際的,當getHour() toString() 等方法時,
 * 通過 獲取本地的時區對Date進行格式轉換再輸出
 * 
 * String --> Date 時,傳遞的 String,默認是本地的時區時間,如果傳遞的參數不是本地時區時間時,
 * 在轉換爲 Date時,需要指定時區
 */
public class Test_TimeZone {

	public static void main(String[] args) throws ParseException {
		
		Date date = new Date();
		System.out.println(date.getTime());  // 全球統一值
		System.out.println(date.toString()); // toString的時候獲取本地時區,做了時間轉換,並不是Date的真實時間
		System.out.println();
		
		String date_str_1 = format(date);
		System.out.println(date_str_1);
		
		Date date_1 = parse(date_str_1);
		System.out.println(date_1.toString());
	
		/*  查看 支持的 TimeZone
		String[] ss = TimeZone.getAvailableIDs();
		for (String string : ss) {
			if (string.indexOf("GMT") > 0) {
				System.out.println(string);
			}
		}
		*/
	}
	
	/**
	 * 日期格式轉字符串   (Date -- > String)
	 * Date 轉字符串,格式隨便定義都可以
	 */
	public static String format(Date date) throws ParseException {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		//df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
		//df.setTimeZone(TimeZone.getTimeZone("Etc/GMT-8"));
		df.setTimeZone(TimeZone.getTimeZone("GMT")); // 國際時間,決定輸出的 String 是國際格式

		return df.format(date);
	}
	/**
	 * 字符串轉日期格式    (String --> Date)
	 */
	public static Date parse(String s) throws ParseException {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		//df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
		//df.setTimeZone(TimeZone.getTimeZone("Etc/GMT-8")); 
		df.setTimeZone(TimeZone.getTimeZone("GMT")); // 指定參數 String爲國際格式,輸出時,按本地時區輸出
		
		return df.parse(s);
	}
}

 

將 某個時區 的 String 格式 轉換爲 另一個時區的 String 格式

package utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Test_Time {

	public static void main(String[] args) throws ParseException {
		parse_format();
	}
	/**
	 * 將 某個時區的 String 的格式 轉換爲 另一個時區的 String 格式 
	 * @throws ParseException
	 */
	public static void parse_format() throws ParseException {

		String timeStr = "2017-8-24 11:17:10";
		/* 
		 * 一般是通過 Date 轉換過來的,Date 轉換到 String 的時候 需要指定時區,所以得到的String是有時區的
		 * (當你此刻輸入一個 String 格式的時間時,這個String一定是有時區的,所以 要深刻理解 String 是有時區的,
		 *  任何時候需要操作該值的時候,都要指定 String 代表的時區)
		 */
		
		SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		bjSdf.setTimeZone(TimeZone.getTimeZone("GMT"));  
		/*
		 *  指定 字符串的時區
		 *  將字符串時間按 國際時間 解析成Date對象
		 *  (因爲你通過其他地方獲取的 String 是國際時間格式,所以按照國際時間轉換)
		 */
		Date date = bjSdf.parse(timeStr); 
		System.out.println(date.getTime());   
		/*  
		 * 如果你獲取的 是 本地的字符串時間,那就需要按照 本地的 時區轉換,
		 * 轉換成功之後,獲取的Date都是國際格式,但是在 toString的時候,會默認按本地時區輸出,但是輸出內容並不是國際時間,
		 *
		 * 但getTime()是統一的,所以我們認爲 Date 沒有時區的概念,任何的輸出操作都會先獲取本地時區,將國際時間格式的Date,按本地時區輸出。(輸出內容不可信)
		 */ 
		SimpleDateFormat tokyoSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 東京
		tokyoSdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo")); // 設置東京時區
		System.out.println("國際時間: " + timeStr + " 對應的東京時間爲:" + tokyoSdf.format(date));
		/*
		 *  輸出:
		 *    1503573430000
		 *    國際時間: 2017-8-24 11:17:10 對應的東京時間爲:2017-08-24 20:17:10
		 * */
	}

}

 

我覺得這兩個例子,應該就能說明大部分問題了,

深刻理解 Date 沒有時區的概念,任何的輸出信息都是根據本地時區來輸出的。

任何一個 String 格式的字符串都有相對應的時區,因爲任何的String都是通過 new Date() 和  format() 轉換過來的,即使沒有寫時區,當時默認也獲取了本地時區。所以,Sting 一定有對應的時區。

 

 

參考博客:

https://blog.csdn.net/halfclear/article/details/77573956

https://www.cnblogs.com/softidea/p/8612287.html

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章