如何使不同時區的時間與京8區一致?(JS實現)


如何使不同時區的時間與京8區一致?(JS實現)

Update:2019/1/28

更簡單的是使用這個函數(toDate):

// 自定義日期格式如下(年月日都必須提供):
// "2011-11-11"
// "2011-11-11 11:11"
// "2011-11-11 11:11:11"
const re_custom = /^(\d{4})-(\d{2})-(\d{2})(?: (\d{2}):(\d{2})(?::(\d{2}))?)?$/;

// iso8601日期格式見:
// http://www.ecma-international.org/ecma-262/5.1/#sec-15.9
const re_iso8601 = /^(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?T(?:(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?)?Z?$/;
const _toString = Object.prototype.toString;

// instanceof Date在跨frame和cypress測試上返回false
function isDate(o) {
  return _toString.call(o) === '[object Date]';
}

function toDate(input) {
  if (!input) {
    return new Date();
  } else if (isDate(input)) {
    return new Date(input);
  } else if (typeof input === 'number') {
    return new Date(input);
  } else if (typeof input === 'string'){
    // 如果是自定義的格式,則用本地時間,
    // 否則,使用原生的構造方法(本地還是UTC看具體實現)。
    let r = re_custom.exec(input);
    if (r) {
      return new Date(~~r[1], ~~r[2]-1, ~~r[3], ~~r[4], ~~r[5], ~~r[6]);
    }

    r = re_iso8601.exec(input);
    if (r) {
      // month/date缺省值為1月/1日
      let month = ~~r[2] - 1;
      if (month < 0) month = 0;
      let date = ~~r[3];
      if (date === 0) date = 1;

      return new Date(Date.UTC(~~r[1], month, date, ~~r[4], ~~r[5], ~~r[6], ~~r[7]));
    }

    return new Date(input);
  }
}

----------------------------分割線-------------------------------

一般而言,我們都以時間戳的方式存儲某個時間。在需要的時候提取出來,根據不同業務需求進行轉化:

function transfromDate(time) {
  // 假設time是時間戳,如:1514273945276
  let curDate = new Data(time);
  // todo
}

這里存在一個潛在問題——改變本機的時區,curDate的值會發生變化!shit!!!

當Date作為構造函數調用並傳入多個參數時,所定義參數代表的是當地時間
MDN

即,構造出的日期用來顯示時,會被轉換為本地時間(調用 toString 方法):

>new Date()
<Tue Dec 26 2017 15:47:50 GMT+0800 (中國標准時間)

GMT AND UTC

GMT+0800是個什么東西呢?我們先來介紹一些可能當年在地理課上學習過的基本概念。

以前人們通過觀察太陽的位置來決定時間(比如:使用日晷),這就使得不同經緯度的地區時間是不一樣的。后來人們進一步規定以子午線為中心,向東西兩側延伸,每 15 度划分一個時區,剛好是 24 個時區。然后因為一天有 24 小時,地球自轉一圈是 360 度,360 度 / 24 小時 = 15 度/小時,所以每差一個時區,時間就差一個小時

GMT:
最開始的標准時間(子午線中心處的時間)是英國倫敦的皇家格林威治天文台的標准時間(因為它剛好在本初子午線經過的地方),這就是我們常說的 GMT(Greenwich Mean Time)。

然后其他各個時區根據標准時間確定自己的時間,往東的時區時間早(表示為 GMT+hh:mm)、往西的時區時間晚(表示為 GMT-hh:mm)。比如,中國標准時間是東八區,我們的時間就總是比 GMT 時間早 8 小時,他們在早晨 9 點,我們才凌晨 1 點。

所以,GMT+0800 表示早於格林威治時間8小時。

UTC:
但是GMT其實是根據地球自轉、公轉計算的(太陽每天經過英國倫敦皇家格林威治天文台的時間為中午 12 點),不是非常准確,於是后面提出了根據原子鍾計算的標准時間 UTC(Coordinated Universal Time)。

一般情況下,GMT 和 UTC 可以互換,但是實際上,GMT 是一個時區,而 UTC 是一個時間標准。

JS使不同時區的時間與京8區一致

要計算不同時區相對於京8區的時間偏差,我們要借助 Javascript 中的 Date 對象的實例方法 getTimezoneOffset():

getTimezoneOffset() 方法返回協調世界時(UTC)相對於當前時區的時間差值,單位為分鍾。
如果本地時區早於協調世界時(UTC),則該差值為負值,如果晚於協調世界時則為正值


東時區 格林威治 西時區
GMT +/- + -
getTimezoneOffset() < 0 > 0
早/晚

完整代碼:

/**
 * 獲取絕對時間
 * 即無論你在哪個時區,得到的時間和京8區的時間一致
 * 
 * @param {Date} time 
 * @returns {years,month, day, hours, minutes, seconds}
 */
function getAbsTime(time) {
  try {
    let currentZoneTime = new Date(time);
    let currentZoneHours = currentZoneTime.getHours();
    let offsetZone = currentZoneTime.getTimezoneOffset() / 60;

    if(offsetZone > 0) {
      // 大於0的是西區(西區晚) 西區應該用時區絕對值加京八區 重新設置時間
      // 西區時間比東區時間晚 所以加時區間隔
      offsetZone = offsetZone + 8;
      currentZoneTime.setHours(currentZoneHours - offsetZone)
    } else {
      // 小於0的是東區(東區早)  東區時間直接跟京八區相加
      offsetZone += 8; 
      currentZoneTime.setHours(currentZoneHours + offsetZone);
    }
    return transfromDate(currentZoneTime)
  } catch(e) {
    throw e
  }
}

部分類容節選自:

https://segmentfault.com/a/1190000004292140
https://www.cnblogs.com/liyunhua/p/4661070.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM