Javascript日期对象总是休息一天吗?

lev*_*evi 205 javascript date

在我的Java Script应用程序中,我将日期存储为如下格式:

2011-09-24
Run Code Online (Sandbox Code Playgroud)

现在,当我尝试使用上面的值来创建一个新的Date对象(所以我可以以不同的格式检索日期)时,日期总会在一天后返回.见下文:

var doo = new Date("2011-09-24");
console.log(doo);
Run Code Online (Sandbox Code Playgroud)

日志:

Fri Sep 23 2011 20:00:00 GMT-0400 (Eastern Daylight Time)
Run Code Online (Sandbox Code Playgroud)

SoE*_*zPz 217

几个疯狂与一个JS发生的事情DATE该字符串转换对象,例如考虑以下日期你提供

注意:以下示例可能是也可能不是一天关闭,具体取决于您的时区和当前时间.

new Date("2011-09-24"); // Year-Month-Day
// => Fri Sep 23 2011 17:00:00 GMT-0700 (MST) - ONE DAY OFF.
Run Code Online (Sandbox Code Playgroud)

但是,如果我们将字符串格式重新排列为Month-Day-Year ...

new Date("09-24-2011");
=> // Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.
Run Code Online (Sandbox Code Playgroud)

另一个奇怪的

new Date("2011-09-24");
// => Fri Sep 23 2011 17:00:00 GMT-0700 (MST) - ONE DAY OFF AS BEFORE.

new Date("2011/09/24"); // change from "-" to "/".
=> // Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.
Run Code Online (Sandbox Code Playgroud)

我们可以在创建新日期时轻松更改日期"2011-09-24"中的连字符

new Date("2011-09-24".replace(/-/g, '\/')); // => "2011/09/24".
=> // Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.
Run Code Online (Sandbox Code Playgroud)

如果我们有一个像"2011-09-24T00:00:00"这样的日期字符串怎么办

new Date("2011-09-24T00:00:00");
// => Fri Sep 23 2011 17:00:00 GMT-0700 (MST) - ONE DAY OFF.
Run Code Online (Sandbox Code Playgroud)

现在改变连字符以像以前一样转发斜线 ; 怎么了?

new Date("2011/09/24T00:00:00");
// => Invalid Date
Run Code Online (Sandbox Code Playgroud)

我通常需要管理日期格式2011-09-24T00:00:00所以这就是我的工作.

new Date("2011-09-24T00:00:00".replace(/-/g, '\/').replace(/T.+/, ''));
// => Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.
Run Code Online (Sandbox Code Playgroud)

UPDATE

如果为Date构造函数提供单独的参数,则可以获得其他有用的输出,如下所述

注意:参数可以是Number或String类型.我将展示具有混合值的示例.

获取给定年份的第一个月和第一天

new Date(2011, 0); // Normal behavior as months in this case are zero based.
=> // Sat Jan 01 2011 00:00:00 GMT-0700 (MST)
Run Code Online (Sandbox Code Playgroud)

获取一年中的最后一个月和一天

new Date((2011 + 1), 0, 0); // The second zero roles back one day into the previous month's last day.
=> // Sat Dec 31 2011 00:00:00 GMT-0700 (MST)
Run Code Online (Sandbox Code Playgroud)

Number,String参数的示例.请注意,月份是3月,因为再次为零.

new Date(2011, "02"); 
=> // Tue Mar 01 2011 00:00:00 GMT-0700 (MST)
Run Code Online (Sandbox Code Playgroud)

如果我们做同样的事情但是一天零,我们会得到不同的东西.

new Date(2011, "02", 0); // again the zero roles back from March to the last day of February.
=> // Mon Feb 28 2011 00:00:00 GMT-0700 (MST)
Run Code Online (Sandbox Code Playgroud)

在任何年份和月份参数中添加零日将获得上个月的最后一天.如果您继续使用负数,您可以继续回滚另一天

new Date(2011, "02", -1);
=> // Sun Feb 27 2011 00:00:00 GMT-0700 (MST)
Run Code Online (Sandbox Code Playgroud)

  • 哇 - javascript非常不一致. (53认同)
  • 所有这一切都是由于基础Date.parse()试图遵循ISO 8601的行为.当日期字符串遵循yyyy-mm-dd格式时,它假定为ISO 8601,隐式UTC为00:00.当字符串偏离格式(例如mm-dd-yyyy或斜线而不是连字符)时,它会根据RFC 2822回退到更宽松的解析器,RFC 2822在没有时区时使用本地时间.不可否认,这对普通人来说都是非常神秘的. (18认同)
  • 这实际上帮助了我最好的.当我创建一个新日期时,我刚刚将.replace(/ - /g,'\ /').replace(/ T.+ /,'')添加到我的数据末尾.超级简单! (10认同)
  • 今天晚上,.replace()电话确实得到了帮助. (2认同)
  • 是的,我已经测试了这一切,它真的很奇怪. (2认同)
  • 但不是给我们!这个评论是一个很好的补充.我不知道为什么会这样做,就是这样. (2认同)
  • 哇。我一直在绞尽脑汁地想为什么我的 JS 日期是错误的日期,结果发现这只是因为 yyy-MM-dd 格式。好在 HTML5 日期输入必须采用 yyy-MM-dd 格式...谢谢您的解释! (2认同)
  • 哦 - 还有 - JS 会解决这个问题吗?使用连字符而不是斜线会导致行为改变,这太奇怪了。 (2认同)

