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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2698725/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 01:30:34  来源:igfitidea点击:

Comparing date part only without comparing time in JavaScript

javascriptdatecomparisonmootools

提问by moleculezz

What is wrong with the code below?

下面的代码有什么问题?

Maybe it would be simpler to just compare date and not time. I am not sure how to do this either, and I searched, but I couldn't find my exact problem.

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

BTW, when I display the two dates in an alert, they show as exactly the same.

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

My code:

我的代码:

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);
    }
});

Is there a simpler way to compare dates and not including the time?

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

回答by nexar

I'm still learning JavaScript, and the only way that I've found which works for me to compare two dates without the time is to use the setHoursmethod of the Date object and set the hours, minutes, seconds and milliseconds to zero. Then compare the two dates.

我仍在学习 JavaScript,我发现唯一可以比较两个没有时间setHours的日期的方法是使用Date 对象的方法并将小时、分钟、秒和毫秒设置为零。然后比较两个日期。

For example,

例如,

date1 = new Date()
date2 = new Date(2011,8,20)

date2will be set with hours, minutes, seconds and milliseconds to zero, but date1 will have them set to the time that date1 was created. To get rid of the hours, minutes, seconds and milliseconds on date1 do the following:

date2将使用小时、分钟、秒和毫秒设置为零,但 date1 会将它们设置为创建 date1 的时间。要去除 date1 上的小时、分钟、秒和毫秒,请执行以下操作:

date1.setHours(0,0,0,0)

Now you can compare the two dates as DATES only without worrying about time elements.

现在您可以仅将两个日期作为 DATES 进行比较,而无需担心时间元素。

回答by bbsimonbb

BEWARE THE TIMEZONE

当心时区

Using the date object to represent just-a-date straight away gets you into a huge excess precision problem. You need to manage time and timezone to keep them out, and they can sneak back in at any step. The accepted answer to this question falls into the trap.

使用 date 对象直接表示刚刚的日期会让你陷入一个巨大的过度精度问题。您需要管理时间和时区以将它们拒之门外,而且它们可以在任何步骤潜入。这个问题的公认答案落入了陷阱。

A javascript date has no notion of timezone. It's a moment in time (ticks since the epoch) with handy (static) functions for translating to and from strings, using by default the "local" timezone of the device, or, if specified, UTC or another timezone. To represent just-a-date™ with a date object, you want your dates to represent UTC midnight at the start of the date in question.This is a common and necessary convention that lets you work with dates regardless of the season or timezone of their creation. So you need to be very vigilant to manage the notion of timezone, both when you create your midnight UTC Date object, and when you serialize it.

javascript 日期没有时区的概念。这是一个及时的时刻(自纪元以来的滴答声),带有方便的(静态)函数来转换字符串和从字符串转换,默认情况下使用设备的“本地”时区,或者,如果指定,UTC 或其他时区。要使用日期对象表示 just-a-date™,您希望您的日期表示相关日期开始时的 UTC 午夜。这是一个常见且必要的约定,可让您处理日期,而不管其创建的季节或时区。因此,无论是在创建午夜 UTC 日期对象时还是在序列化它时,您都需要非常警惕地管理时区的概念。

Lots of folks are confused by the default behaviour of the console. If you spray a date to the console, the output you see will include your timezone. This is just because the console calls toString()on your date, and toString()gives you a local represenation. The underlying date has no timezone! (So long as the time matches the timezone offset, you still have a midnight UTC date object)

许多人对控制台的默认行为感到困惑。如果您向控制台喷洒日期,您看到的输出将包括您的时区。这只是因为控制台会呼叫toString()您的约会对象,并toString()为您提供本地代表。基础日期没有时区!(只要时间与时区偏移量匹配,您仍然有一个午夜 UTC 日期对象)

Deserializing (or creating midnight UTC Date objects)

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

This is the rounding step, with the trick that there are two "right" answers. Most of the time, you will want your date to reflect the timezone of the user. Click if today is your birthday. Users in NZ and US click at the same time and get different dates. In that case, do this...

这是四舍五入的步骤,技巧是有两个“正确”的答案。大多数情况下,您会希望您的日期反映用户的时区。如果今天是您的生日,请单击。新西兰和美国的用户同时点击会得到不同的日期。在这种情况下,这样做...

