時區計算

1、 JS

兩個函數

  1. 獲得標準時區的時間
//獲得標準時區的時間
function getLocalTime(i) {
    //參數i爲時區值數字,好比北京爲東八區則輸入8,西5輸入-5,現默認東八區北京時間
    var i=i?parseFloat(i):8; 
 
    //獲得本地時間
    var d = new Date();
 
    //獲得1970年一月一日到如今的秒數
    var local = d.getTime();
 
    //本地時間與GMT時間的時間偏移差
    var offset = d.getTimezoneOffset() * 60000;
 
    //獲得如今的格林尼治時間
    var utcTime = local + offset;
 
    return new Date(utcTime + 3600000 * i);
}
  1. 轉換服務器時區時間
//轉換服務器時區時間
function formatTime(t,utc){
    //t傳入的時間參數,utc傳入的時區參數
    if(!t) return;
 
    //獲取本地時間
    var d=new Date();
 
    //得到本地時區
    utc=utc?parseFloat(utc):d.getTimezoneOffset()/60;
 
    //格式化傳入時間
    var time=new Date(t);
 
    //轉換傳入時間爲本地時間(默認傳入服務器時間爲東八區時間)
    time.setHours(time.getHours()+(utc-8));
 
    //輸出時間
    var yy=time.getFullYear();
    var MM=time.getMonth()+1;
    MM=MM<10?'0'+MM:MM;
    var dd=time.getDate();
    dd=dd<10?'0'+dd:dd;
    var hh=time.getHours();
    hh=hh<10?'0'+hh:hh;
    var mm=time.getMinutes();
    mm=mm<10?'0'+mm:mm;
    var ss=time.getSeconds();
    ss=ss<10?'0'+ss:ss;
    var date=yy+'-'+MM+'-'+dd+' '+hh+':'+mm+':'+ss;
 
    return date;
}

利用Date對象獲得本地時間

d = new Date();
localTime = d.getTime(); //經過調用Data()對象的getTime()方法,便可顯示1970年1月1往後到此時時間之間的毫秒數。

接下來,經過Data()對象的getTimezoneOffset()方法來找出當地時間偏移值。在缺省狀況下,此方法以分鐘顯示時區偏移值結果,所以在早先的計算中要將此值轉換成毫秒。java

localOffset = d.getTimezoneOffset() * 3600000;

而後將當前時間與時區偏移量相加,獲得國際標準時間(用毫秒錶示的,由於後面還須要計算,因此這裏不作轉換),而後與你想要知道的時區的偏移量再進行相加,獲得那個時間的時間,而後再利用Date對象將其轉換爲時間字符串。程序員

utc = localTime + localOffset; //獲得國際標準時間  
offset = 5.5;  // 已知的時區
calctime = utc + (3600000*offset);  
nd = new Date(calctime);  
document.write('指定時區時間是:' + nd.toLocalString());

實例

場景描述:根據國外用戶所在的時區,獲取數據庫(東八區錄入)在當地所應展現的時間數據庫

function getLocalTime() {
    var d = new Date();//得到當前時間
    var gmtHours =-( d.getTimezoneOffset()/60);//根據當前時間獲得你是哪一個時區的
    var date = '2014-08-12 09:25:24';//上課時間
    date=date.replace(/-/g,':').replace(' ',':');
    date=date.split(':');
    var time1 = new Date(date[0],(date[1]-1),date[2],date[3],date[4],date[5]);
    console.log("時區:" + gmtHours);
    //獲得1970年一月一日到如今的秒數
    var len = time1.getTime();
    //本地時間與GMT時間的時間偏移差
    var offset = -8 * 3600000; // 東八區
    //獲得如今的格林尼治時間 
    var utcTime = len + offset;
    return new Date(utcTime + 3600000 *gmtHours );
}

2、Java

1. 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毫秒。反過來講,輸出的年月日時分秒實際上是根據這個毫秒數來反算出來的。code

2. 時區

全球分爲24個時區,相鄰時區時間相差1個小時。好比北京處於東八時區,東京處於東九時區,北京時間比東京時間晚1個小時,而英國倫敦時間比北京晚7個小時(英國採用夏令時時,8月英國處於夏令時)。好比此刻北京時間是2017年8月24日11:17:10,則東京時間是2017年8月24日12:17:10,倫敦時間是2017年8月24日4:17:10。orm

既然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裏存放的毫秒數是與時區無關的。字符串

繼續上述例子,若是上述3個程序員調用那一刻的時間是2017年8月24日11:17:10,他們繼續調用

System.out.println(date);

那麼北京的程序員將會打印出2017年8月24日11:17:10,而東京的程序員會打印出2017年8月24日12:17:10,倫敦的程序員會打印出2017年8月24日4:17:10。既然Date對象只存了一個毫秒數,爲何這3個毫秒數徹底相同的Date對象,能夠打印出不一樣的時間呢?這是由於Sysytem.out.println函數在打印時間時,會取操做系統當前所設置的時區,而後根據這個時區將同毫秒數解釋成該時區的時間。固然咱們也能夠手動設置時區,以將同一個Date對象按不一樣的時區輸出。能夠作以下實驗驗證:

