仅比较日期部分而不比较JavaScript中的时间

mol*_*ezz 364 javascript comparison mootools date

下面的代码有什么问题?

也许比较日期而不是时间会更简单.我不知道怎么做,我搜索,但我找不到我的确切问题.

顺便说一句,当我在警报中显示两个日期时,它们显示完全相同.

我的代码:

window.addEvent('domready', function() {
    var now = new Date();
    var input = $('datum').getValue();
    var dateArray = input.split('/');
    var userMonth = parseInt(dateArray[1])-1;
    var userDate = new Date();
    userDate.setFullYear(dateArray[2], userMonth, dateArray[0], now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds());

    if (userDate > now)
    {
        alert(now + '\n' + userDate);
    }
});
Run Code Online (Sandbox Code Playgroud)

是否有更简单的方法来比较日期而不包括时间?

nex*_*xar 729

我还在学习JavaScript,而且我发现哪种方法可以让我在没有时间的情况下比较两个日期的唯一方法是使用setHoursDate对象的方法并将小时,分钟,秒和毫秒设置为零.然后比较两个日期.

例如,

date1 = new Date()
date2 = new Date(2011,8,20)
Run Code Online (Sandbox Code Playgroud)

date2将小时,分钟,秒和毫秒设置为零,但date1将它们设置为创建date1的时间.要消除date1上的小时,分​​钟,秒和毫秒,请执行以下操作:

date1.setHours(0,0,0,0)
Run Code Online (Sandbox Code Playgroud)

现在,您只需将两个日期作为日期进行比较,而无需担心时间元素.

  • 请注意,`date1 === date2`的测试似乎不能提供一致的行为; 最好做`date1.valueOf()=== b.valueOf()`甚至`date1.getTime()=== date2.getTime()`.陌生感. (53认同)
  • 我知道这是一个老问题,但它在谷歌搜索时首先出现.小心这个答案.如果用户与日期对象的创建者不在同一时区,则会给出错误的答案.例如,将计算机操作系统上的时区更改为东海岸(美国)时间.打开浏览器的控制台,然后输入`var date2 = new Date(2011,8,20)`.现在将操作系统的时区更改为太平洋时间(美国).在同一个浏览器控制台中键入`date2.toDateString()`,你将得到`2011年9月19日星期一`而不是20号星期二! (7认同)
  • 另请注意,`setHours()`根据浏览器自动检测到的当前时区设置时间.尝试:`t = new Date("2016-02-29T01:45:49.098Z");``t.setHours(0,0,0,0);``console.log(t.toJSON()); `将打印'"2016-02-28T15:00:00.000Z"`,日期28,但不是29我当前的时区是`Asia/Tokyo` (7认同)
  • 这个答案确实应该更新为使用`setUTCxxx`方法而不是本地/时区感知变体. (7认同)
  • 注意:如果date1和date2是冬季和夏季,并且你计划使用addDays(1)从一个迭代到另一个,问题是由于夏令时它们不会有相同的时区,所以最后一个比较应该给予相同的日期将无法工作,因为这两个日期实际上不是在00:00:00:0. (4认同)
  • @ErwinWessels使用getTime()来比较Date对象.它们并不意味着可以直接比较. (2认同)

bbs*_*nbb 107

请注意时区

使用日期对象直接表示只是一个日期会让你陷入一个巨大的超额精度问题.您需要管理时间和时区以防止它们出现,并且他们可以在任何步骤中潜入.这个问题的公认答案属于陷阱.

javascript日期没有时区概念.它是一个时刻(自纪元以来的刻度),具有用于转换到字符串和从字符串转换的方便(静态)函数,默认情况下使用设备的"本地"时区,或者,如果指定,则使用UTC或其他时区.要使用日期对象表示日期,您希望日期代表相关日期开始时的UTC午夜.这是一个常见且必要的约定,可让您使用日期,无论其创建的季节或时区如何.因此,在创建午夜UTC日期对象以及序列化时,您需要非常警惕地管理时区的概念.

很多人都对控制台的默认行为感到困惑.如果您向控制台喷涂日期,您看到的输出将包含您的时区.这只是因为控制台会调用toString()您的日期,并toString()为您提供本地代表.基础日期没有时区!(只要时间与时区偏移相匹配,您仍然有午夜UTC日期对象)

反序列化(或创建午夜UTC日期对象)

大多数情况下,您希望您的日期反映用户的时区.点击今天是你的生日.新西兰和美国的用户同时点击并获得不同的日期.在这种情况下,这样做......