zzz*_*Bov 86

请注意,东部夏令时是-4 hours您回来之日的时间20.

20h + 4h = 24h
Run Code Online (Sandbox Code Playgroud)

这是2011-09-24的午夜.

你得到了正确的约会,你从未指定过正确的时区.

如果您需要访问日期值,您可以使用getUTCDate()任何其他getUTC*()功能:

var d,
    days;
d = new Date('2011-09-24');
days = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'];
console.log(days[d.getUTCDay()]);
Run Code Online (Sandbox Code Playgroud)

  • 你如何"指定正确的时区"?日期构造函数始终将日期字符串解释为UTC,但随后调整时区.我甚至可以做'新日期('2012-01-02 EDT')并且仍然将其移回前一天,因为应用了夏令时的偏移,这没有任何意义,因为如果我告诉你这是按照日期EDT的当前本地时区,然后不对其应用额外的偏移.我告诉它时区是EDT,但它仍然适用**额外的**偏移,将其移回一天. (19认同)
  • @AaronLS,如果你被迫使用`get*`方法并且需要它来返回正确的日期/时间,包括未知的时区偏移,只需添加未知的时区偏移:`d = new Date('2013-01 -08 GMT'); d.setMinutes(d.getMinutes()+ d.getTimezoneOffset());`这会将日期规范化为用户的语言环境,以便`.get*`方法返回预期的值.`.getUTC*`方法将是不正确的,所以要小心. (6认同)
  • @AaronLS,“EDT”是[夏令时](http://en.wikipedia.org/wiki/Daylight_ saving_time),“EST”是一月份适用的时区。 (2认同)
  • 我想做的就是从字符串中将其创建为 UTC,因此我问“如何“指定正确的时区”?” 关于您所说的“您只是从未指定正确的时区。”。如果我执行“new Date('2012-01-01 GMT')”,它仍然会应用偏移量,因为它将其转换为用户的本地日期时间。 (2认同)
  • 这些评论中的许多都做出了一个巨大的假设,即使用了我们创建的日期。如果像我一样,您从其他来源获取日期,例如使用 dd-mmm-yy 格式的 oracle,该怎么办。我也不知道他们将来是否打算更改这种格式,因为他们的应用程序很旧,如果手动处理可能会破坏我的程序,因此我需要一个通用转换器。如果没有在解析期间指定本地时区的机制,这种 UTC 日期假设同样糟糕。对我来说,问题仍然存在。我如何确保在解析过程中日期没有改变 (2认同)

Aar*_*nLS 67

规范化日期并消除不需要的偏移量(在此测试:https://jsfiddle.net/7xp1xL5m/):

var doo = new Date("2011-09-24");
console.log(  new Date( doo.getTime() + Math.abs(doo.getTimezoneOffset()*60000) )  );
// Output: Sat Sep 24 2011 00:00:00 GMT-0400 (Eastern Daylight Time)
Run Code Online (Sandbox Code Playgroud)

这也完成了相同的功能并归功于@tpartee(在此测试:https://jsfiddle.net/7xp1xL5m/1/ ):

var doo = new Date("2011-09-24");
console.log( new Date( doo.getTime() - doo.getTimezoneOffset() * -60000 )  );
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用,除了我必须减去 timeZoneOffset,而不是添加它 (3认同)
  • @AaronLS你在正确的轨道上,但逻辑略有错误.为了补偿TZ偏移,正确的逻辑是:console.log(new Date(doo.getTime() - doo.getTimezoneOffset()*-60000)); - 偏移的符号很重要,不能绝对消失,但你还需要反转符号进行修正,所以我们将偏移乘以-60000,以便应用反转符号. (2认同)

lin*_*lnk 25

如果要在本地时区中获取某个日期的小时0,请将各个日期部分传递给Date构造函数.

new Date(2011,08,24); // month value is 0 based, others are 1 based.
Run Code Online (Sandbox Code Playgroud)


Kyl*_*der 24

只是想补充一点,显然在字符串末尾添加一个空格将使用UTC进行创建.

new Date("2016-07-06")
> Tue Jul 05 2016 17:00:00 GMT-0700 (Pacific Daylight Time)

new Date("2016-07-06 ")
> Wed Jul 06 2016 00:00:00 GMT-0700 (Pacific Daylight Time)
Run Code Online (Sandbox Code Playgroud)

编辑:这不是推荐的解决方案,只是一个替代答案.请不要使用这种方法,因为很不清楚发生了什么.有很多方法可以让人意外地重构这个错误.

  • 效果很好!new Date(data.Date+ " ").toLocaleDateString("en-US") (2认同)
  • 这在Firefox中不再起作用。 (2认同)

Fis*_*rdo 21

我认为这与时区调整有关.您创建的日期是GMT,默认时间是午夜,但您的时区是EDT,因此减去4小时.试试这个来验证:

var doo = new Date("2011-09-25 EDT");
Run Code Online (Sandbox Code Playgroud)

  • 这是最好的答案。+1百万用于使用内置时区本地化字符串而不是通过编程方式进行转换。 (2认同)
  • 这个有帮助。它是这样工作的:$scope.dat = new Date(datestring + 'EDT')。请注意 EDT 和 EST 之间的区别:[link](/sf/ask/1851725851/) (2认同)

小智 12

如果您需要一个简单的解决方案,请参阅:

new Date('1993-01-20'.split('-')); 
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

  • 这**不适用于 Safari。 (2认同)

Ale*_*s G 11

您的问题特别针对时区.注意部分GMT-0400- 那是你比GMT落后4小时.如果您将4小时添加到显示的日期/时间,您将获得2011/09/24的午夜时间.使用toUTCString()方法来获取GMT字符串:

var doo = new Date("2011-09-24");
console.log(doo.toUTCString());
Run Code Online (Sandbox Code Playgroud)


小智 8

这可能不是一个好的答案,但我只想分享我在这个问题上的经验。

我的应用程序在全球范围内使用格式为 'YYYY-MM-DD' 的 utc 日期,而我使用的 datepicker 插件只接受 js 日期,我很难同时考虑 utc 和 js。因此,当我想将 'YYYY-MM-DD' 格式的日期传递给我的日期选择器时,我首先使用 moment.js 或您喜欢的任何格式将其转换为 'MM/DD/YYYY' 格式,日期选择器上显示的日期是现在正确的。对于你的例子

var d = new Date('2011-09-24'); // d will be 'Fri Sep 23 2011 20:00:00 GMT-0400 (EDT)' for my lacale
var d1 = new Date('09/24/2011'); // d1 will be 'Sat Sep 24 2011 00:00:00 GMT-0400 (EDT)' for my lacale
Run Code Online (Sandbox Code Playgroud)

显然 d1 是我想要的。希望这对某些人有帮助。


Akh*_*ani 6

您可以通过以下方式将此日期转换为 UTC 日期

new Date(Date.UTC(Year, Month, Day, Hour, Minute, Second))
Run Code Online (Sandbox Code Playgroud)

并且始终建议使用 UTC(通用时区)日期而不是 Date 与本地时间,因为默认情况下日期与 UTC 一起存储在数据库中。因此,在整个项目中使用和解释 UTC 格式的日期是一种很好的做法。例如,

Date.getUTCYear(), getUTCMonth(), getUTCDay(), getUTCHours()
Run Code Online (Sandbox Code Playgroud)

因此,使用 UTC 日期可以解决与时区问题相关的所有问题。


cma*_*tin 5

这是通过我循环,在zzzBov的答案+1.以下是使用UTC方法为我工作的日期的完整转换:

//myMeeting.MeetingDate = '2015-01-30T00:00:00'

var myDate = new Date(myMeeting.MeetingDate);
//convert to JavaScript date format
//returns date of 'Thu Jan 29 2015 19:00:00 GMT-0500 (Eastern Standard Time)' <-- One Day Off!

myDate = new Date(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate());
//returns date of 'Fri Jan 30 2015 00:00:00 GMT-0500 (Eastern Standard Time)' <-- Correct Date!
Run Code Online (Sandbox Code Playgroud)


Bri*_*isk 5

尽管在OP的情况下,时区是EDT,但不能保证执行脚本的用户将在EDT时区,因此对偏移量进行硬编码不一定有效。我找到的解决方案分割日期字符串并在日期构造函数中使用单独的值。

var dateString = "2011-09-24";
var dateParts = dateString.split("-");
var date = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
Run Code Online (Sandbox Code Playgroud)

请注意,您必须考虑 JS 的另一个怪异之处:月份是从零开始的。


Gab*_*tes 5

当我的客户使用大西洋标准时间时,我遇到了这个确切的问题。客户端检索到的日期值是“2018-11-23”,当代码将其传递到new Date("2018-11-23")客户端的输出时,该日期值是前一天的。我创建了一个实用函数,如代码片段中所示,该函数规范了日期,为客户提供了预期的日期。

date.setMinutes(date.getMinutes() + date.getTimezoneOffset());

var normalizeDate = function(date) {
  date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
  return date;
};

var date = new Date("2018-11-23");

document.getElementById("default").textContent = date;
document.getElementById("normalized").textContent = normalizeDate(date);
Run Code Online (Sandbox Code Playgroud)
<h2>Calling new Date("2018-11-23")</h2>
<div>
  <label><b>Default</b> : </label>
  <span id="default"></span>
</div>
<hr>
<div>
  <label><b>Normalized</b> : </label>
  <span id="normalized"></span>
</div>
Run Code Online (Sandbox Code Playgroud)