是Javascript日期对象总是一天?

在我的Java脚本应用程序中,我以这样的格式存储日期:

2011-09-24

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

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

日志:

Fri Sep 23 2011 20:00:00 GMT-0400 (Eastern Daylight Time)
283027 次浏览

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

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

它意味着2011-09-24 00:00:00 GMT,由于你在GMT -4,它将是前一天的20:00

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

注意,东部夏令时为-4 hours,返回日期的小时数为20

20h + 4h = 24h

2011年9月24日午夜。日期是UTC (GMT)中的解析,因为您提供了一个只有日期的字符串,没有任何时区指示器。如果你给出了一个日期/时间字符串,没有指示器(new Date("2011-09-24T00:00:00")),它会在你的本地时区被解析。(历史上有不一致的地方,不仅仅是因为规范改变了不止一次,但现代浏览器应该是可以的;或者你总是可以包含一个时区指示器。)

你得到了正确的日期,只是没有指定正确的时区。

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

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

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

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

你的问题是时区。注意GMT-0400部分——也就是你比格林尼治时间晚4个小时。如果在显示的日期/时间上加上4个小时,就会得到2011/09/24的零点。使用toUTCString()方法来获取GMT字符串:

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

如果你想获取本地时区某个日期的0小时,将各个日期部分传递给Date构造函数。

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

规范化日期并消除不需要的偏移量(在这里测试: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 )  );

这个通过我循环,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!

JS 日期对象转换字符串时会发生一些疯狂的的事情,例如考虑你提供的以下日期

下面的例子可能是也可能不是休息一天,这取决于你的时区和当前时间。

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 - 24 t00: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 - 24 - t00: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)

数字,字符串参数的例子。注意,这个月是3月,因为又是以零为基础的月份。

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

如果我们做同样的事情,但是一天是0,我们得到的结果是不同的。

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)

在任何年和月参数中添加0的一天将得到前一个月的最后一天。如果你继续用负数,你可以在另一天继续回滚

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

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

编辑:这不是一个推荐的解决方案,只是一个替代答案。请不要使用这种方法,因为它非常不清楚正在发生什么。有很多种方法可以重构这个不小心导致错误。

虽然在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的另一个奇怪之处:月份是从零开始的。

下面的方法对我很有效

    var doo = new Date("2011-09-24").format("m/d/yyyy");

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

我的应用程序是全球使用utc日期的格式'YYYY-MM-DD',而datepicker插件我只接受js日期,这对我来说很难同时考虑utc和js。所以当我想传递一个'YYYY-MM-DD'格式的日期到我的datepicker,我首先转换为'MM/DD/YYYY'格式使用moment.js或任何你喜欢的,日期显示在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是我想要的。希望这对一些人有所帮助。

处理这个问题的最好方法是不使用更多的转换方法,

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

现在只需在日期中添加GMT或附加它。

 var  mydateNew='2016,3,3'+ 'GMT';
var utcDateNew = Date.parse(mydateNew);
console.log("the right time that you want:"+utcDateNew)

生活:https://jsfiddle.net/gajender/2kop9vrk/1/

您正在使用ISO日期字符串格式,根据这个页面,导致日期使用UTC时区构造:

注意:用date构造函数(和 日期。解析,它们是等效的)是强烈不鼓励的,因为 浏览器差异和不一致。支持RFC 2822格式 字符串只是按照惯例。对ISO 8601格式的支持有所不同 只有日期的字符串(例如:"1970-01-01")被视为UTC,而不是 当地. < / p >

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

我遇到过这样的问题。但我的问题是off set,而从数据库获取日期。

这是在数据库中,它是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);

因此,当日期来自服务器,有服务器偏移量,所以我分割日期和删除服务器偏移量,然后转换为日期。它解决了我的问题。

当我的客户使用大西洋标准时间时,我遇到了这个问题。客户端检索到的日期值是“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>

你的日志输出GMT,所以你要指定你的时区:

var doo = new Date("2011-09-24 EST");

如果你只是想确保日期的各个部分保持不变,即使我改变了时区,这个方法似乎也能奏效:

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

只要把0加进去。

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

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

