Mongoose saving and retrieving dates with UTC time, change to server timezone - node.js

I'm using mongoose models to save my records including created and updated dates. Here's my model schema:
var CasesModelSchema = new mongoose.Schema(
{
caseId: Number,
sessionId: String,
createdAt: {type: Date},
updatedAt: {type: Date, default: Date.now},
docs: mongoose.Schema.Types.Mixed
},
{
collection: 'cases'
}
);
The problem I'm facing is that the updatedAt field saves the datetime as ISODate("2017-04-24T12:40:48.193Z"), which is in UTC, but my server's timezone is Asia/Calcutta. Since I need to make queries according to my server's time, I need the datetimes to be saved in my preferred timezone.
Here's the query I need to execute (get all data for the last 10 days)
var today = moment(moment().format('YYYY-MM-DD')).toDate();
var tenDaysDate = moment(moment().format('YYYY-MM-DD')).add(-10, 'days').toDate();
CasesModel.findOne({updatedAt: {$gte: tenDaysDate, $lt: today}},
function(err, caseData){
cl(caseData, __line);
});
What I want is to do a query to get all the updated records in the last 10 days, exactly from 10 days ago midnight (Asia/Calcutta timezone) to today's midnight (Asia/Calcutta timezone). How do I do that?

What I want is to do a query to get all the updated records in the last 10 days, exactly from 10 days ago midnight (Asia/Calcutta timezone) to today's midnight (Asia/Calcutta timezone). How do I do that?
If by "today's midnight" you mean the last midnight that happened (in which case you will not get results from a moment ago), then you can use something like this - using your local time zone:
// use moment-timezone to handle time zones correctly:
const moment = require('moment-timezone');
let end = moment().startOf('day').tz('UTC')
let start = end.subtract(10, 'days');
or explicitly using Asia/Calcutta time zone:
let end = moment.tz('Asia/Calcutta').startOf('day').tz('UTC');
let start = end.subtract(10, 'days');
If by "today's midnight" you mean the next midnight that will happen (in which case you will get results from a moment ago), then you can use something like this - using your local time zone:
let end = moment().endOf('day').tz('UTC')
let start = end.subtract(10, 'days');
or explicitly using Asia/Calcutta time zone:
let end = moment.tz('Asia/Calcutta').endOf('day').tz('UTC');
let start = end.subtract(10, 'days');
You will have UTC dates that correspond to your local midnights, ready to use in Mongo queries.
No need to change anything in Mongo.

Related

how to store date and timezone in Indian Standard Time(IST) format in node.js?