// 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()));

Sometimes, international comparability trumps local accuracy. In that case, do this...

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

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

Deserialize a date

反序列化日期

Often dates on the wire will be in the format YYYY-MM-DD. To deserialize them, do this...

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

var midnightUTCDate = new Date( dateString + 'T00:00:00Z');

Serializing

序列化

Having taken care to manage timezone when you create, you now need to be sure to keep timezone out when you convert back to a string representation. So you can safely use...

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

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

And totally avoid everything else, especially...

并完全避免其他一切,尤其是...

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

So to answer your question, 7 years too late...

所以回答你的问题,晚了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>

See it running...

看到它运行...

Update 2019... free stuff...

2019 年更新……免费的东西……

Given the popularity of this answer, I've put it all in code. The following function returns a wrapped date object, and only exposes those functions that are safe to use with just-a-date™.

鉴于此答案的受欢迎程度,我已将其全部放入代码中。以下函数返回一个包装的日期对象,并且只公开那些可以安全地与 just-a-date™ 一起使用的函数。

Call it with a Date object and it will resolve to JustADate reflecting the timezone of the user. Call it with a string: if the string is an ISO 8601 with timezone specified, we'll just round off the time part. If timezone is not specified, we'll convert it to a date reflecting the local timezone, just as for date objects.

使用 Date 对象调用它,它将解析为 JustADate 反映用户的时区。用字符串调用它:如果字符串是指定时区的 ISO 8601,我们将把时间部分四舍五入。如果未指定时区,我们会将其转换为反映本地时区的日期,就像日期对象一样。

function JustADate(initDate){
  var utcMidnightDateObj = null
  // if no date supplied, use Now.
  if(!initDate)
    initDate = new Date();

  // if initDate specifies a timezone offset, or is already UTC, just keep the date part, reflecting the date _in that timezone_
  if(typeof initDate === "string" && initDate.match(/((\+|-)\d{2}:\d{2}|Z)$/gm)){  
     utcMidnightDateObj = new Date( initDate.substring(0,10) + 'T00:00:00Z');
  } else {
    // if init date is not already a date object, feed it to the date constructor.
    if(!(initDate instanceof Date))
      initDate = new Date(initDate);
      // Vital Step! Strip time part. Create UTC midnight dateObj according to local timezone.
      utcMidnightDateObj = new Date(Date.UTC(initDate.getFullYear(),initDate.getMonth(), initDate.getDate()));
  }

  return {
    toISOString:()=>utcMidnightDateObj.toISOString(),
    getUTCDate:()=>utcMidnightDateObj.getUTCDate(),
    getUTCDay:()=>utcMidnightDateObj.getUTCDay(),
    getUTCFullYear:()=>utcMidnightDateObj.getUTCFullYear(),
    getUTCMonth:()=>utcMidnightDateObj.getUTCMonth(),
    setUTCDate:(arg)=>utcMidnightDateObj.setUTCDate(arg),
    setUTCFullYear:(arg)=>utcMidnightDateObj.setUTCFullYear(arg),
    setUTCMonth:(arg)=>utcMidnightDateObj.setUTCMonth(arg),
    addDays:(days)=>{
      utcMidnightDateObj.setUTCDate(utcMidnightDateObj.getUTCDate + days)
    },
    toString:()=>utcMidnightDateObj.toString(),
    toLocaleDateString:(locale,options)=>{
      options = options || {};
      options.timezone = "UTC";
      locale = locale || "en-EN";
      return utcMidnightDateObj.toLocaleDateString(locale,options)
    }
  }
}


// if initDate already has a timezone, we'll just use the date part directly
console.log(JustADate('1963-11-22T12:30:00-06:00').toLocaleDateString())

回答by AdEpt

How about this?

这个怎么样?

Date.prototype.withoutTime = function () {
    var d = new Date(this);
    d.setHours(0, 0, 0, 0);
    return d;
}

It allows you to compare the date part of the date like this without affecting the value of your variable:

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

var date1 = new Date(2014,1,1);
new Date().withoutTime() > date1.withoutTime(); // true

回答by Joshua Pinter

Using Moment.js

使用Moment.js

If you have the option of including a third-party library, it's definitely worth taking a look at Moment.js. It makes working with Dateand DateTimemuch, much easier.

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