// create a date (utc midnight) reflecting the value of myDate and the environment's timezone offset.
new Date(Date.UTC(myDate.getFullYear(),myDate.getMonth(), myDate.getDate()));
Run Code Online (Sandbox Code Playgroud)

有时,国际可比性胜过当地的准确性.在这种情况下,这样做......

// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate()));
Run Code Online (Sandbox Code Playgroud)

反序列化日期

通常,电线上的日期将采用YYYY-MM-DD格式.要反序列化它们,请执行此操作...

var midnightUTCDate = new Date( dateString + 'T00:00:00Z');
Run Code Online (Sandbox Code Playgroud)

序列化

在创建时注意管理时区,现在需要确保在转换回字符串表示时保留时区.所以你可以安全地使用......

  • toISOString()
  • getUTCxxx()
  • getTime() //returns a number with no time or timezone.
  • .toLocaleDateString("fr",{timezone:"UTC"}) // whatever locale you want, but ALWAYS UTC.

完全避免其他一切,特别是......

  • getYear(),getMonth(),getDate()

所以回答你的问题,7年来为时已晚......

<input type="date" onchange="isInPast(event)">
<script>
var isInPast = function(event){
  var userEntered = new Date(event.target.valueAsNumber); // valueAsNumber has no time or timezone!
  var now = new Date();
  var today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() ));
  if(userEntered.getTime() < today.getTime())
    alert("date is past");
  else if(userEntered.getTime() == today.getTime())
    alert("date is today");
  else
    alert("date is future");

}
</script>
Run Code Online (Sandbox Code Playgroud)

看它正在运行......

  • 您的答案包含非常有价值的信息!不幸的是,您实际上并没有将答案添加到OP的实际问题中,从而阻止了我对它的质疑。尝试添加一个回答OP问题的小代码段。 (2认同)
  • 哈哈哈@‘晚了7年’!我喜欢你的风格user1585345!你得到了我的投票! (2认同)

小智 70

这个怎么样?

Date.prototype.withoutTime = function () {
    var d = new Date(this);
    d.setHours(0, 0, 0, 0);
    return d;
}
Run Code Online (Sandbox Code Playgroud)

它允许您比较日期的日期部分,而不会影响变量的值:

var date1 = new Date(2014,1,1);
new Date().withoutTime() > date1.withoutTime(); // true
Run Code Online (Sandbox Code Playgroud)

  • 为什么@andrey.shedko?未经推理而说出某件事是一个坏主意或错误的方式对每个人都不好。如果它有效并且是您在整个项目中重复使用的东西,并且可以节省您重复的手动修剪,那么它就可以正常工作并且很好用。 (4认同)
  • 向原型添加自定义功能并不是一个好主意。 (2认同)

Jos*_*ter 21

使用Moment.js

如果您可以选择包含第三方库,那么绝对值得一看Moment.js.它与工作DateDateTime非常非常容易.

例如,查看一个日期是否在另一个日期之后,但不包括它们的时间,您将执行以下操作:

var date1 = new Date(2016,9,20,12,0,0); // October 20, 2016 12:00:00
var date2 = new Date(2016,9,20,12,1,0); // October 20, 2016 12:01:00

// Comparison including time.
moment(date2).isAfter(date1); // => true

// Comparison excluding time.
moment(date2).isAfter(date1, 'day'); // => false
Run Code Online (Sandbox Code Playgroud)

