Exercise Tracker - Correct Output, Failed test [SOLVED]

UPDATE: I finally solved it, but I want to leave this post here in case other people run into the same issue, so I will finish this post and then add the answer in a reply so I can mark it as solved too.

Hello fellow campers. Been going at this one for a while and I just can’t figure out what is it that is not working. All tests are passing except for this one :

The response returned from POST /api/users/:_id/exercises will be the user object with the exercise fields added.

Expected output according to fCC example:

{
  username: "fcc_test",
  description: "test",
  duration: 60,
  date: "Mon Jan 01 1990",
  _id: "5fb5853f734231456ccb3b05"
}

My example output:

{
"username":"Rodrigo",
"description":"Biceps",
"duration":30,
"date":"Wed Mar 06 2024",
"_id":"65e8c221ccbc8c00f8873cac"
}

Relevant Code:

// --- POST NEW WORKOUT ---
// ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ 
app.post("/api/users/:_id/exercises", (req, res, next)=>{
  let userId = req.params._id;
  let workout = req.body.description;
  let duration = parseInt(req.body.duration); // add parseInt() ?
  let date = req.body.date ? new Date(req.body.date).toDateString() : new Date().toDateString();
  // res.send([userId, workout, duration, date])
  // --- INSERT AND SAVE NEW WORKOUT
  new Workout({"userId": userId, "description": workout, "duration": duration, "date": date}).save(function(err, workoutData){
    if(err){console.error(err); return}
  })
  ;
  // --- FETCH USERNAME ---
  User.find({"_id": userId}).select({"username": 1, "_id":1}).exec(
    function(err, userNameAndId){
      if(err){console.error(err); return };
      // --- RETURN USERNAME AND _ID FIELDS
      // userNameAndId[0].description = workout;
      // userNameAndId[0].duration = duration;
      // userNameAndId[0].date = date;
      res.json({username: userNameAndId[0].username, description: workout, duration: duration, date: date, _id: userId })
      // res.send(userNameAndId[0])
    }
  )
})
// ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ 
// --- END OF POST NEW WORKOUT ---

FAQ:

  1. I’m running this locally
  2. Duration is an integer
  3. I don’t have a Replit account (and I’ve created so many different accounts since I got started with fCC, that I’d rather find a solution to this without having to create a new one)
  4. I suspect that maybe the problem has something to do with the dates (my timezone is GMT: -3:00… maybe the server checks with a different timezone? )
  5. On that note, since we’re in a leap year, I tried to log exercises for dates Feb. 28, Feb. 29, and Mar. 1 and they were all added as the day prior (Feb. 27, Feb. 28, and Feb.29)

GitHub:
https://github.com/RodrigoHLC/fcc-exercise-tracker/tree/main

Exercise link:
https://www.freecodecamp.org/learn/back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker

OK, so: this is what led me to finding the solution:

  1. On that note, since we’re in a leap year, I tried to log exercises for dates Feb. 28, Feb. 29, and Mar. 1 and they were all added as the day prior (Feb. 27, Feb. 28, and Feb.29)

After writing that, I tried with other dates further from Feb. 29 and realized all of them were being added for the day prior. Gotta give a special shoutout to ChatGPT here, because the problem had to do with something I really had no idea about and which I would have never been able to simply figure out myself, because it told me to use a library the existence of which I didn’t even know about: moment.js

“The issue you’re encountering is likely due to the behavior of the JavaScript Date object’s parsing and the discrepancy between UTC and local time zones. When you parse a date string using new Date('YYYY-MM-DD'), it creates a date object representing the given date in the local time zone.

However, since the date strings are being parsed in the local time zone, there can be inconsistencies when dealing with time zone transitions, such as daylight saving time changes or differences in how dates are interpreted between UTC and local time.

To ensure consistent behavior regardless of time zone discrepancies, you can use a library like moment.js or date-fns for handling date parsing and manipulation. These libraries offer more robust and consistent date parsing and formatting functionalities.”

NOTE: the issue arised when manually inputting dates. If I didn’t input a date, then the date automatically created for the current day was correct.

So if you’re having the same issue I’m having, try adding the moment.js library to your dependencies (version I used: ^2.30.1 ), require it in your index.js file.
I replaced my faulty line of code
new Date(req.body.date).toDateString()
with

moment(req.body.date).toDate().toDateString()

I blurred it in case you want to try to figure it out yourself, but in all honestly, there’s absolutely no reason for you to simply guess how to use it if you’ve never seen any examples.

You shouldn’t need to use a date library for this.

The two example responses you posted are not different by timezone they are completely different dates.

Also, make sure your system time is correct (OS clock).


BTW, don’t commit or push .env files you are leaking your DB credentials

1 Like

Ok, thank you, but can you then tell me what I do need to fix? Because that package was the only thing that worked for me so far.

System time is correct.

Ahh thanks for the advice about the .env file. I have now removed it from the repository.

I never had any issues with dates for the challenges. For me, your old code is passing the tests. I’m GMT+1

What is the response you are sending for the failed test?

What does running new Date('1990-01-01').toDateString() in your browser console return and what does running it in Node return?

As far as I understand, all the code runs locally. The tests are client-side and run in the browser and your server is running locally as well so the dates they produce should match I would think.

Edit: but you are not the first to have issues with dates and the tests.

https://forum.freecodecamp.org/search?expanded=true&q=Exercise%20Tracker%20timezone


If you do need a date library I would suggest something more modern like date-fns (even Moment own site no longer recommend it for new projects).

There is also the Intl stuff you can look at.

Tests: https://github.com/freeCodeCamp/freeCodeCamp/blob/main/curriculum/challenges/english/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md


As an aside, you should change the DB credentials because it is in your git history now. Remember to add the .env file to a .gitignore file.

1 Like

Revoking the credentials by changing it is the most sound advise that it can be given. Removing the sensitive file from the repository is not enough since anyone that have access to the history can obtain it. There are ways of trying to sanitized the history, but … (trying to rewrite history is never a good thing :wink:

1 Like

Running new Date('1990-01-01').toDateString() in my browser console returned “Sun Dec 31 1989”

I’ve no idea what that is all about :face_with_raised_eyebrow: :face_with_raised_eyebrow:

I guess it is just a time zone issue.

Honestly, I have looked at the JS Date API many times and I still don’t understand it well enough. Also, it has got to be the most boring API to try and learn. I can’t get through half a page without falling asleep. :sleeping:

It’s also kind of broken but it should be getting updated Temporal.

As far as I understand, if no time is provided it is assumed to be midnight GMT and is adjusted to the timezone the code is running in.

let date = new Date("2017-01-26");
alert(date);
// The time is not set, so it's assumed to be midnight GMT and
// is adjusted according to the timezone the code is run in
// So the result could be
// Thu Jan 26 2017 11:00:00 GMT+1100 (Australian Eastern Daylight Time)
// or
// Wed Jan 25 2017 16:00:00 GMT-0800 (Pacific Standard Time)

Here are a few logs after I set my time zone to UTC-5

new Date('1990-01-01').toDateString()
'Sun Dec 31 1989'
new Date('1990-01-01, GMT-5').toDateString()
'Mon Jan 01 1990'
new Date('1990-01-01T00:00:00.000Z').toDateString()
'Sun Dec 31 1989'
new Date('1990-01-01').toISOString()
'1990-01-01T00:00:00.000Z'
new Date('1990-01-01').toUTCString()
'Mon, 01 Jan 1990 00:00:00 GMT'

I think if you use toISOString or toUTCString you will get the correct date but you will have to format the string. The Intl API can also help with that. Or I guess just use the date-fns package.