For example, seeing if one Date comes after another Date but excluding their times, you would do something like this:

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

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

The second parameter you pass into isAfteris the precision to do the comparison and can be any of year, month, week, day, hour, minuteor second.

你传递到第二个参数isAfter是精度做比较,可以是任意的yearmonthweekdayhourminutesecond

回答by Rahi

Simply compare using .toDateString like below:

简单地使用 .toDateString 进行比较,如下所示:

new Date().toDateString();

This will return you date part only and not time or timezone, like this:

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

"Fri Feb 03 2017"

“2017 年 2 月 3 日星期五”

Hence both date can be compared in this format likewise without time part of it.

因此,两个日期都可以以这种格式进行比较,而没有时间部分。

回答by Useless Code

This might be a little cleaner version, also note that you should always use a radix when using parseInt.

这可能是一个更简洁的版本,还要注意在使用 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);
    }
});

Checkout the MDC parseIntpage for more information about the radix.

有关基数的更多信息,请查看 MDC parseInt页面。

JSLintis a great tool for catching things like a missing radix and many other things that can cause obscure and hard to debug errors. It forces you to use better coding standards so you avoid future headaches. I use it on every JavaScript project I code.

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

回答by Diodeus - James MacFarlane

The date.jslibrary is handy for these things. It makes all JS date-related scriping a lot easier.

date.js库是非常方便的这些东西。它使所有与 JS 日期相关的脚本变得更加容易。

回答by brittohalloran

If you are truly comparing date only with no time component, another solution that may feel wrong but works and avoids all Date()time and timezone headaches is to compare the ISO string date directly using string comparison:

如果您真的只比较没有时间组件的日期,另一种可能会感觉错误但有效并避免所有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

You can get the current date (UTC date, not neccesarily the user's local date) using:

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

> new Date().toISOString().split("T")[0]
"2019-04-22"

My argument in favor of it is programmer simplicity -- you're much less likely to botch this than trying to handle datetimes and offsets correctly, probably at the cost of speed (I haven't compared performance)

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

回答by Mike Feltman

Just use toDateString() on both dates. toDateString doesn't include the time, so for 2 times on the same date, the values will be equal, as demonstrated below.

只需在两个日期使用 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

Obviously some of the timezone concerns expressed elsewhere on this question are valid, but in many scenarios, those are not relevant.

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

回答by Max Yari

As I don't see here similar approach, and I'm not enjoying setting h/m/s/ms to 0, as it can cause problems with accurate transition to local time zone with changed dateobject (I presume so), let me introduce here this, written few moments ago, lil function:

因为我在这里没有看到类似的方法,而且我不喜欢将 h/m/s/ms 设置为 0,因为它可能会导致在更改date对象的情况下准确转换到本地时区时出现问题(我认为是这样),让我这里介绍一下这个,刚才写的,lil函数:

+: Easy to use, makes a basic comparison operations done (comparing day, month and year without time.)
-: It seems that this is a complete opposite of "out of the box" thinking.

+: 简单易用,做了一个基本的比较操作(比较没有时间的日月年。)
-: 这似乎与“开箱即用”的想法完全相反。

function datecompare(date1, sign, date2) {
    var day1 = date1.getDate();
    var mon1 = date1.getMonth();
    var year1 = date1.getFullYear();
    var day2 = date2.getDate();
    var mon2 = date2.getMonth();
    var year2 = date2.getFullYear();
    if (sign === '===') {
        if (day1 === day2 && mon1 === mon2 && year1 === year2) return true;
        else return false;
    }
    else if (sign === '>') {
        if (year1 > year2) return true;
        else if (year1 === year2 && mon1 > mon2) return true;
        else if (year1 === year2 && mon1 === mon2 && day1 > day2) return true;
        else return false;
    }    
}

Usage:

用法:

datecompare(date1, '===', date2)for equality check,
datecompare(date1, '>', date2)for greater check,
!datecompare(date1, '>', date2)for less or equal check

datecompare(date1, '===', date2)用于相等检查,
datecompare(date1, '>', date2)用于更大的检查,
!datecompare(date1, '>', date2)用于更少或相等的检查

Also, obviously, you can switch date1and date2in places to achieve any other simple comparison.

此外,很明显,你可以切换date1,并date2在地方实现任何其他简单的比较。