Date date = new Date(1503544630000L);  // 對應的北京時間是2017-08-24 11:17:10  
  
SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");     // 北京  
bjSdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));  // 設置北京時區  
  
SimpleDateFormat tokyoSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  // 東京  
tokyoSdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));  // 設置東京時區  
  
SimpleDateFormat londonSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 倫敦  
londonSdf.setTimeZone(TimeZone.getTimeZone("Europe/London"));  // 設置倫敦時區  
  
System.out.println("毫秒數:" + date.getTime() + ", 北京時間:" + bjSdf.format(date));  
System.out.println("毫秒數:" + date.getTime() + ", 東京時間:" + tokyoSdf.format(date));  
System.out.println("毫秒數:" + date.getTime() + ", 倫敦時間:" + londonSdf.format(date));

輸出爲:

毫秒數:1503544630000, 北京時間:2017-08-24 11:17:10
毫秒數:1503544630000, 東京時間:2017-08-24 12:17:10
毫秒數:1503544630000, 倫敦時間:2017-08-24 04:17:10

能夠看出,同一個Date對象,按不一樣的時間來格式化,將獲得不一樣時區的時間。因而可知,Date對象裏保存的毫秒數和具體輸出的時間(即年月日時分秒)是模型和視圖的關係,而時區(即Timezone)則決定了將同模型展現成什麼樣的視圖。

3. 從字符串中讀取時間

有時咱們會遇到從一個字符串中讀取時間的要求,即從字符串中解析時間並獲得一個Date對象,好比將"2017-8-24 11:17:10"解析爲一個Date對象。如今問題來了,這個時間到底指的是北京時間的2017年8月24日11:17:10,仍是東京時間的2017年8月24日11:17:10?若是指的是北京時間,那麼這個時間對應的東京時間2017年8月24日12:17:10;若是指的是東京時間,那麼這個時間對應的北京時間就是2017年8月24日10:17:10。所以,只說年月日時分秒而不說是哪一個時區的,是有歧義的,沒有歧義的作法是,給出一個時間字符串,同時指明這是哪一個時區的時間。 從字符串中解析時間的正確做法是:指定時區來解析。示例以下:

String timeStr = "2017-8-24 11:17:10"; // 字面時間  
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 設置北京時區  
Date d = sdf.parse(timeStr);  
System.out.println(sdf.format(d) + ", " + d.getTime());

輸出爲: 2017-08-24 11:17:10, 1503544630000,

將一個時間字符串按不一樣時區來解釋,獲得的Date對象的值是不一樣的。驗證以下:

String timeStr = "2017-8-24 11:17:10"; // 字面時間  
SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
bjSdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));  
Date bjDate = bjSdf.parse(timeStr);  // 解析  
System.out.println("字面時間: " + timeStr +",按北京時間來解釋:" + bjSdf.format(bjDate) + ", " + bjDate.getTime());  
  
SimpleDateFormat tokyoSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  // 東京  
tokyoSdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));  // 設置東京時區  
Date tokyoDate = tokyoSdf.parse(timeStr); // 解析  
System.out.println("字面時間: " + timeStr +",按東京時間來解釋:"  + tokyoSdf.format(tokyoDate) + ", " + tokyoDate.getTime());

輸出爲:

字面時間: 2017-8-24 11:17:10,按北京時間來解釋:2017-08-24 11:17:10, 1503544630000
字面時間: 2017-8-24 11:17:10,按東京時間來解釋:2017-08-24 11:17:10, 1503541030000
能夠看出,對於"2017-8-24 11:17:10"這個字符串,按北京時間來解釋獲得Date對象的毫秒數是
1503544630000;而按東京時間來解釋獲得的毫秒數是1503541030000,前者正比如後者大於3600000毫秒即1個小時,正好是北京時間和東京時間的時差。這很好理解,北京時間2017-08-24 11:17:10對應的毫秒數是1503544630000,而東京時間2017-08-24 11:17:10對應的北京時間實際上是2017-08-24 10:17:10(由於北京時間比東京時間晚1個小時),北京時間2017-08-24
 10:17:10天然比北京時間2017-08-24 11:17:10少3600000毫秒。

4. 將字符串表示的時間轉換成另外一個時區的時間字符串

綜合以上分析,若是給定一個時間字符串,並告訴你這是某個時區的時間,要將它轉換爲另外一個時區的時間並輸出,正確的作法是:

  1. 將字符串按原時區轉換成Date對象;
  2. 將Date對象格式化成目標時區的時間。

好比,將北京時間"2017-8-24 11:17:10"輸出成東京時間,代碼爲:

String timeStr = "2017-8-24 11:17:10"; // 字面時間  
SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
bjSdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));  
Date date = bjSdf.parse(timeStr);  // 將字符串時間按北京時間解析成Date對象  
  
SimpleDateFormat tokyoSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  // 東京  
tokyoSdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));  // 設置東京時區  
System.out.println("北京時間: " + timeStr +"對應的東京時間爲:"  + tokyoSdf.format(date));

輸出爲: 北京時間:2017-8-24 11:17:10對應的東京時間爲:2017-08-24 12:17:10

相關文章
相關標籤/搜索