I have installed moment-timezone node-module and getting the date correctly but when I try to save it to database it is converting back into some another time-zone.
const moment = require('moment-timezone');
const dateIndia = moment.tz(Date.now(), "Asia/Kolkata");
console.log(dateIndia);
Here console is printing the correct IST time:
Moment<2022-06-04T15:08:08+05:30>
Then I am storing it into the database from schema:
bookingDate: {
type: Date,
default: dateIndia,
required: true,
},
But it is saving date into UTC timezone like this:
2022-06-04T09:18:38.540+00:00
That is not about your NodeJS. That is your database time-zone configuration.
You can solve that with one of the 2 below:
1 - Change your database time-zone configurations
2 - When you get from the database just use the same function you used to create the date and convert it back to the timezone you want:
let dateUTC = (moment.tz(databaseDate, "UTC");
let dateIndia = dateUTC.tz("Asia/Kolkata").format()

how to fix the date error using Date.now()

I am using Date.now() to get the current date and time, but I didn't know the problem I am having. The scenario is this that I use console to check whether date.now() generating correct time or not? Unfortunately I got the correct date in Unix code value convert and check that was correct time and date but when I put that in mongoo schema it used few hours back and store date with few hours back time. But when I get that object with date it returns me the few hours back date and time but when I bind that with Angular front it shows me the correct time the time I put on mongoo the problem is I am not able to filter data by date bcs that object contain few hours back time.
Here is the typescript object that I am pushing on the mongoo
bill = {
orderArray: [],
//investment total
totalActual:0,
//sale total
totalSale: 0,
//investment - sale
totalSave: 0,
quantity: 0,
date: Date.now()
}
and here is the mongo schema:
var cartSchema = mongoose.Schema({
orderArray: Array,
date: { type: Date, default: Date.now },
totalActual: Number,
totalSale: Number,
totalSave: Number,
})
Please check to whether your DB server and application running in the same timezone
Or convert your local time to UTC format from application side and pass it MongoDB

How to prevent Sequelize from converting Date object to local time

I am using sequelize for a node project. It's connecting to a Postgres databsae, which contains a table with a DATE field (unlike TIMESTAMP WITH TIMEZONE, DATE has not time data).
In the code I'm modeling the date using a javascript Date object, which stores the time as UTC midnight. When I use that to insert a record into the table using that Date object, sequelize is apparently coverting it to local time first because the records are always 1 day behind. So if I want to insert 2000-10-31 into the database I end up with 2000-10-30. I am in UTC-5.
How do I tell sequelize to not convert the Date to a local time before inserting into the database?
Here is some sample code. I also created a repository if you want to run it yourself.
var Sequelize = require('sequelize');
const sequelize = new Sequelize('testdb', 'postgres', '???', {
host: 'localhost',
dialect: 'postgres'
});
TestTable = sequelize.define('date_test',
{
id: {
primaryKey: true,
type: Sequelize.INTEGER,
autoIncrement: true
},
someDate: {
field: 'some_date',
type: Sequelize.DATEONLY
}
},
{
timestamps: false,
freezeTableName: true
}
);
// midnight UTC on Halloween 🎃
var date = new Date(Date.UTC(2000, 9, 31));
// converts to local time resulting in 2000-10-30
TestTable.create({ someDate: date })
.then(function() {
// also apparently converts to local time resulting in 2000-10-30
return TestTable.create({ someDate: date.toUTCString() });
})
.then(function() {
// convert to string, definitely works but seems unnecessary
var strDate = date.getUTCFullYear() + '-' + pad2(date.getUTCMonth() + 1) + '-' + pad2(date.getUTCDate());
return TestTable.create({ someDate: strDate });
})
.then(function() {
// cerate a new local Date, also works but seems hacky
var newDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
return TestTable.create({ someDate: newDate });
})
.then(function() {
process.exit(0);
});
function pad2(n) {
if (n.length === 1) {
return '0' + n;
}
return n;
}
The problem is that the date is created as UTC time, but because DATEONLY has no awareness of the timezone, it formats the Date object "as is" (in local time) with format YYYY-MM-DD (using moment.js - see here in source).
For a DATEONLY you can just do this:
var date = new Date(2000, 9, 31);
That will insert the date correctly.
Programmers seldom say this, but for once you were thinking too much about timezones!
OLD INCORRECT ANSWER
It depends on how you are checking the value, but javascript and postgresql are converting it to your local timezone for display.
Sequelize uses a TIMESTAMP WITH TIMEZONE type for a date field (source).
In the postgresql docs it says:
For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system's timezone parameter, and is converted to UTC using the offset for the timezone zone.
When a timestamp with time zone value is output, it is always converted from UTC to the current timezone zone, and displayed as local time in that zone. To see the time in another time zone, either change timezone or use the AT TIME ZONE construct (see Section 9.9.3).
If you are outputting the time value in postgresql, try converting it to UTC. If you are are outputting it in javascript, try date.toUTCString().
The reason your hacks appear to work is because they are actually storing 2000-11-01 05:00 but when you inspect the value, it is converted into your local time zone.

Date conversion in nodejs and postgres

I have column birthday in postgres with type date, I receive a unixtimestamp from front-end like 716500800. When I am saving it to postgresql, it seems like it is converting based on my local time zone. I don't understand what I should do, here is a code
const date = moment.utc(data.birthday * 1000).format();
console.log(date); // 1992-09-15T00:00:00Z it is right date
db.query(
'UPDATE app_users SET birthday=$1 where id=$2 RETURNING birthday',
[
date,
id
],
(err, bd) => {
console.log(bd.rows); // birthday: 1992-09-14T20:00:00.000Z
}
So I set timezone on server and db to UTC. From front-end I get timezone and chande db field to timestamptz (with time zone). Now I operate with all dates in UTC and show/get from client with time zone.

PayPal-node-SDK `Subscription start date should be greater than current date` always occurs after 12 am

I live in Hong Kong and I always get this sandbox paypal transaction error after midnight from paypal.billingAgreement.execute(). The error goes away in the afternoon, probably because the place where paypal server is located finally gets past the midnight.
{ name: 'SUBSCRIPTION_UNMAPPED_ERROR',
message: 'Subscription start date should be greater than current date',
information_link: 'https://developer.paypal.com/docs/api/payments.billing-agreements#errors',
debug_id: 'd2e618eef4162',
httpStatusCode: 400
},
I know this is a timezone problem with the sandbox environment but I can't figure out how to solve it.
My billing agreement is created as per the example in PayPal-node-SDK
process.env.TZ = 'utc';
var isoDate = new Date();
isoDate.setSeconds(isoDate.getSeconds() + 4);
isoDate.toISOString().slice(0, 19) + 'Z';
var billingAgreementAttributes = {
"start_date": isoDate,
/..../
}
I have set the TZ environment variable in nodes to utc;
The time zone setting of the sandbox account I use to log in and subscribe:
I've also tried different zones like Eastern Time but it has no effects.
As per PayPal Docs, StartDate should be UTC, looks
Setting Process Time Zone
process.env.TZ = 'utc';
has no effect in your code(some time it might be cashed), can you check the date variable value is in UTC?
I would suggest to change
var isoDate = new Date();
to
var isoDate = new Date().toISOString();
Hope it helps!

Resources