Sequelize returning dates with wrong time - javascript

The database and node are set as -02:00 timezone.
When I save a register, using sequelize, it saves the register with the right date and time in its date fields. For example, if I save a register with the field moment set as '2017-01-15T23:59:59-0200' and look in the database via MySQL Workbench I will see 2017-01-16 00:00:00 in the respective column.
I can even correctly find registers and filter by date and time.
But the value returned by a find operation in the field is '2017-01-16T01:59:59.000Z', meaning it was added two hours to the answer.
How could I retrive the correct date and time from MySQL using Sequelize?

Solved by overhiding String.toJSON:
Date.prototype.toJSON = function(){ return this.toLocaleString(); }

Related

MongoDB Stored my date with the wrong time

I recently tried to assign a new date in MongoDB, but I have a problem with that, it stored the date I give but it's not correct
userSchema.methods.createPasswordResetToken = async function () {
this.passwordResetToken = crypto.randomBytes(20).toString('hex')
this.passwordResetExpires = moment().format(this.createAt)
await this.save()
console.log(moment().format(this.createAt)) // 2021-12-21T19:01:54+02:00
console.log(this.passwordResetExpires) // 2021-12-21T17:01:54.000Z
return { token: this.passwordResetToken, userId: this._id }
}
mongoDb remove 2 hours when storing it
and when I try to catch the type of two values
I got
console.log(moment().format(this.createAt)) // string
console.log(this.passwordResetExpires) // object
:
user Schema
...
passwordResetToken: String,
passwordResetExpires: Date
...
From the docs:
MongoDB stores times in UTC by default, and will convert any local time representations into this form. Applications that must operate or report on some unmodified local time value may store the time zone alongside the UTC timestamp, and compute the original local time in their application logic.
It seems your server just sits in GMT timezone ( utc +2, you could also see it from your date value // 2021-12-21T19:01:54+02:00 ). I would usually offer some hacky way to get around the issue but this is actually a best practice. Hence I recommend you do your date calculations in UTC and not in machine time.
note your other date is in UTC (2021-12-21T17:01:54.000Z), make sure your comparing apples to apples.

Get changes based on uploaded time from firebase

I have initialized a real time database using firebase, I am detecting live changes to the databse using
const ref = firebase.database().ref("test");
ref.on('value', function(dataSnapshot){
console.log(dataSnapshot.val())
});
But this returns me value in ascending order. Whereas I want it to return based on time. I tried using time in: 00:00 (IST) format but if a data is marked 11:59 (am) and another 01:02 (pm) this will return me the second message first.
What will be the best way to fix this?
example data is =>
in my databse =>
It is not clear what you mean by time in ascending order
None of your example data mention time. They are just usernames and text.
If you want to order times correctly, best to use ISO date format
This stores 1:02 pm as 13:02, which will sort after 11:59. Its sorting characteristics are ideal.
Use an international time standard to store your times
An international time standard, UTC, has great advantages over national times. It is not subject to change with location, political decisions, or season. You can always interconvert with the user's local time, at the time of entry or display.
Example
const dateString = (new Date()).toISOString();
console.log(dateString)
// Result:
// 2021-06-22T14:40:37.985Z
// If you want to use them as Firebase keys, they must not contain a ".", so you might clean it up like this:
const cleanDateString = (new Date()).toISOString().replace(".","-")
console.log(cleanDateString)
// Result:
// 2021-06-22T14:47:44-445Z
Even better, use a Firebase PushID
The above date-and-time system will work if you are using it to sort the remarks made by a single person, but will not be good as a message identifier if a single space is shared by all people, since 2 people will eventually make a message at the same millisecond, and will get the same message ID.
To deal with that it is better practice to use a Firebase Push ID.
An explanation is given here: In Firebase when using push() How do I get the unique ID and store in my database
Or from Firebase itself, here:
https://firebase.google.com/docs/database/admin/save-data

Knex silently converts Postgres timestamps with timezone and returns incorrect time

I have a table in my psql database with a "trigger_time" column of type "TIMESTAMP WITH TIME ZONE DEFAULT now()"
I data in the row is this 2018-06-27 15:45:00-03.
When running from psql console
SELECT trigger_time AT TIME ZONE 'UTC'
FROM tasks
WHERE task_id = 1;
this query returns "2018-06-27 18:45:00".
Similarly when I run
SELECT trigger_time AT TIME ZONE 'America/Glace_Bay'
FROM tasks
WHERE task_id = 1;
I get 2018-06-27 15:45:00
Using knex.raw("SELECT trigger_time AT TIME ZONE 'America/Glace_Bay' FROM tasks WHERE task_id = 1") I get 2018-06-27T18:45:00.000Z and when running knex.raw("SELECT trigger_time AT TIME ZONE 'UTC' FROM tasks WHERE task_id = 1") I get 2018-06-27T21:45:00.000Z
Both of these results from knex are incorrect, how do I get knex to stop silently altering my data?
Probably things are failing because when you are querying datetimes from database in certain timezone and effectively converting type of timestamp to be timestamp without timezone. In that case database will not send information to knex about in which timezone that returned time was.
So knex (or rather pg driver which knex is using) interprets your timestamp as local time, which depends of timezone setup of your application server running knex.
You could fetch time just as UTC and do timezone conversion in JavaScript side with moment or luxon libraries (IMO latter is better for timezone handling).
Other solution would be to tell pg driver that timestamp and timestamp with timezone types should not be converted to JavaScript Date objects.
It can be done like this (https://github.com/brianc/node-pg-types):
const types = require('pg').types;
const TIMESTAMPTZ_OID = 1184;
const TIMESTAMP_OID = 1114;
types.setTypeParser(TIMESTAMPTZ_OID, val => val);
types.setTypeParser(TIMESTAMP_OID, val => val);
This code which makes all timestamps to be returned as strings may be added to for example in start of knexfile.js. Those returned strings will be exactly in the same format that they were returned by database server itself.
EDIT:
In code in the original post, when timestamp is converted to be in time zone UTC database server converts timestamp with time zone type to be normal timestamp without time zone so returned value doesn't have timezone information. To add timezone information back you can for example append +02 to the end of returned time stamp like this:
select ('2010-01-01T00:00:00.000Z'::timestamptz AT TIME ZONE 'UTC')::text || '+00';
Which returns 2010-01-01 00:00:00+00 to the driver which can be read correctly by pg driver too.
This will effectively do the same thing that just setting SET TIME ZONE 'UTC'; in db server when connection is created and just returning timestamptz column directly:
SET TIME ZONE 'UTC';
select '2010-01-01T00:00:00.000+02:00'::timestamptz;
Which will return 2009-12-31 22:00:00+00.

storing timestamp in meteor mongo collection and then displaying it

I have a simple form which when submitted enters data into a meteor mongo collection. I then output the data just submitted into another div, kind of like tweets being submitted and shown in a timeline.
I'd like to store the timestamp of when the user submitted the form into the collection and then display the 'feed' ordered by the timestamp descending, so newest first. I'm currently using moment.js to record the timestamp in the collection and then simply use that timestamp on the output, but it doesnt seem the most efficient way to do this.
I intend to have users in different time zones submitting the form and therefore would like to be able to display the timestamps submitted in UTC ordered by most recent.
Currently I have...
Template.form.events({
'submit form': function(e) {
e.preventDefault();
var insertPost = {
timestamp: moment().format('DD-MM-YY HH:mm:ss ZZ')
// some other stuff as well
};
form._id = Posts.insert(insertPost);
)};
Then this is being displayed in my post_item.html :
<template name="post-item">
<div>
<ul class="list-inline">
<li><small>{{timestamp}}</small></li>
// some other stuff too
</ul>
</div>
</template>
Is this way of storing the timestamp ok? I feel storing it in milliseconds is probably better and then formatting that on the output.
So I can change my form.events code to store
timestamp: moment.utc().valueOf(),
and this stores in milliseconds since the epoch, but how do I then convert that within the html template to display the timestamp nicely formatted?
Use moment js to display dates and times in various formats and the atmosphere package has plenty of installs.
http://momentjs.com
https://atmospherejs.com/momentjs/moment

OData Date Filtering from JS

I am using the DXTREME framework from Devexpress to connect a HTML mobile app to an OData source.
One of my tables in SQL Server, exposed through the OData service is a table with a date (not datetime) field in it. It is exposed through OData like this:
<d:TaskDate m:type="Edm.DateTime">2010-04-01T00:00:00</d:TaskDate>
I am trying to filter the data on this field through a calendar control, but when I try to filter the datasource on the JS side, I get no matches. This is because the date is passed to the OData service, I believe, in UTC format, so if I query for TaskDate = '10/JUL/2013', I believe the date is passed as "09/JUL/2013 14:00". If I filter on TaskDate > '10/JUL/2013' I get results back from after "09/JUL/2013 14:00" at any rate.
I have tried declaring a new date with no time part:
filterDate = new Date(2013, 6, 10)
but is still doesn't work, it still subtracts 10 formy time zone on the JS side.
What I want to do is to return a lists of Tasks valid on that particular date. How can I achieve this?
I think my problem was the confusion around the dxDateBox control returning just a date, and that date being changed when passed to my odata service.
I solved the issue by converting the date to UTC myself, but just using the Date parts from the control, (where filterDate came from the control):
var paramDate = new Date(Date.UTC(this.filterDate().getFullYear(), this.filterDate().getMonth(), this.filterDate().getDate()));
this.dataSource.filter(["TaskDate", "=", paramDate]);
This works nicely, but seems rather verbose.

Categories

Resources