How to remove gmt from postgreSQL db across date columns? - node.js

I am using PostgreSQL in my application. Simply I have declared a particular model attribute as sale_date and have set its data type to Date as follows:
//definition in backend model
sale_date: {
type: Sequelize.DATE,
allowNull: true,
}
And I am using moment on the frontend which is on react. I am giving the user a calendar option to select a date and setting the time as 00:00:00 so that the DB does not pick the local time. However, one issue I am facing is that it automatically adds +05 to the time which is the timezone I am currently in.
2021-06-01 05:00:00+05
Here because of +05, the time became 05:00:00 automatically, how to avoid this, I need time to stay 12am always so that the calendar date does not change even if I upload a document at 11:00 pm.
Using moment like this on the frontend
//From front-end implementation
sale_date = moment
.utc(object.sale_date)
.format("YYYY-MM-DD 00:00:00Z");
How do I achieve the desired behavior?

I think that .utcOffset() can be helpful for your case.
const date = moment().format();
const date2 = moment
.utc(date)
.utcOffset(0)
.format();
console.log(date);
console.log(date2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
Documentation of utf offset

Related

Date-time recorded by mongo-db is different from clientPC (server location is in same region)

This is about a different date-time recorded in mongoDb via Node.js.
e.g. the date time recorded is 2022-02-01T13:32:01.967Z,
the actual time is 19:02 for the same date.
Looks like it has recorded GMT. This code will be eventually run on a VPS based in my country. However, at the moment I am running the code on localhost.
below is the code in Node.js
/// part of a controller method
const xDate = new Date();
console.log('new Date()', xDate);
// output: 2022-02-01T13:32:01.967Z, actual time 19:02 on same date
candidate.history.push({
actionDate: xDate,
userId: user.acctId,
userName: user.userName,
remarks: 'bla bla bla'
})
await candidate.save();
Any idea how to correct it? In Angular we can set the input field to datetime-local type to save the date/time without timezone. Can we do something similar in Node.js /mongodb? How do I get the correct time stored in mongo?
I have read that MongoDB always stores the timestamp in UTC. Is there any way this can be handled application-wide to handle all date values recd from Mongo in both the below cases:
at Node.js levelfor performing some date calculations based on date value recd from Angular?
At Angular level for date values recd from Node(as it is from Mongo)

Date format in our Application

Can anyone tell me which is the right format to store date in my database.
Suppose if the client and the server are in the same region, we can use unix epoch timestamp or date string. But if the server is in US and the client is from Asia, I knew people saying UTC to auto convert date from the particular region. But I cannot store UTC in MongoDB via Node js, maybe i made it in the wrong way.
.currently I store "09-02-2021" for date and 1612837056077 timestamp. I also get the time from the front end.Also, I am not sure with the above things. Can someone explain the right way of using date and time in a real world application. If possible show me a quick demo in node js and mongoose
Thank you all :)
UTC is the way to go. I don't know what you mean by "But I cannot store UTC in MongoDB via Node js". Create your schema like so:
const client_schema = new mongoose.Schema({
...
...
date_created: {type: Date, default: Date.now},
...
...
});
And date_created will always be stored in UTC format. From UTC, you can convert it to any timezone. Here is just one example, using moment, of how to convert UTC to a Eastern Timezone:
const d = moment(utc_date).utcOffset(moment(utc_date).tz("America/New_York").format('Z'), true).toDate();
Note: moment is being phased out and is no longer recommended for new projects.

mongodb storing incorrect date

I don't really understand why this is happening but in mongodb atlas personalisation settings I have set my time zone to the country I am in. I am hosting the frontend on Netlify and I am using Heroku for my node.js backend.
In my schema I have the date set up like so:
requiredDate: {
type: Date,
required: true,
},
On the frontend there is a date picker. If someone was to select a Friday, it always saves in the database as Thursday like below. So, it is always a day behind it would seem, either in hours or days or whatever it is.
2020-08-27T22:00:00.000+00:00
The date picker field on the frontend sends the date to node.js like so:
27/8/2020
I tried this which seems to work but isn't there a more global way of doing it than having to do this for every form that has a date in it?
let localTime = visitDate.toLocaleString("en-US", {
timeZone: "Asia/Calcutta",
});

Mongoose datetime and timezone, how to get datetime based on server timezone

