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.
{
"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:
I’m running this locally
Duration is an integer
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)
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? )
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)
OK, so: this is what led me to finding the solution:
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.
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.
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
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.
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.