Date conversion in nodejs and postgres - node.js

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.

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 create a timestamp with timezone value which is (currentdate-7) days in nodejs?

My postgresql timestamp with timezone format is 2020-07-03T07:01:42.231433+00:00
How can I create such a timestamp value which is (current date - 7 days) in nodejs?
My aim is create a grapghl query to update all rows older than 7 days in postgresql.
mutation MyMutation($timestampInterval: timestamptz) {
update_Offers(where: {createdAt: {_lt: $timestampInterval}}, _set: {active: false}) {
affected_rows
}
}
In this query I am comparing if the createdAt time (which is timestamp with timezone) is less than the timestamp with timezone value that I am giving.
use moment.js library.
its fairly easy using it.
const moment = require('moment');
const oldDate = moment().substract(7,'d').format('YYYY-MM-DDTHH:mm:ss+00:00');

Node.js with TypeORM inserts wrong timezones into Azure SQL Database

I have a backend written on top of node.js, I'm using TypeORM as the ORM and Azure SQL Database to store my data. When I call the ORM's create() and save() functions, I'm passing in the correct date and time as can be seen below. But when I query the inserted data in the server, the timezone has shifted from -03:00 to +00:00. It maybe a normal behavior, since I'm new working with dates though.
This is the code where I call the create() in:
class CreateAppointmentsService {
public async execute({ provider, date }: RequestDTO): Promise<Appointment> {
const appointmentsRepository = getCustomRepository(AppointmentsRepository);
const roundDate = startOfHour(date);
const foundAppointment = await appointmentsRepository.findByDate(roundDate);
if (foundAppointment) {
throw Error('This date and time already has a booking.');
}
const appointment = appointmentsRepository.create({
provider,
date: roundDate,
});
await appointmentsRepository.save(appointment);
return appointment;
}
}
This is my debug information, showing date and time in expected timezone.
This is the data in the database. The field type is datetimeoffset and the server time is set to UTC (+00:00).
Thanks in advance! =)
[EDIT]: Explaining better: the time I posted to the database is rounded to 20:00 -03:00 (America/Sao_Paulo/Brasilia). If you look the column "created_at", the time is updated to UTC, but the column "data" only got the timezone set to +00:00, the time remais 20:00.
Found the problem! I forgot to set the "date" column to datetimeoffset in the typeORM model =(.
How it was:
#Column()
date: Date;
Changed to:
#Column('datetimeoffset')
date: Date;
Now it work wonders! The correct timezone is being set alongside the time. Cheers!

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.

Knex NodeJS insert date timezone compatible inside PostgreSQL

I have a postgreSQL table like this:
table.string('id');
table.string('name');
table.specificType('data', 'JSONB');
table.timestamp('runDate');
table.boolean('done').default(false);
I wonder what is the safe way to insert date time inside the database.
This is what I do:
await _i_.knex("jobs")
.transacting(ctx ? ctx.transaction : null)
.insert({
id: job.id,
name: job.name,
data: job.data,
id: job.id,
runDate: job.runDate,
done: false
});
When I want to query my table, I use:
return await _i_.knex('jobs')
.transacting(ctx ? ctx.transaction : null)
.whereRaw('"runDate" < NOW()')
.andWhere('done', false)
.returning("*")
.update({
done: true
});
So I can have issue with the timezone if my nodeJS server doesn't have the save timezone than my PostgreSQL.
How do you manage that?
By default knex creates timestamp with time zone (timestamptz) type for .timestamp() columns for PostgreSQL. So, your date and time are stored with timezone. For inserting timestamp values I like to use moment package.
const moment = require('moment');
const dateStr = moment().utc().format();
console.log(dateStr); // => Date in format 'YYYY-MM-DDTHH:mm:ssZ'
knex.insert({ runDate: dateStr })
How about using the DB time on insert: ...runDate: knex.raw("NOW()")...
Then the storage and retrieval dates will be synchronized to the same timezone.
BUT if the job.runDate needs millisecond accuracy, or the record has been held for a significant amount of time before storage, then this would not be appropriate.

Resources