The first answer of this question suggests that mongoose would adapt the date according to server timezone when retrieving data.
However, I don't have this comportement.
I set the (node) server timezone with :
process.env.TZ='Europe/Paris'
For exemple if I create a simple model like :
const mongoose = require("mongoose");
const testSchema = new mongoose.Schema({
myDate: { type: Date, required: true },
}, { timestamps: true });
exports.Comment = mongoose.default.model('TestSchema', testSchema);
But if I create a date with 2020-01-01 20:20:20, when doing TestSchema.find() the date will be: 2020-01-01T19:20:20.000Z so there are two things that I don't understand :
Europe/Paris is actually UTC +2, so I would expect the date to be either 2020-01-01T18:20:20.000Z in UTC or 2020-01-01T20:20:20.000Z with the server timezone
How to have mongoose automatically set the date to the correct timezone?
I know that myDate is a Date object, so I can convert it manually but I'd rather not have to do it myself for simple reasons like forgetting to convert one of the dates in the application or not having to do it every time a Date field is added
An easy solution that I can think of would be to register a global plugin for mongoose which would use schema.set('toJSON', ... and schema.set('toObject', ...) with the transform method so I can loop through schema fields and if the field is a Date, update it to my timezone.
But I see two problems with this approch :
It doesn't sound very good performance-wise if I am querying a lot of documents each with a lot of fields
As you can see here I am currently not able to register global plugins...
What would be the best method to get the date in the server timezone format? I would rather still store them in UTC but set the hour according to the server timezone.
EDIT :
I just saw that while console.log(myDate) outputs 2018-01-01T19:20:20.000Z console.log(myDate.toString() outputs Mon Jan 01 2018 20:20:20 GMT+0100 (Central European Standard Time) so it seems likes this could be used, even tho I'd rather still have a Date object and converting it to string just before sending it to the client (would need some formatting tho since this format is not very user friendly). But then again, how would I do this globally and not for every date
A few things:
Europe/Paris at 2020-01-01T20:20:20 is UTC+1. It doesn't switch to UTC+2 until Summer Time kicks in on March 29th. Reference here. Thus the conversion to 2020-01-01T19:20:20Z is correct.
The output of console.log when passed a Date object is implementation specific. Some implementations will emit the output of .toString() (which is in local time in RFC 2822 format), and some will emit the output of .toISOString() (which is in UTC in ISO 8601 extended format). That is why you see the difference.
In general, it is not good to send a local time without also sending a time zone offset. ISO 8601 format is ideal, but you should send either 2020-01-01T19:20:20Z, or 2020-01-01T20:20:20+01:00. Don't just send the date and time without an offset to the client. Otherwise, if your client could be in a different time zone then they would interpret the value incorrectly.
Keep in mind that Date objects are not time zone aware. They contain only a Unix timestamp internally, and they convert only to the system's local time zone for the functions that work in local time. They cannot work in any other time zone.
Relying on the system local time zone is bad for portability. One doesn't always have the ability to change it, and it doesn't do well when you have to work in multiple time zones. It would be better to not rely on setting a local time zone from Node's TZ variable. Instead, consider writing your code to be independent of any local time zone setting.
A time zone aware date library can help with most of your concerns. I can recommend Luxon, js-Joda, Moment + Moment-Timezone, or date-fns + date-fns-timezone.
"how would I do this globally" is something I'm not following in your question. Try the approach I described, and if you still have issues then open a new question. Try to be specific and ask a single question. You're likely to get better results that way. Please read How do I ask a good question? and How to create a Minimal, Complete, and Verifiable example. Thanks.
To solve the issue:
npm i mongoose-timezone
In your schema file:
import timeZone from "mongoose-timezone";
const testSchema = new mongoose.Schema({
myDate: { type: Date, required: true },
}, { timestamps: true });
// mongoose will save the dates based on user's timezone
testSchema.plugin(timeZone)
mongoose-timezone basically adds the current timezone offset to the
date before store and removes the offset when retrieving data. This
way dates are kept proportional in the database and in the app.

Timestamp in sequelize 1.7.3

hi i want to save date and time according to eastern time, my sequelize model is:
var objName= sequelize.define('tbl_name',{
orders_id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true },
customers_id:Sequelize.INTEGER,
date_purchased: { type: Sequelize.DATE, defaultValue: Sequelize.NOW },
order_total:Sequelize.INTEGER,
},
{
tableName: 'tbl_name',
timestamps: false
});
now i want to use timestamps somehow in it and want to save (Eastern Standard Time), can someone guide me how can i do this.
Note: i am using mysql and sailsjs .
Thanks.
EDIT
also used following two snippets but then it saves 0000-00-00 00:00:00
date_purchased: { type: Sequelize.DATE, defaultValue: sequelize.literal("FROM_UNIXTIME(UNIX_TIMESTAMP() + (3600 * 2))") },
date_purchased: { type: Sequelize.DATE, defaultValue: sequelize.literal("(now() at time zone 'EST')") }
Are you going to want to manipulate your dates (add, subtract, compare)? If NOT then just save them as pre-formatted strings.
Otherwise you are going to run into problems with this approach of saving "Eastern time" that are beyond sails. Remember eastertime is the same as UTC, just with an offset and this offset changes depending on if your in Daylight savings or no.
MySQL by default will use the system time zone internally but it is possible to define a different time zone for the MySQL server globally or even per transaction. However, MYSQL is still going to save the time in a UTC, all your telling MYSQL is to transform during read/writes as if we were in eastern timezone.
This can be tricky when dealing with many variables such as your application server, your db adapter and finally your DB.
The safest thing to do is to save all dates as UTC (have your server setup in a UTC system time) and then display them in the correct timezone via the application layer.
You have to ask yourself. "Where are my dates coming from". Are they all being generated within the database itself (like your code above)? Are they being generated by the application server (such as sails creating the date and then inserting it) or will dates come form the client (browsers have their own timezone issues).
If you do want to manipulate/compare them, then your best making sure your dates save UTC and then manipulating the timezone when its displayed to the user. Consider Daylight Savings Time (it changes this weekend!).
How to accomplish this will vary depending on your setup and answering many of the questions I have issued above.
I know that I stopped using Date/Time methods a while ago and instead use integer to store all my dates with a UnixTimestamp. Then I format that into the correct timezone before showing to the client. This ensures that my dates will not be unduly transformed no matter what DB i'm using or where the server is. This is just a personal preference, but I find it has elevated a big headache.

Resources