我在我的电脑上切换时区,日期保持不变,我从API得到的日期字符串yyyy-mm-dd。

但我是不是遗漏了什么/这是个坏主意?

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

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

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

enter image description here

试着在这个帖子中添加我的2分(详细说明@paul-wintz的答案)。

在我看来,当日期构造函数接收到匹配ISO 8601格式(日期部分)的第一部分的字符串时,它会在UTC时区与0时间进行精确的日期转换。当该日期转换为本地时间时,可能会发生日期移位

.如果午夜UTC是本地时区的较早日期
new Date('2020-05-07')
Wed May 06 2020 20:00:00 GMT-0400 (Eastern Daylight Time)

如果日期字符串在任何其他“;松散”中;格式(使用"/"或date/month没有填充为零)它会在本地时区创建日期,因此会出现没有日期转移问题。

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)

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

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

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

new Date(Date.UTC(Year, Month, Day, Hour, Minute, Second))
并且总是建议使用UTC (universal time zone) date而不是date with local time,因为默认情况下日期以UTC存储在Database中。因此,在整个项目中使用和解释UTC格式的日期是一个很好的实践。 例如,< / p >
Date.getUTCYear(), getUTCMonth(), getUTCDay(), getUTCHours()

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

由于大多数答案都很俗气,请允许我提出对我来说非常简单的方法:将脚本的时区设置为UTC

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

有了这个更改,任何时区修改都是无效的,所以只要您不需要跑步者的实际时区,这可能是最简单的解决方法。

您可以使用时刻库格式化日期。 https://momentjs.com/ < / p >

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


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

编辑

时刻现在已弃用,您可以使用date-fns 格式方法来格式化日期。

import { format } from 'date-fns'
format(new Date(), "yyyy-MM-dd")

这解决了我的问题(感谢@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

// When the time zone offset is absent, date-only formats such as '2011-09-24'
// are interpreted as UTC time, however the date object will display the date
// relative to your machine's local time zone, thus producing a one-day-off output.
const date = new Date('2011-09-24');
console.log(date); // Fri Sep 23 2011 17:00:00 GMT-0700 (PDT)
console.log(date.toLocaleDateString('en-US')); // "9/23/2011"
            

// To ensure the date object displays consistently with your input, simply set
// the timeZone parameter to 'UTC' in your options argument.
console.log(date.toLocaleDateString('en-US', { timeZone: 'UTC' })); // "9/24/2011"

要解析ISO日期而不受时区困扰,我的解决方案是添加一个&;t12:00:00&;因为格林威治的中午时分,全世界都在同一天:

function toDate(isoDateString) {
// isoDateString is a string like "yyyy-MM-dd"
return new Date(`${isoDateString}T12:00:00`);
}

之前:

> new Date("2020-10-06")
> Date Mon Oct 05 2020 14:00:00 GMT-1000 (heure normale d’Hawaii - Aléoutiennes)

后:

> toDate("2020-10-06")
> Date Tue Oct 06 2020 12:00:00 GMT-1000 (heure normale d’Hawaii - Aléoutiennes)

使用moment可以在转换为isostring时保持偏移量

let date = moment("2022-03-15").toISOString();
// WRONG OUTPUT 2022-03-14T18:30:00.000Z


let date = moment("2022-03-15").toISOString(true);
// CORRECT OUTPUT 2022-03-15T00:00:00.000+05:30

我只是想就这个问题发表我的意见,因为这篇文章对解决这个问题非常有帮助。我想我没见过这个解决方案,如果我说错了请指正。

正如这里已经提到过无数次的那样,问题主要来自夏季/冬季时间。我注意到in January, the GMT was +1。如果没有设置时间,它将始终是00.00.00(午夜),这将导致前一天的第23小时。

如果你有一个动态日期并且不关心小时,你可以在使用toISOString()之前使用setHours()方法设置小时。

< p >的语法: setHours(hoursValue, minutesValue, secondsValue, msValue)

这意味着:

dynamicDate.setHours(12, 0, 0, 0)
dynamicDate.toISOString()

应该希望为您工作,即使日期提前/后一个小时,它仍然是同一天,现在我们将时间设置为中午。

有关中数上setHours()的更多信息。