你传递到第二个参数isAfter是精度做比较,可以是任意的year,month,week,day,hour,minutesecond.

  • 获得了100倍的加速,从momentjs解决方案转移到Date()+ sethours解决方案.细心的朋友:-) (4认同)
  • [Moment 处于维护模式](https://momentjs.com/docs/),如果您尚未使用它,则不应再使用它。还有其他选择,并且日期对象比以前更好。 (2认同)

Rah*_*ahi 12

只需使用.toDateString进行比较,如下所示:

new Date().toDateString();
Run Code Online (Sandbox Code Playgroud)

这将仅返回日期部分而不是时间或时区,如下所示:

"2017年2月3日星期五"

因此,两种日期都可以用这种格式进行比较,同时没有时间的一部分.

  • 这是一个好的开始,但它不允许比较,因为它现在是一个字符串。为了进行比较,通过执行`new Date(new Date().toDateString());`将其改回Date对象 (3认同)
  • @GridTrekkor 是的,但如果您只想快速进行相等测试,这是最简单的解决方案。 (2认同)

Mik*_*man 10

只需在两个日期使用 toDateString() 即可。toDateString 不包括时间,因此对于同一日期的 2 次,值将相等,如下所示。

var d1 = new Date(2019,01,01,1,20)
var d2 = new Date(2019,01,01,2,20)
console.log(d1==d2) // false
console.log(d1.toDateString() == d2.toDateString()) // true
Run Code Online (Sandbox Code Playgroud)

显然,在这个问题的其他地方表达的一些时区问题是有效的,但在许多情况下,这些并不相关。

  • 就我而言,这个解决方案比所选答案和投票较多的答案要好得多。标题中明确指出“无需比较时间”,该解决方案正是这样做的,节省了设置时间来操作比较的需要。要回答“事件 X 和事件 Y 是否在同一天发生”,仅比较日期更有意义,而不是回答“事件 X 的日期的上午 00:00:00.00 是否与 00:00 完全相同:事件 Y 日期的 00:00?” 这就是许多其他回答者正在做的事情 (3认同)

Use*_*ode 8

这可能是一个更简洁的版本,还要注意在使用parseInt时应始终使用基数.

window.addEvent('domready', function() {
    // Create a Date object set to midnight on today's date
    var today = new Date((new Date()).setHours(0, 0, 0, 0)),
    input = $('datum').getValue(),
    dateArray = input.split('/'),
    // Always specify a radix with parseInt(), setting the radix to 10 ensures that
    // the number is interpreted as a decimal.  It is particularly important with
    // dates, if the user had entered '09' for the month and you don't use a
    // radix '09' is interpreted as an octal number and parseInt would return 0, not 9!
    userMonth = parseInt(dateArray[1], 10) - 1,
    // Create a Date object set to midnight on the day the user specified
    userDate = new Date(dateArray[2], userMonth, dateArray[0], 0, 0, 0, 0);

    // Convert date objects to milliseconds and compare
    if(userDate.getTime() > today.getTime())
    {
            alert(today+'\n'+userDate);
    }
});
Run Code Online (Sandbox Code Playgroud)

查看MDC parseInt页面以获取有关基数的更多信息.

JSLint是一个很好的工具,用于捕获丢失的基数和许多其他可能导致模糊和难以调试错误的事情.它迫使您使用更好的编码标准,以避免未来的头痛.我在我编写的每个JavaScript项目中使用它.


rob*_*cat 8

比较日期的有效且正确的方法是:

Math.floor(date1.getTime() / 86400000) > Math.floor(date2.getTime() / 86400000);
Run Code Online (Sandbox Code Playgroud)

它忽略时间部分,它适用于不同的时区,您==也可以比较是否相等。86400000 是一天中的毫秒数 ( = 24*60*60*1000)。

请注意,相等运算符永远不==应该用于比较 Date 对象,因为当您期望相等测试起作用时它会失败,因为它正在比较两个 Date 对象(并且不比较两个日期),例如:

> date1;
outputs: Thu Mar 08 2018 00:00:00 GMT+1300

> date2;
outputs: Thu Mar 08 2018 00:00:00 GMT+1300

> date1 == date2;
outputs: false

> Math.floor(date1.getTime() / 86400000) == Math.floor(date2.getTime() / 86400000);
outputs: true
Run Code Online (Sandbox Code Playgroud)

注意:如果您要比较时间部分设置为零的 Date 对象,那么您可以使用date1.getTime() == date2.getTime(),但几乎不值得优化。直接比较 Date 对象时可以使用<><=、 或 ,>=因为这些运算符在进行比较之前首先通过调用来转换 Date 对象.valueOf()


bri*_*ran 7

如果您真的只比较没有时间组件的日期,另一种可能感觉不对但有效并避免所有Date()时间和时区问题的解决方案是直接使用字符串比较来比较 ISO 字符串日期:

> "2019-04-22" <= "2019-04-23"
true
> "2019-04-22" <= "2019-04-22"
true
> "2019-04-22" <= "2019-04-21"
false
> "2019-04-22" === "2019-04-22"
true
Run Code Online (Sandbox Code Playgroud)

您可以使用以下方法获取当前日期(UTC 日期,不一定是用户的本地日期):

> new Date().toISOString().split("T")[0]
"2019-04-22"
Run Code Online (Sandbox Code Playgroud)

我赞成它的论点是程序员的简单性 - 与尝试正确处理日期时间和偏移相比,您不太可能将其搞砸,这可能会以速度为代价(我没有比较性能)