Javascript 日期对象总是休息一天吗?
在我的 Javascript 应用程序中,我以如下格式存储日期:
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
您正在使用 ISO 日期字符串格式,根据 此页面,导致使用 UTC 时区构建日期:
如果您以不同的方式设置文本格式,例如
"Jan 01 1970"
,那么(至少在我的计算机上)它会使用您的本地时区。You are using the ISO date string format which, according to this page, causes the date to be constructed using the UTC timezone:
If you format the text differently, such as
"Jan 01 1970"
, then (at least on my machine) it uses your local timezone.以 MySql 日期格式存储
yyyy-mm-dd
您必须执行以下操作:Storing
yyyy-mm-dd
in MySql Date format you must do the following:使用 moment 您可以在转换为 ISOString 时保留 Offset
Using moment you can keep Offset while converting toISOString
以下代码对我有用。首先,我将日期和时间字符串转换为 localeDateString,然后对返回的字符串应用 split 函数。
Following Code worked for me. First I converted to date and time string to localeDateString then apply the split function on the returned string.
您还可以使用 getUTCDate() 来获取正确的日期。
You can also use getUTCDate() to get the correct date.
尝试了多种解决方案。我的建议是将现有日期转换为字符串
接受来自后端的字符串,然后从后端
Convert.ToDateTime(date)
这样,它在所有情况下都适合我,
请尝试这个。
如果你想从 ui 端本身转换
Tried multiple solutions. My suggestion would be convert the existing date to string
accept string from backend and then
Convert.ToDateTime(date)
from backendIn this way it worked well for me in all scenarios,
Please try this.
if your want to convert from ui side itself
转换字符串的 JS DATE 对象会发生几个疯狂的事情,例如考虑您提供的以下日期
如果您向 Date 构造函数提供单独的参数,您可以获得其他有用的输出,如下所述
注意:参数可以是数字或字符串类型。我将展示具有混合值的示例。
There are several crazy things that happen with a JS DATE object that convert strings, for example consider the following date you provided
If you provide separate arguments to the Date constructor you can get other useful outputs as described below
Note: arguments can be of type Number or String. I'll show examples with mixed values.
请注意,东部夏令时间为
-4 小时
,而您返回日期的小时数为20
。这是 2011 年 9 月 24 日午夜。日期是在 UTC (GMT) 中解析,因为您提供了仅日期字符串,没有任何时区指示器。如果您提供了一个不带指示符的日期/时间字符串 (
new Date("2011-09-24T00:00:00")
),则它将在您的本地时区中进行解析。 (从历史上看,那里一直存在不一致的情况,尤其是因为规范多次更改,但现代浏览器应该没问题;或者您始终可以包含时区指示器。)您得到了正确的日期,只是从未指定正确的时间区。
如果您需要访问日期值,可以使用
getUTCDate()
或 任何其他getUTC*()
函数:Notice that Eastern Daylight Time is
-4 hours
and that the hours on the date you're getting back are20
.which is midnight of 2011-09-24. The date was parsed in UTC (GMT) because you provided a date-only string without any time zone indicator. If you had given a date/time string w/o an indicator instead (
new Date("2011-09-24T00:00:00")
), it would have been parsed in your local timezone. (Historically there have been inconsistencies there, not least because the spec changed more than once, but modern browsers should be okay; or you can always include a timezone indicator.)You're getting the right date, you just never specified the correct time zone.
If you need to access the date values, you can use
getUTCDate()
or any of the othergetUTC*()
functions:标准化日期并消除不需要的偏移(此处测试:https://jsfiddle.net/7xp1xL5m/) :
这也完成了相同的任务,并归功于@tpartee(在这里测试:https://jsfiddle.net/7xp1xL5m/1/ ):
To normalize the date and eliminate the unwanted offset (tested here : https://jsfiddle.net/7xp1xL5m/ ):
This also accomplishes the same and credit to @tpartee (tested here : https://jsfiddle.net/7xp1xL5m/1/ ):
我认为这与时区调整有关。您创建的日期采用 GMT,默认时间是午夜,但您的时区是 EDT,因此会减去 4 小时。尝试这样做来验证:
I believe that it has to do with time-zone adjustment. The date you've created is in GMT and the default time is midnight, but your timezone is EDT, so it subtracts 4 hours. Try this to verify:
只是想补充一点,显然在字符串末尾添加空格将使用 UTC 进行创建。
编辑:这不是推荐的解决方案,只是一个替代答案。请不要使用这种方法,因为目前还不清楚发生了什么。有人可以通过多种方式重构此过程,从而意外地导致错误。
Just want to add that apparently adding a space at the end of the string will use UTC for creation.
Edit: This is not a recommended solution, just an alternative answer. Please do not use this approach since it is very unclear what is happening. There are a number of ways someone could refactor this accidentally causing a bug.
如果您想要获取本地时区某个日期的 0 小时,请将各个日期部分传递给
Date
构造函数。If you want to get hour 0 of some date in the local time zone, pass the individual date parts to the
Date
constructor.如果您需要一个简单的解决方案,请参阅:
if you need a simple solution for this see:
您可以将此日期转换为 UTC 日期,
并且始终建议使用 UTC(通用时区)日期而不是使用本地时间的日期,因为默认情况下日期以 UTC 存储在数据库中。因此,在整个项目中使用和解释 UTC 格式的日期是一个很好的做法。
例如,
因此,使用 UTC 日期可以解决与时区问题相关的所有问题。
You can convert this date to UTC date by
And it is always recommended to use UTC (universal time zone) date instead of Date with local time, as by default dates are stored in Database with UTC. So, it is good practice to use and interpret dates in UTC format throughout entire project.
For example,
So, using UTC dates solves all the problem related to timezone issues.
您的问题具体与时区有关。请注意
GMT-0400
部分 - 即您比 GMT 晚 4 小时。如果您在显示的日期/时间上加上 4 小时,您将得到 2011 年 9 月 24 日午夜。使用toUTCString()
方法来获取 GMT 字符串:Your issue is specifically with time zone. Note part
GMT-0400
- that is you're 4 hours behind GMT. If you add 4 hours to the displayed date/time, you'll get exactly midnight 2011/09/24. UsetoUTCString()
method instead to get GMT string:这可能不是一个好的答案,但我只是想分享我对此问题的经验。
我的应用程序全局使用 utc 日期,格式为“YYYY-MM-DD”,而我使用的 datepicker 插件只接受 js 日期,我很难同时考虑 utc 和 js。因此,当我想将“YYYY-MM-DD”格式的日期传递给我的日期选择器时,我首先使用 moment.js 或您喜欢的任何内容将其转换为“MM/DD/YYYY”格式,并且日期选择器上显示的日期现在是正确的。对于你的例子
显然 d1 是我想要的。希望这对某些人有帮助。
This probably is not a good answer, but i just want to share my experience with this issue.
My app is globally use utc date with the format 'YYYY-MM-DD', while the datepicker plugin i use only accept js date, it's hard for me to consider both utc and js. So when i want to pass a 'YYYY-MM-DD' formatted date to my datepicker, i first convert it to 'MM/DD/YYYY' format using moment.js or whatever you like, and the date shows on datepicker is now correct. For your example
Apparently d1 is what i want. Hope this would be helpful for some people.
这通过我循环了一遍,对 zzzBov 的答案+1。以下是使用 UTC 方法对我有用的日期的完整转换:
This through me for a loop, +1 on zzzBov's answer. Here is a full conversion of a date that worked for me using the UTC methods:
当我的客户使用大西洋标准时间时,我遇到了这个确切的问题。客户端检索到的日期值是“2018-11-23”,当代码将其传递到
new Date(“2018-11-23”)
时,输出为客户是前一天的。我创建了一个实用函数,如代码片段中所示,该函数规范了日期,为客户提供了预期的日期。date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
I encountered this exact problem where my client was on Atlantic Standard Time. The date value the client retrieved was "2018-11-23" and when the code passed it into
new Date("2018-11-23")
the output for the client was for the previous day. I created a utility function as shown in the snippet that normalized the date, giving the client the expected date.date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
尽管在OP的情况下,时区是EDT,但不能保证执行脚本的用户将在EDT时区,因此对偏移量进行硬编码不一定有效。我找到的解决方案分割日期字符串并在日期构造函数中使用单独的值。
请注意,您必须考虑 JS 的另一个怪异之处:月份是从零开始的。
Though in the OP's case the timezone is EDT, there's not guarantee the user executing your script will be int he EDT timezone, so hardcoding the offset won't necessarily work. The solution I found splits the date string and uses the separate values in the Date constructor.
Note that you have to account for another piece of JS weirdness: the month is zero-based.
我解析 ISO 日期而不被时区困扰的解决方案是在解析之前在末尾添加一个“T12:00:00”,因为当格林威治中午时,整个世界都在同一天:
之前:
后:
My solution to parse an ISO date without beeing annoyed by the timezone is to add a "T12:00:00" at the end before parsing it, because when it's noon at Greenwich, well the whole world is on the same day :
Before:
After:
它表示
2011-09-24 00:00:00 GMT
,由于您现在处于GMT -4
,因此将为20:00
> 前一天。就我个人而言,我得到的是
2011-09-24 02:00:00
,因为我住在GMT +2
。It means
2011-09-24 00:00:00 GMT
, and since you're atGMT -4
, it will be20:00
the previous day.Personally, I get
2011-09-24 02:00:00
, because I'm living atGMT +2
.您可以使用时刻库来格式化日期。
https://momentjs.com/
编辑
该时刻现已弃用,您可以使用 date-fns format 用于格式化日期的方法。
You can use moment library to format the date.
https://momentjs.com/
EDIT
The moment is now deprecated, you can use date-fns format method for formatting a date.
由于大多数答案都是 hacky,请允许我提出对我有用的非常简单的 hack:将脚本的时区设置为 UTC
通过此更改,任何时区修改都会被抵消,因此只要您不这样做需要跑步者的实际时区,这可能是最简单的解决方法。
As most answers are hacky, allow me to propose my very simple hack that worked for me: Set the script's timezone to UTC
With this change, any timezone modifications are neutralized, so as long as you don't need the runner's actual timezone, this is probably the easiest fix.
如果您只是想确保日期的各个部分出于显示目的保持不变,*即使我更改时区,这似乎也有效:
只需在其中添加零即可。
在我的代码中,我这样做:
然后我在计算机上切换时区,日期与从 API 获取的 yyyy-mm-dd 日期字符串保持不变。
但我错过了什么/这是一个坏主意吗?
*至少在铬合金中。这在 Safari 中不起作用!截至撰写本文时
if you're just looking to make sure the individual parts of the date stay the same for display purposes, *this appears to work, even when I change my timezone:
just add the zeros in there.
In my code I do this:
And I switch around my timezone on my computer and the date stays the same as the yyyy-mm-dd date string I get from the API.
But am I missing something/is this a bad idea ?
*at least in chrome. This Doesn't work in Safari ! as of this writing
处理此问题的最佳方法是在不使用更多转换方法的情况下,
现在只需在日期中添加 GMT,或者您可以附加它。
直播:https://jsfiddle.net/gajender/2kop9vrk/1/
The best way to handle this without using more conversion methods,
Now just add GMT in your date or you can append it.
Live: https://jsfiddle.net/gajender/2kop9vrk/1/
我遇到了这样的问题。但我的问题是从数据库获取日期时的偏移。
这是存储在数据库中的,并且采用 UTC 格式。
因此,当我从数据库获取并检查日期时,它会添加偏移量并发送回javascript。
它添加了+05:00,因为这是我的服务器时区。我的客户位于不同时区 +07:00。
所以这是我对这个问题的解决方案。
因此,当日期来自服务器并具有服务器偏移量时,我会分割日期并删除服务器偏移量,然后转换为日期。它解决了我的问题。
I faced some issue like this. But my issue was the off set while getting date from database.
this is stroed in the database and it is in the UTC format.
So when i get from database and check date it is adding offset with it and send back to javascript.
It is adding +05:00 because this is my server timezone. My client is on different time zone +07:00.
So here is my solution what i do with this issue.
So when date come from the server and have server offset so i split date and remove server offset and then convert to date. It resolves my issue.
试图将我的 2 美分添加到这个帖子中(详细说明@paul-wintz 的答案)。
在我看来,当 Date 构造函数接收到与 ISO 8601 格式的第一部分(日期部分)匹配的字符串时,它会在 UTC 时区中以 0 时间进行精确的日期转换。当该日期转换为当地时间时可能会发生日期变化
如果午夜 UTC 是本地时区中较早的日期。
如果日期字符串采用任何其他“宽松”格式(使用“/”或日期/月份未用零填充),它将在本地时区中创建日期,因此没有日期转换问题。
因此,如上所述,一种快速修复方法是将 ISO 格式的仅日期字符串中的“-”替换为“/”。
Trying to add my 2 cents to this thread (elaborating on @paul-wintz answer).
Seems to me that when Date constructor receives a string that matches first part of ISO 8601 format (date part) it does a precise date conversion in UTC time zone with 0 time. When that date is converted to local time a date shift may occur
if midnight UTC is an earlier date in local time zone.
If the date string is in any other "looser" format (uses "/" or date/month is not padded with zero) it creates the date in local time zone, thus no date shifting issue.
So then one quick fix, as mentioned above, is to replace "-" with "/" in your ISO formatted Date only string.
这解决了我的问题(感谢@Sebastiao 的回答)
This solved my problem (thanks to @Sebastiao answer)
我只想为此付出 2 美分,因为这篇文章对于解决这个问题非常有帮助。我认为我没有看到提到过这个解决方案,如果我错了,请纠正我。
正如这里已经多次提到的,问题主要来自夏季/冬季。我注意到
一月份,GMT 为+1
。如果未设置时间,则始终为 00.00.00(午夜),这将导致前一天的 23 小时继续。如果您有动态日期并且不关心小时,则可以使用
setHours()
方法设置小时,然后再将其与toISOString()
一起使用。句法:
应该希望对您有用,因为即使日期提前/落后一小时,
这意味着:
它仍然是同一天,因为我们将时间设置为中午。
有关 setHours() 的更多信息,请访问 MDN。
I just wanted to give my 2 cents on this, as this post was very helpful to figure out the issue. I don't think I've seen this solution mentioned, correct me if I'm wrong.
As it has been mentioned numerous times already here, the problem comes mainly from summer/winter time. I noticed that
in January, the GMT was +1
. If the time is not set, it will always be 00.00.00 (midnight), which results in going on the 23rd hour of the previous day.If you have a dynamic date and don't care about the hour, you can set the hour using the
setHours()
method before using it withtoISOString()
.syntax:
setHours(hoursValue, minutesValue, secondsValue, msValue)
Which means that:
should hopefully work for you as even if the date is one hour ahead/behind it will still be the same day now that we're setting the hour to be noon.
More about setHours() on MDN.