2017-10-17 23 views
1

此問題與Deprecation warning: moment construction falls back to js Date類似,因爲出現相同的警告。但是,這個警告並不是這個問題的焦點,所描述的解決方案並不適合我的用例。我已經編輯了下面的適當段落來解釋爲什麼會這樣。解釋(不轉換!)其他時區中的日期在JavaScript /時刻

考慮一個Web應用程序,用戶可以選擇由固定攝像頭拍攝的圖像的時間範圍。 很明顯,這款相機可能不在他自己的時區。 除此之外,傳遞圖像的REST-API以UTC形式完成所有工作。

我使用的是angular4,moment.js和moment timezone。

因此,他可以選擇是否要在他的本地時區,相機所在時區或UTC中查看帶有時間戳的圖像。到目前爲止,一切都在努力達到這一點。

我遇到麻煩的時候是在設置時間範圍時。顯然,用戶設置的開始時間和結束時間應該被解釋爲處於他選擇顯示的時區,所以我可以在將請求發送到服務器之前將它們轉換爲UTC。 我從日期選擇器(在這種情況下是primeng日曆,但這並不重要)獲取的Date對象當然是在瀏覽器本地時間。

所以我需要做的是取得該日期,並在相機的時區解釋它,而不是將其轉換。因此,如果用戶在UTC時區-2時區設置「從10:00到17:00」,並且攝像機位於UTC + 2,則需要獲取「UTC +2的10:00至17:00」 ,而不是「UTC +2的14:00至21:00」。

我嘗試了幾種方法,其中一些方法甚至可以工作,但每個方法似乎都有自己的注意事項,而且它們都很尷尬,因爲它們會執行不必​​要的字符串轉換。例如:

moment.tz(date.toLocaleString, cameraTimezone) 

這工作,但拋出一個棄用警告:提供

值不是一個公認的RFC2822或ISO格式。時刻建設回落到js Date(),這在所有瀏覽器和版本中都不可靠。

我可以通過指定什麼格式傳遞的日期字符串爲擺脫警告,但我面臨的問題是,無論的toLocaleString()也不是的toString()是一致的。 toLocaleString()顯然會根據語言環境給我另一種格式,toString()會在不同的瀏覽器中產生不同的結果,所以我怎麼知道我得到了什麼?

所以我試圖用正確的格式,但如果我直接使用Date::toIsoString,那一刻我得到已被轉換爲UTC,這不是我所需要的兩種:

let datestring = date.toISOString(); //datestring will be in utc 
const mom = moment.tz(datestring, cameraTimezone); //moment will therefore be the wrong time. 

有創造的明顯的方式我自己的一個Date對象的字符串(在JavaScript中非常醜陋),然後通過指定該格式來解析它。但是,所有這些字符串轉換更像是一種黑客而不是一個適當的解決方案,我真的很想完全擺脫它們,只是告訴時刻「在這裏你有一個日期,它應該在這個時區,即使它說這不是「。有沒有辦法做到這一點?

+0

這個答案應該對你有所幫助我相信https://stackoverflow.com/a/23376374/482868 –

+0

馬特約翰遜(momentjs「所有者」和日期/時間專家之一)評論我的答案[這裏](https:/ /stackoverflow.com/q/45009474/4131048)_實際上,因爲輸入包含'Z',所以它確實將被視爲UTC並且僅用'moment.tz(輸入,區域)'_來轉換。我認爲你的情況相同('date.toISOString()'以'Z'結尾)。我建議解析你的非ISO字符串指定格式和時區。 – VincenzoC

回答

1

它可以適合於基於本地日期和用戶選擇的時間和時區來構建符合ISO 8601的字符串,例如,

window.onload = function() { 
 
    var form = document.getElementById('cameraTimeDetail'); 
 
    form.addEventListener('submit', getPicISO, false); 
 
    
 
} 
 

 
function getPicISO(e) { 
 

 
    // For demo 
 
    e.preventDefault(); 
 

 
    function z(n){return ('0'+n).slice(-2)} 
 
    var date = new Date(); 
 
    var form = this; 
 
    
 
    // Use local date parts 
 
    var s = date.getFullYear() + '-' + 
 
      z(date.getMonth()+1) + '-' + 
 
      z(date.getDate()) + 'T' + 
 
      // Use input timezone and time 
 
      form.pictureTime.value + 
 
      form.cameraTimezone.value; 
 

 
    // Consructed ISO string 
 
    form.timeString.value = (s); 
 
    
 
    // Convert to UTC ISO String 
 
    form.timeStringUTC.value = new Date(s).toISOString(); 
 

 
    return false; 
 
}
input, button { 
 
    width: 15em; 
 
}
<form id="cameraTimeDetail"> 
 
    <table> 
 
    <tr> 
 
     <td>Enter timezone (e.g. -08:00, +05:30) 
 
     <td><input name="cameraTimezone" value="+05:30"> 
 
    <tr> 
 
     <td>Enter time (HH:mm) 
 
     <td><input name="pictureTime" value="14:37"> 
 
    <tr> 
 
     <td><input type="reset"> 
 
     <td><button>Get pic</button> 
 
    <tr> 
 
     <td>Selected date and time: 
 
     <td><input name="timeString" readonly> 
 
    <tr> 
 
     <td>Equivalent UTC: 
 
     <td><input name="timeStringUTC" readonly> 
 
    </table> 
 
</form>

顯然,這被簡化,需要的輸入值的驗證,但示出的邏輯。您可能還想讓用戶選擇可以使用相同邏輯的日期。

+0

謝謝。這幾乎是我最終解決它的方式。它只是醜陋而且會消耗不必要的資源。我希望有更好的方法,但如果沒有,至少它是有效的。 – UncleBob

相關問題