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.
Related
Im trying to create a new document in firestore using a cloud function. However i am unable to save the date as a timestamp rather, it's saved as a string currently.
How it is right now
What i need to achieve
Snippet of my cloud function
await admin.firestore()
.doc('/buyerProfile/'+response.buyerId)
.collection('notifications')
.add({
'type':'New response',
'responseId':response.responseId,
'requestId':response.requestId,
'date': Date(Date.now()),
'compressedImgUrl':response.compressedImgUrl,
'description':response.description,
'requestPaidFor':request.data().isPaidFor
}).then(()=>console.log('Notification created'));
You can use to get timestamp new Date().getTime();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#return_value
just do it like this:
let today = new Date();
let timestamDate = Date.parse(today) / 1000;
and your date will be converted to timestamp
You don't have new keyword before Date constructor which will indeed return a string. If you want a Date object try this:
date: new Date() // Date object of current time
If you want to store the timestamp as number then pass Date.now()
You can check the same in a browser console:
You can also use serverTimestamp() method instead:
date: admin.firestore.FieldValue.serverTimestamp()
This worked for my case, i had to import Timestamp from firebase admin
const { timeStamp, time } = require("console");
...
'date': timeStamp.now(),
Firestore stores date/time values in its own Timestamp format.
There are two options:
If you want to capture the client-side time, use Timestamp.now(), so:
'date': Firestore.Timestamp.now(),
If you want to capture the server-side time, use:
'date': admin.firestore.FieldValue.serverTimestamp(),
import { serverTimestamp } from 'firebase/firestore';
and replace: <'date': Date(Date.now())>
with <'date': serverTimestamp()>
this should solve your problem
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');
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!
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.
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.