Home > database >  Same date format between MongoDB and JS but they are not equal?
Same date format between MongoDB and JS but they are not equal?

Time:01-19

I'm trying to do an action when the date today (via Node.js) and the date value (via MongoDB) is the same. However, I'm not receiving any output from my for loop indicating that there's no match.

Here's how I get the date today (date output is 2023-01-19T00:00:00.000Z):

const d = new Date(new Date().toLocaleString("en-US", { timeZone: "Asia/Hong_Kong" }));
const day = d.getDate();
const month = d.getMonth()   1;
const year = "2023"; //this is a dummy variable since year is required for Date().
const date = new Date(year   "-"   month   "-"   day);
console.log(date);

Here's the users document from MongoDB:

name: "Angelo"
birthday: 2023-01-11T00:00:00.000 00:00 //Date data type

name: "Josh"
birthday: 2023-01-19T00:00:00.000 00:00 //Date data type

Here's the for loop that should trigger success when there's a match, but there's no output. This is my problem.

let users = [];
db.collection("users").find({})
.forEach((user) => { users.push(user) })
.then(() => {
   for (i = 0; i < users.length; i  ) {
      if(users[i].birthday == date) {
         console.log("Success"); //no output on console
      }
   }
})

Checking users[i].birthday in console shows:

  • 2023-01-19T00:00:00.000Z (Shouldn't this be a match of today's date?)
  • 2023-01-11T00:00:00.000Z

CodePudding user response:

MongoDB Date objects store values in UTC. In your example you create a date object in the local timezone, so your dates will not match.

You can create a UTC zero date using the Date.UTC() static method, where zero date means a date with zero for the hours, minutes, and seconds. Here is an example that simulates your users array from MongoDB, assuming that the birthdays are all UTC zero dates. You can't compare the date objects directly, because two date objects that have the same date have different object addresses. Therefore you need to compare the value of the date objects (.valueOf()), or a string representation (.toISOString()).

function getUtcZeroDate(str) {
  if(str) {
    return new Date(str   'T00:00:00.000Z');
  } else {
    let date = new Date();
    return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
  }
}

const users = [
  {name: 'Angelo', birthday: getUtcZeroDate('2023-01-11') },
  {name: 'Josh', birthday: getUtcZeroDate() }, // today
]

const todayUtcZeroDate = getUtcZeroDate();
console.log("Today's UTC zero date:", todayUtcZeroDate.toISOString());

users.forEach(doc => {
  const match = (todayUtcZeroDate.valueOf() == doc.birthday.valueOf()) ? 'match' : 'no match';
  console.log(doc.name   ', born '   doc.birthday.toISOString(), '=>', match);
});

Output at the time of writing:

Today's UTC zero date: 2023-01-18T00:00:00.000Z
Angelo, born 2023-01-11T00:00:00.000Z => no match
Josh, born 2023-01-18T00:00:00.000Z => match

CodePudding user response:

A simple way to compare dates is to use setHours(0,0,0) for both birthday date and date like below:

const d = new Date(new Date().toLocaleString("en-US", { timeZone: "Asia/Hong_Kong" }));
const day = d.getDate();
const month = d.getMonth()   1;
const year = "2023"; //this is a dummy variable since year is required for Date().
let date = new Date(year   "-"   month   "-"   day);
date=date.setHours(0,0,0)


for fetching date and comparing from db:
let users = [];
db.collection("users").find({})
.forEach((user) => { users.push(user) })
.then(() => {
   for (i = 0; i < users.length; i  ) {
       users[i].birthday=new Date(users[i].birthday).setHours(0,0,0)
      if(users[i].birthday == date) {
         console.log("Success"); // output on console
      }
   }
})

Try it you will get output.

CodePudding user response:

I suggest considering using moment.js for this. You'll be also need moment-timezone.js add-on to use timezones.

I recommend moment.js because with it, the code becomes more readable.

moment.tz.setDefault("Asia/Hong_Kong");

const users = [{
    name: "Angelo",
    birthday: new Date('2023-01-11T00:00:00.000 00:00'),
  },
  {
    name: "Josh",
    birthday: new Date('2023-01-19T00:00:00.000 00:00'),
  },
];

const today = moment();

for (i = 0; i < users.length; i  ) {
  const user = users[i];
  if ( today.isSame(user.birthday, 'date')) {
    console.log("Success", users[i]);
  }
}
<script src="https://momentjs.com/downloads/moment.min.js"></script>
<script src="https://momentjs.com/downloads/moment-timezone-with-data.min.js"></script>

  • Related