停止javascript日期函数更改时区偏移量

Stop javascript Date function from changing timezone offset

本文关键字:时区 偏移量 函数 javascript 日期 停止      更新时间:2023-09-26

所以我有一个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)

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

MomentJs也是如此。

一种解决方案是分割字符串的时间部分,然后使用MomentJS,如其他答案中所述。

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

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

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

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

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

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

和往常一样,解决这个问题的唯一好方法是使用专用的图书馆。在Javascript中,您会发现Moment.js和Moment.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"转换"你的日期并不重要。

您可以使用Moment.js之类的库来完成此操作。

请参阅字符串+格式解析

http://momentjs.com/docs/#/parsing/string-格式/

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

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/

这是一个旧问题,最近被链接到一个新问题的答案中,但现有的答案似乎都不能完全解决原始问题。

在许多情况下,在接收的时区中格式化和显示日期时间字符串的最简单方法是根本不将字符串转换为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.js与Moment时区一起使用,以显示特定时区中的日期。例如:

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中处理日期时间字符串和时区时,需要注意以下几点,这一点非常重要。JavaScript Date构造函数不会更改时区偏移量。当您使用ISO 8601格式从字符串创建日期时,如问题示例中所示,Date会执行以下操作:

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

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

不知道这是否有帮助:

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将而不是更改,并且会咬到您。

我有一个场景,其中日期时间戳只需要更新一次。详细地说,我的应用程序中有一个按钮,当点击它时,它将生成一个PDF和时间戳页脚,当刷新时,它不应该更改日期时间。

对于上面的场景,我使用了localStorage.setItem('','')和getItems。确切地说。。。。当点击生成按钮时,我使用了localStorage.setItem('',''),在生成页脚逻辑中,我使用localStorage.getItem('')来进行数据…

以上逻辑的解释:

  1. 每当我们生成时,我都会设置当前日期时间,生成时调用getItem,它将从本地存储中选择设置的日期时间
  2. 单击"生成"按钮时,此项将再次重置

希望这能帮助到有需要的人……:-)