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

时间:2011-09-26 14:23:08

标签: javascript date

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

2011-09-24

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

var doo = new Date("2011-09-24");
console.log(doo);

日志:

Fri Sep 23 2011 20:00:00 GMT-0400 (Eastern Daylight Time)

25 个答案:

答案 0 :(得分:189)

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

  

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

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

但是,如果我们将字符串格式重新排列为月 - 日 - 年 ......

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

另一个奇怪的人

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.
  

我们可以在制作新日期时轻松更改日期“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.
  

如果我们的日期字符串如“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.
  

现在像以前一样将连字符更改为正斜杠;会发生什么?

new Date("2011/09/24T00:00:00");
// => Invalid Date
  

我通常必须管理日期格式 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.
  

<强>更新

如果为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)
  

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

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)
  

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

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

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

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)
  

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

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

答案 1 :(得分:84)

请注意,东部夏令时为-4 hours,而您返回日期的时间为20

20h + 4h = 24h

是2011-09-24的午夜。

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

如果您需要访问日期值,可以使用getUTCDate()any of the other getUTC*() functions

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

答案 2 :(得分:64)

标准化日期并消除不需要的偏移(在此测试: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)

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

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

答案 3 :(得分:25)

如果您想在当地时区获得某个日期的0小时,请将各个日期部分传递给Date构造函数。

new Date(2011,08,24); // month value is 0 based, others are 1 based.

答案 4 :(得分:23)

只是想补充一点,显然在字符串末尾添加一个空格将使用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)

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

答案 5 :(得分:16)

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

var doo = new Date("2011-09-25 EDT");

答案 6 :(得分:11)

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

var doo = new Date("2011-09-24");
console.log(doo.toUTCString());

答案 7 :(得分: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!

答案 8 :(得分:4)

这意味着2011-09-24 00:00:00 GMT,因为您位于GMT -4,前一天将是20:00

就个人而言,我得到2011-09-24 02:00:00,因为我住在GMT +2

答案 9 :(得分:4)

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

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

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

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

答案 10 :(得分:4)

您可以将此日期转换为UTC日期

new Date(Date.UTC(Year, Month, Day, Hour, Minute, Second))

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

Date.getUTCYear(), getUTCMonth(), getUTCDay(), getUTCHours()

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

答案 11 :(得分:4)

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

new Date('1993-01-20'.split('-')); 

enter image description here

答案 12 :(得分:2)

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

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

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

答案 13 :(得分:1)

在不使用更多转换方法的情况下处理此问题的最佳方法,

<rewrite>
        <rules>
            <rule name="apple_json_file">
                <match url="^apple-app-site-association" />
                <action type="Rewrite" url="apple-app-site-association.json" />

            </rule>
        </rules>
    </rewrite>

现在只需在您的日期添加GMT,或者您可以追加它。

 var mydate='2016,3,3';
 var utcDate = Date.parse(mydate);
 console.log(" You're getting back are 20.  20h + 4h = 24h :: "+utcDate);

直播:https://jsfiddle.net/gajender/2kop9vrk/1/

答案 14 :(得分:1)

尝试将我的2美分添加到该线程中(详细说明@ paul-wintz答案)。

在我看来,当Date构造函数接收到与ISO 8601格式的第一部分(日期部分)匹配的字符串时,它将在UTC时区中以0时间进行精确的日期转换。该日期转换为当地时间后,日期可能会发生变化 如果午夜UTC是本地时区的较早日期。

new Date('2020-05-07')
Wed May 06 2020 20:00:00 GMT-0400 (Eastern Daylight Time)

如果日期字符串采用任何其他“更宽松”的格式(使用“ /”或日期/月份未填充零),则会在本地时区创建日期,因此不会出现日期转换问题。

new Date('2020/05/07')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
new Date('2020-5-07')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
new Date('2020-5-7')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
new Date('2020-05-7')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)

因此,如上所述,一种快速的解决方法是将ISO格式的“仅日期”字符串中的“-”替换为“ /”。

new Date('2020-05-07'.replace('-','/'))
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)

