mongodb date conversion is weird - node.js

I'm making a small employee management system in which I have to play with dates in many places like attendance, leaves etc.
I use luxon for dates in my node.js project. Ex: DateTime.fromISO("2020-10-15"); gives me this in the console: 2020-10-15T00:00:00.000+05:00
but when I save it in mongodb it becomes 2020-10-14T19:00:00.000+00:00 and this is problematic because i need to query objects to check if there is an attendance marked in the same day or to get today's attendance. How can I solve this issue?

Storage
When MongoDB stores time-type data, it is first converted to UTC time and then stored in the database. The date submitted by the client is East 5, and the conversion to UTC time is minus 5 hours;
Read
MongoDB will convert the UTC date stored in the database into the East 5 zone of the client according to the time zone of the client, and then return it to the client

MongoDB only has a timestamp type, it does not have a date type. Dates are converted to times when they are stored. Which timezone the date is interpreted to be in can vary, looks like your driver uses the beginning of specified date in UTC. Ruby works the same way and you can read more about the principle here.
To "solve this issue", either only store and query by timestamps in MongoDB, converting dates to timestamps in your application, or understand how your language and driver converts dates to timestamps (note that JS Date type is actually a timestamp).

Related

Node application and insertion in Mongodb timestamp, problem with Date type and locale time

I have a node application that receives data from MQTT, where various parameters and timestamp are sent to the broker. The server and hardware are correctly configured with local time (Spain).
When I am going to do the insertion in the database, in this case MongoDB, I format the timestamp to be able to insert it in the mongo date format.
The problem is that only the javascript Date() can insert the date format in mongo and I always get two hours less than my local time.
//Format timestamp to date with dayjs
let date = dayjs(data.channels.timestamp * 1000).format()
//Output: 2021-09-16T13:32:33+02:00
//Format date to insert in MongoDB
let timestamp_ = new Date(date);
//Output: 2021-09-16T11:32:33.000Z
The correct date is: 2021-09-16T13:32:33+02:00
I tried momentjs and I have the same problem.
It is normal to have date in timezone GMT+0. Date object assumes the date is always GMT+0. Keep it like that and store everything in GMT+0.
Manipulate your query according to the time zone, not the data stored.

MongoDB/Mongoose timezone date decrement problem

I've got an edit page with a "date" type input. I'm using node.js, express, and mongoose to pull the content of the input and save it to the database using a date field in a Mongoose model. When I log the date before it goes into the database I'm seeing:2020-03-31. When I look at it in the database I'm seeing:2020-03-31T00:00:00.000+00:00. Does that +00:00 mean it's getting a timezone assigned? Do I need to edit how my MongoDB database is storing dates?
I'm running into trouble with the time zone when I read it back out and use it to populate the input on the edit page. I'm using a Mongoose model function to format the date before it goes into the value field on the html input. Within that function I'm running the below code:
console.log(date);
// Output:
// 2020-03-31T00:00:00.000Z
console.log(date.getDate());
// Output:
// 30
Is the 'Z' coming from the "+00:00" above? I'm GMT-4, so my server is interpreting that time as March 30th at 8pm and now the date picker on the edit page is populated with March 30th instead of the 31st. If I save this, then the next time I load the page the input will read March 29th. I don't want to unintentionally decrement the date by one every time the page is loaded and saved!
In this case, I really don't care about time and just want to refer to the date. Is there a different best practice I can use here?
MongoDB stores timestamps only, it does not have a facility to store dates. Javascript similarly does not have a facility for storing dates natively contrary to what you might expect - the Date type is actually a DateTime. Mongoose also does not have a date type (it uses JS Date which is a datetime).
What this means is:
When you are converting user input to a JS Date instance, you are getting the date converted to a datetime (sounds like the time component is zero in UTC in your application).
When you are reading the date out of the database, you are reading a datetime (which is the beginning of the day of that date in UTC per your provided information, not in your local time).
I would then proceed as follows:
The DateTime you are reading is the beginning of day on your date in UTC.
If mongoose converts the time to your local time, as it appears to do, you need to either stop it from doing that or convert back to UTC.
Then retrieve the year-month-day components of the UTC datetime.
Using these components you can create a new Date instance in local time or do whatever else you wish such as rendering them.
There are various libraries available in JS for dealing with dates and time zones, but the language itself has limited date support.

Moment date format changing from Node to MongoDB

I am creating an app in node js and saving date to Mongo DB, the datatype of Mongoose, I used to save is Date.
moment.locale("pt");
today= moment().startOf("day").format();
The date is printing like 2019-05-27T00:00:00-03:00
But when it is saving and I am trying to retrieve the date it is coming from mongo db like 2019-05-27T03:00:00.000Z
Now the comparison didn't work. So I am finding data based on this date and it is not working.
I am using locale for Brazil.I am keeping the user details day wise from 00:00 to next 24 hours and doing a luck draw of users. So I have huge database and want to filter data based on today date. So I need date should be saved in local timezone i.e. Brazil.
Any help would be appreciated.
I suggest moving to UTC, then changing the locale, then mutating the date to match the day's beginning and then storing as ms:
const d = moment
.utc() // Get the UTC time
.locale('pt_BR') // Change locale to Brazil
.startOf('day') // Go back in time to current date # 00:00:00
.valueOf() // Get ms value
// store d in the database

Cassandra time not saved in UTC

I need to split my timestamp to date and time separately and insert then to db columns with 'date' and 'time' cqltypes.
I was trying to insert a time value as string to Cassandra table. The time was converted to UTC (05:27:00). But while I checked table using Datastax devcenter, column was populated with value '09:37:54.935541808'. I tried to retrieve the value in spring using repository, then it was returning value as '3473746674935541808'.
How to get the correct value from table for time?
It looks like the limitation of Spring-data. In Cassandra time value is encoded as a 64-bit signed integer representing the number of nanoseconds since midnight. But I don't see the time type listed as supported in spring-data-cassandra documentation, so you may need to write your custom converter for it, as described in documentation.

Azure Table Storage date time comparison with UTC and local time difference

I am trying to store and retrieve three datetime columns on azure table storage.
Start date, End date and Last Executed date.
I have another fourth column which is called timeIntervalInMinutes.
My code execution will happen on an azure VM which might be on any zone in US.
I am going to use these values to execute some task based on current time:
start date >= current date <= end date
Current time = Last Executed Date (time) + intervalInMinutes
There are few doubts that I have:
The user is going to call this worker service on azure from their app, from any timezone US. Do I need to get their timezone in their request and store it along with the date time, which will get stored in UTC format on table storage?
If Yes, then if the user tries to retrieve this configuration information, should I convert based on UTC to local time conversion?
I need to execute my custom task based on the local time of the user. So when converting to UTC and storing it in the azure table, I need to say UTC + or - to suit the local time of the user's timezone?
Please help.
The OP wrote in a comment:
I have solved this by adding entity properties with DateTimeOffset type and created separate fields for holding UtcOffset timespan value as ticks (long type). With this I can compare the UTC format timestamp with UtcOffset values and date as well for my scheduler to work. So it's now easy for me to query against date and as well as retrieve and present the user back with his / her own specified local time.

Resources