27

所以我有需要从字符串转换为日期对象的 iso 日期时间。如何保持日期不将其转换为本地浏览器时区。

new Date('2013-07-18T17:00:00-05:00')
Thu Jul 18 2013 18:00:00 GMT-0400 (EDT)

我想得到

2013 年 7 月 18 日星期四 17:00:00 GMT-0500 (XX)

4

5 回答 5

6

虽然 MomentJS 是一个很棒的库,但它可能无法为每个用例提供解决方案。例如,我的服务器以 UTC 格式提供日期,并且当日期的时间部分未保存在数据库中(因为它无关紧要)时,客户端会收到一个默认时间全为零的字符串 - 午夜 - 并以的偏移量+0000。然后浏览器会根据我的本地时区自动调整,并将时间拉回几个小时,结果是前一天。

MomentJs 也是如此。

一种解决方案是切掉字符串的时间部分,然后按照其他答案中的描述使用 MomentJS。

但是如果 MomentJS 不是一个可行的选择会发生什么,即我已经有很多地方使用 JS 日期并且不想更新这么多代码行?问题是如何首先阻止浏览器根据本地时区转换日期。答案是,当日期是 ISO 格式时,你不能。

但是,没有规定您传递给 JavaScript 的 Date 构造函数的字符串必须是 ISO 格式。如果您只是将-分隔年、月和日的 替换为/,您的浏览器将不会执行任何转换。

就我而言,我只是更改了 Dates 服务器端的格式,问题就解决了,而无需使用 MomentJS 更新所有客户端 JS 日期。

请注意,JavaScript 的 Date 类的 MDN 文档在解析字符串以创建 Date 实例时警告不可预测的浏览器行为。

于 2018-11-08T14:23:54.890 回答
5

您无法更改 Javascript 的这种行为,因为它是 Javascript 工作的唯一简单方式。发生的事情只是 Javascript 查看时间偏移,计算匹配的时间戳,然后向操作系统询问该时间戳在本地时区的表示。这里要理解的关键是,这-05:00不是时区的指示,而只是与 UTC 的偏移。

时区是复杂的野兽,只是武断的政治决定。操作系统提供了在本地时区显示时间的服务,而不是在其他时区显示时间。要做到这一点,你必须考虑到像夏令时这样的事情,这简直就是地狱。

与时间管理一样,解决此问题的唯一体面方法是使用专用库。在 Javascript 中,您会发现Moment.jsMoment.Timezone.js非常有用。

示例http://codepen.io/Xowap/pen/XKpKZb?editors=0010

document.write(moment('2013-07-18T17:00:00-05:00').tz('America/New_York').format('LLL'));

作为奖励,您可以从 Moment.js 获得大量格式化/解析功能。

另请注意,只要您使用 ISO 8601,您的日期就可以精确定位,从而显示在您喜欢的任何时区。换句话说,JS“转换”你的日期并不重要。

于 2016-06-24T09:45:40.237 回答
2

您可以使用Moment.js等库来执行此操作。

请参阅字符串 + 格式解析

http://momentjs.com/docs/#/parsing/string-format/

以下内容应解析您提供的日期,但您可能需要根据需要对其进行修改。

var dateString = "2013-07-18T17:00:00-05:00";

var dateObject = moment(dateString, "YYYY-MM-DDTHH:mm:ssZ").toDate();

或者,请参阅 Moment 的字符串解析器,它看起来像您提供的格式,除了时间的秒数和时区之间的空格。

http://momentjs.com/docs/#/parsing/string/

于 2014-07-02T22:16:58.557 回答
2

这是一个老问题,最近与一个新问题的答案相关联,但现有答案似乎都没有完全解决原始问题。

在许多情况下,在接收到的时区中格式化和显示日期时间字符串的最简单方法是根本不将该字符串转换为Date对象。相反,只需解析日期时间字符串并将这些部分重新组合成所需的格式。例如,如果您可以在问题中请求的输出中没有星期几,您可以执行以下操作来处理请求的输入和输出格式(包括星期几会增加足够的复杂性,可能那时值得使用图书馆)。当然,这种方法需要根据您在客户端收到的日期时间字符串的格式进行修改。

const months = {1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec'};
const format = (datetime) => {
  const [date, time] = datetime.split('T');
  const [y, m, d] = date.match(/\d+/g);
  const [t, tz] = time.split(/(?=[+-])/);
  return `${months[Number(m)]} ${d} ${y} ${t} GMT${tz}`;
};

const dt = format('2013-07-18T17:00:00-05:00');
console.log(dt);
// Jul 18 2013 17:00:00 GMT-05:00

有 JavaScript 和其他库方法可让您将日期时间字符串转换为Date实例,然后在特定时区显示它边。以下是几个例子。

toLocaleString使您能够在特定时区显示日期,但options并非所有浏览器都支持设置时区所需的参数(截至本答案日期)。例如(请注意,Date仍然不鼓励使用构造函数解析日期字符串,但大多数现代浏览器将处理如下所示的 ISO 8601 格式字符串):

const dt = new Date('2013-07-18T17:00:00-05:00');
const ny = dt.toLocaleString('en-US', { timeZone: 'America/New_York' });
console.log(`Local: ${dt}`);
console.log(`New York: ${ny}`);

您还可以使用Moment.jsMoment Timezone来显示特定时区的日期。例如:

const ny = moment('2013-07-18T17:00:00-05:00').tz('America/New_York').format();
console.log(`New York: ${ny}`);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.23/moment-timezone-with-data.min.js"></script>

在 JavaScript 中使用日期时间字符串和时区时,请务必注意以下事项。JavaScriptDate构造函数不会更改时区偏移量。当您使用问题示例中的 ISO 8601 格式从字符串创建日期时,请Date执行以下操作:

创建一个表示单个时间点的 JavaScript Date 实例。Date 对象使用 Unix 时间戳,它是一个整数值,表示自 1970 年 1 月 1 日 UTC 以来的毫秒数。

换句话说,JavaScriptDate实例不存储(或更改)时区偏移量。Date您经常在本地时区看到 JavaScript 输出的原因是,当您将实例toString记录到控制台(或使用各种其他方法来输出您的日期)时调用的默认方法。Date在大多数浏览器实现中,此方法依赖于浏览器的本地时区,将自 1970 年 1 月 1 日 UTC 以来的毫秒数转换为日期的字符串表示形式。

于 2019-03-29T16:06:48.217 回答
0

想知道这是否有帮助:

function goAheadMakeMyDate(s){
  var d = new Date(s);
  // override Date.toString()
  d.toString = function(){ return ''+s; };
  return d;
}

var example = goAheadMakeMyDate("Fri 19 July 2013 12:00:00 GMT");

example.toString() // returns string actually used to construct the date
'Fri 19 July 2013 12:00:00 GMT'

example.toLocaleString()
'Fri Jul 19 2013 08:00:00 GMT-0400 (EDT)'

1*example // gives seconds since epoch
1374235200000

根据您的输入:

example = goAheadMakeMyDate('2013-07-18T17:00:00-05:00')
{ Thu, 18 Jul 2013 22:00:00 GMT toString: [Function] }
> example.toString()
'2013-07-18T17:00:00-05:00'
> example.toLocaleString() // I live in GMT-4
'Thu Jul 18 2013 18:00:00 GMT-0400 (EDT)'
> 1*example  // convert to integer date
1374184800000

但是,如果您开始修改此日期,则 toString不会更改并且会咬您。

于 2013-07-19T17:16:43.270 回答