解释(不转换!)其他时区中的日期在JavaScript /时刻
此问题与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中非常丑陋),然后通过指定该格式来解析它。但是,所有这些字符串转换更像是一种黑客而不是一个适当的解决方案,我真的很想完全摆脱它们,只是告诉时刻“在这里你有一个日期,它应该在这个时区,即使它说这不是“。有没有办法做到这一点?
它可以适合于基于本地日期和用户选择的时间和时区来构建符合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>
显然,这被简化,需要的输入值的验证,但示出的逻辑。您可能还想让用户选择可以使用相同逻辑的日期。
谢谢。这几乎是我最终解决它的方式。它只是丑陋而且会消耗不必要的资源。我希望有更好的方法,但如果没有,至少它是有效的。 – UncleBob
这个答案应该对你有所帮助我相信https://stackoverflow.com/a/23376374/482868 –
马特约翰逊(momentjs“所有者”和日期/时间专家之一)评论我的答案[这里](https:/ /stackoverflow.com/q/45009474/4131048)_实际上,因为输入包含'Z',所以它确实将被视为UTC并且仅用'moment.tz(输入,区域)'_来转换。我认为你的情况相同('date.toISOString()'以'Z'结尾)。我建议解析你的非ISO字符串指定格式和时区。 – VincenzoC