Reputation: 1883
I'm writing a React Application that uses MongoDB as its database. There seems to be some strange behaviour when saving and retrieving dates from the database, specifically when updating the date in a particular document.
When I create a new document, everything is fine. However, if I try to edit the date on that document using an ajax call, the date stored in MongoDB is one day earlier than the one I selected and what is displayed in the browser. Code below to explain a little more.
The date is selected using an HTML5 <input type='date' />
element. Here's some of the code. I've included console logs at various points to show the output. Let's assume I'm selecting '30 October 2016' as the date. The date and the year get split up for display purposes elsewhere, but then joined together in the form of a JS Date object before sending to the server (see code below)
React component method:
saveChanges(e, cancel){
e.preventDefault();
const cancelled = cancel ? true : false
console.log(this.state.date); // 30 Oct
console.log(this.state.year); // 2016
const saveData = {
id: this.props.data.id,
venue: this.state.venue,
unitNumber: this.state.unitNumber,
unitName: this.state.unitName,
date: this.state.date,
year: this.state.year,
day: this.state.day,
tutorID: this.state.tutorID,
cancelled: cancelled
}
editWorkshop(saveData, (data) => {
this.props.getWorkshopDetails();
this.props.workshopDetailsSaved(data);
});
}
The above method sends the data to editWorkshop.js
, an external ajax call, using axios:
import axios from 'axios';
export default function editWorkshop(input, callback){
const date = new Date(input.date + ' ' + input.year) // Rejoin date and year and convert to Date object
console.log(date); // Sun Oct 30 2016 00:00:00 GMT+0100 (BST)
const data = {
id: input.id,
venue: input.venue,
unitNumber: input.unitNumber,
unitName: input.unitName,
date: date,
day: input.day,
tutorID: input.tutorID,
cancelled: input.cancelled
}
axios.post('/editWorkshop', data).then(function(res){
callback(res.data);
})
}
And finally the express route which handles the ajax call
const express = require('express');
const Workshop = require('../data/models/Workshop');
module.exports = function(req, res){
const data = req.body
console.log(data.date); // 2016-10-29T23:00:00.000Z - here is where it seems to go wrong - notice that the date has changed to 2016-10-29 instead of 10-30. This now gets written to the database
Workshop.update({ _id: data.id }, {
$set: {
unitNumber: data.unitNumber,
date: data.date,
venue: data.venue,
tutor: data.tutorID,
session: data.day,
cancelled: data.cancelled
}
}, function(err){
if (err) {
res.send(err);
return
}
var message = 'Workshop updated'
res.send({
success: true,
message: message
});
})
}
What's really strange is that when I retrieve the data from the database elsewhere in the application, it shows the correct date in the browser - 30 Oct 2016.
Arguably this isn't a problem as the correct date is being displayed, but I'm not comfortable with this as these dates are a fundamental part of the app and I'm concerned that there could be scope for a bug in the future.
Can anyone shed any light on this?
Upvotes: 2
Views: 343
Reputation: 5095
2016-10-29T23:00:00.000Z
is same as Sun Oct 30 2016 00:00:00 GMT+0100 (BST)
.
2016-10-29T23:00:00.000Z
is in UTC(GMT)
timezone. If you convert that to BST you will get the same value.
MongoDB saves the date values as UTC milliseconds since the Epoch.
From the docs:
MongoDB stores times in UTC by default, and will convert any local time representations into this form. Applications that must operate or report on some unmodified local time value may store the time zone alongside the UTC timestamp, and compute the original local time in their application logic.
Upvotes: 5