How does date comparison work using . toLocaleDateString();?

Asked

Viewed 216 times

4

It is a doubt that I have some time and I can not find an answer anywhere on the internet (I searched here and on Soen).

given the following code:

var hoje = new Date(2018, 08, 07).toLocaleDateString();
var dataQualquer = '08/05/2018';
if(dataQualquer < hoje) console.log('sucess!');

the ifwill return true due to date being shorter. If I hiss the date by '08/05/2019', still get true. In short: the .toLocaleDateStringconverts a date into a string. You can compare this date to another date string, and it works to a certain extent (disregard the year, but compare day/month).

The question is: How does this work anyway? How does javascript compare two strings and return true or false depending on the value in them? I’m still new to programming compared to most on this site, but I understand that a filled string should be considered a true value, and therefore should always return true. And regardless of that, why compare the days and months but not the years?

I know the question is a long one, but I would really like to know how this process works.

Thank you for your attention in advance.

  • dataQualquer < hoje gives false and not true

  • 2

    It works wrong as it makes no sense to compare dates as string in the proposed format. The only real solution is to forget everything in the question code and start right from scratch. If you are going to use strings, use the YYYYMMDD order and do nothing to convert. If the format is already date, compare as date or numerically (using getTime). If they are 2 different formats, convert to a format that makes sense (or string in the right order, or integer/timestamp)

  • I understand that it works wrong and I know the right way to do it, the question was how the comparison system (>, <, >=, <=) worked between strings. The question of dates was an example in which I came across by chance and used as an example here. But thank you for your attention and attention.

3 answers

5


Strings in Javascript are compared character by character, from left to right until the characters are not equal, or over no other letter to compare.

You can compare sentences:

"a" < "b" // true
"a" < "a" // false
"abc" < "aaa" // falso, porque b é maior que a
"abc" < "abd" // verdadeiro, porque c é menor que d

As well as numbers, although the result is not the same as comparing with numerical types.

"20" < "3" // verdadeiro, porque 2 é menor que 3
"50" > "100" // verdadeiro, porque 5 é maior que 1
"305" < "31" // verdadeiro, porque 1 é maior que 0

This is because strings are compared Lexicographically, giving each character an order that can be compared.

It is possible to compare this date with another date string, and it works to some extent (disregard the year, but compare day/month).

The same happens when comparing two dates in format string:

"21/09/2018" < "21/10/2018" // true porque 0 é menor que 9 (mês)
"21/09/2018" < "31/10/2019" // verdadeiro, porque 3 é maior que 2 (dia)
"21/09/2020" < "31/10/2019" // ainda verdadeiro, porque 3 continua maior que 2 (desconsiderando assim o ano)

Finally, to compare dates, always use two objects of the type Date, and note that to use operators != and == you need to use the method date.getTime();

var data1 = new Date();
var data2 = new Date(data1);

data1 == data2 // false, errado
data1 != data2 // false, errado
data1.getTime() == data2.getTime() // verdadeiro, correto
data1 > data2 // false, correto
data1 >= data2 // true, correto
data1 <= data2 // true, correto
  • 1

    Thank you for the clarification. I know how to make it work, I wanted to understand just why javascript act this way, and how the 'reasoning' of the machine worked in this situation. What I usually do is take today’s date with new Date(); and buy with the current date as follows: var x = '08/05/2018'.split('/'); and then create a new new Date(x[2], x[1], x[0]) to compare.

  • Correct: always convert your date to a "Date" object and directly compare the "Date" object, never strings.

2

The question is: How does this work after all? How does javascript compare two strings and return true or false depending on the value in them?

When comparing two strings "2" > "14", "2" shall be greater than "14" because (in order from left to right) that 2 is greater than 1, and likewise its doubt "Se eu sibstituir a data por '08/05/2019', ainda recebo true", is due as above and explained below.

General rule

To calculate string comparisons, Javascript converts each character of a string with its ASCII value. Each character, starting with the left operator, is compared with the corresponding character in the right operator.

In the following example, note that character 7 is less than 8, so as a general rule, regardless of what comes after character 7 of the left operator and after character 8 of the right operator the expression will always be false.

Note that in your case it is a comparison between two strings.

var hoje = new Date(2018, 08, 07).toLocaleDateString();
console.log(typeof hoje); //string

var dataQualquer = '08/05/2018';
console.log(typeof dataQualquer); //string

console.log(hoje);        // 07/09/2018
console.log(dataQualquer); //08/05/2018

if (dataQualquer<hoje){
  console.log("verdadeiro");
}else{
  console.log("falso");  //8 não é menor que 7
}

Note that Javascript does not compare 7 to 8, but its ASCII values

7 corresponde a 055 em ASCII
8 corresponde a 056 em ASCII

NOTE: for numerical values, the results are equal to what you would expect from your school algebra classes.

facil right? For numeric characters the ASCII values start with 0 (048) and end with 9 (057).

So

           | cada centena representa o valor ASCII de cada caractere
07/09/2018 | 048 055 047 048 057 047 050 048 049 056
08/05/2018 | 048 056 047 048 053 047 050 048 049 056
                 ---

For alphabetic characters it is not that easy, see the example below

    if ("mateus" < "Mateus"){
       console.log("verdadeiro");
    }else{
       console.log("falso");
    }

mateus | 109 097 116 101 117 115
Mateus | 077 097 116 101 117 115
         ---

ASCII values for uppercase letters are smaller than the corresponding ones in minuscule letters.

One of the various solutions, for your case, is to use the order YEAR MONTH DAY

var hoje = new Date(2018, 08, 07).toLocaleDateString();
var dataQualquer = '08/05/2018';

 hoje = hoje.split("/").reverse().join("-"); //2018-09-07
 dataQualquer = dataQualquer.split("/").reverse().join("-"); // 2018-05-08
        

     if (dataQualquer<hoje){
       console.log("verdadeiro");
     }else{
       console.log("falso"); 
     }

 2018-09-07  | 050 048 049 056 045 048 057 045 048 055
 2018-05-08  | 050 048 049 056 045 048 053 045 048 056
                                       ---
  • Thank you for showing me a way to make it work with strings, even though I have no reason to do so. Very good answer, I would like to be able to choose two answers at the same time.

  • Opa @Máttheusspoo, I thought to understand how Javascript really makes comparison. The best answer was from @Baccowho preferred only to comment.

  • Actually no, he proposed a solution to the presented code, but did not answer what I asked. What I asked was what you answered, how javascript compares strings. I know the code in the question is wrong and I know how to solve it.

  • @Máttheusspoo understood and I’m glad I helped.

1

Unfortunately javascript does not have native support (but why?) for comparisons between dates, as @Vinícius mentioned: strings are compared one by one and in order to get differences between dates you would have to use the javascript Date() object (which takes a lot of work from the handle).

There are also some techniques assembled by developers around the world. Take a look if interest.

Personally I would recommend the Moment.js. In this link there are also some examples explaining how to use Moment.js correctly and some features of javascript dates.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.