答案 15 :(得分:1)

如果您只是要确保日期的各个部分保持一致以进行显示,*即使我更改了时区,这似乎也可行:

var doo = new Date("2011-09-24 00:00:00")

只需在其中添加零即可。

在我的代码中,我这样做:

let dateForDisplayToUser = 
  new Date( `${YYYYMMDDdateStringSeparatedByHyphensFromAPI} 00:00:00` )
  .toLocaleDateString( 
    'en-GB', 
    { day: 'numeric', month: 'short', year: 'numeric' }
  )

然后我在计算机上切换时区,并且日期与从API获取的yyyy-mm-dd日期字符串相同。

但是我错过了什么吗/这是个坏主意吗?

*至少在chrome中。这在Safari中不起作用!在撰写本文时

答案 16 :(得分:1)

我遇到了这样的问题。但是我的问题是从数据库获取日期时出现偏移。

它存储在数据库中,并且采用UTC格式。

  

2019-03-29 19:00:00.0000000 +00:00

因此,当我从数据库中获取日期并检查日期时,它会添加偏移量并发送回javascript。

enter image description here

正在添加+05:00,因为这是我的服务器时区。我的客户所在的时区是+07:00。

  

2019-03-28T19:00:00 + 05:00 //这就是我在javascript中得到的东西。

这是我的解决方案,我将如何处理此问题。

var dates = price.deliveryDate.split(/-|T|:/);
var expDate = new Date(dates[0], dates[1] - 1, dates[2], dates[3], dates[4]);
var expirationDate = new Date(expDate);

因此,当日期来自服务器且具有服务器偏移量时,我将拆分日期并删除服务器偏移量,然后转换为日期。它解决了我的问题。

答案 17 :(得分:0)

我的客户在大西洋标准时间遇到了这个确切的问题。客户端检索的日期值为“ 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);
<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>

答案 18 :(得分:0)

您使用的是ISO日期字符串格式,根据this page,该格式导致使用UTC时区构造日期:

  

注意:使用Date构造函数解析日期字符串(和   强烈建议不要使用Date.parse,它们等效)   浏览器的差异和不一致之处。支持RFC 2822格式   字符串仅按照惯例。对ISO 8601格式的支持在以下方面有所不同   仅日期的字符串(例如“ 1970-01-01”)被视为UTC,而不是   本地的。

如果您以不同的格式设置文本,例如"Jan 01 1970",则(至少在我的机器上)它将使用您的本地时区。

答案 19 :(得分:0)

以MySql Date格式存储yyyy-mm-dd时,您必须执行以下操作:

const newDate = new Date( yourDate.getTime() + Math.abs(yourDate.getTimezoneOffset()*60000) );
console.log(newDate.toJSON().slice(0, 10)); // yyyy-mm-dd

答案 20 :(得分:0)

由于大多数答案都是 hacky,请允许我提出对我有用的非常简单的 hack:将脚本的时区设置为 UTC

process.env.TZ = 'UTC' // this has to be run before any use of dates

通过此更改,任何时区修改都将无效,因此只要您不需要跑步者的实际时区,这可能是最简单的解决方法。

答案 21 :(得分:0)

您可以使用矩库来格式化日期。 https://momentjs.com/

let format1 = "YYYY-MM-DD"
let date = new Date();

console.log(moment(date).format(format1))

答案 22 :(得分:0)

这解决了我的问题(感谢@Sebastiao 的回答)

var date = new Date();
//"Thu Jun 10 2021 18:46:00 GMT+0200 (Eastern European Standard Time)"

date.toString().split(/\+|-/)[0] ;  // .split(/\+|-/) is a regex for matching + or -
//"Thu Jun 10 2021 18:46:00 GMT"

var date_string_as_Y_M_D = (new Date(date)).toISOString().split('T')[0];
//2021-06-10

答案 23 :(得分:-1)

您的日志输出GMT,因此您想指定时区:

page

答案 24 :(得分:-3)

没关系,没注意到GMT -0400,导致日期是昨天

您可以尝试将默认“时间”设置为12:00:00