Browser Time different from MySQL Time - javascript

I'm currently working on a NodeJS-MySQL project, I'm making a controller for a table (graduates). This table has two attributes (created_at, updated_at) that receive the current date and time. The problem is: when I GET the values from this table in the Browser/Insomnia, the date is in the UTC 0 time zone (not what I want), but when i check directly on MySQL, it is in the UTC -3 (my time zone/what i want). In order to get the date values i'm using moment.js and moment-timezone.js.
Some parts of my code:
var moment = require('moment');
var moment = require('moment-timezone');
moment().tz("America/Sao_Paulo").format();
setting up moment.js (setting the timezone to Sao_Paulo didn't change anything, probably i'm using it wrong)
const result = await mysql.execute("SELECT * FROM graduates;")
const response = {
length: result.length,
graduates: result.map(graduate => {
return {
id: graduate.id,
nomeGrad: graduate.nomeGrad,
description: graduate.description,
created_at: graduate.created_at,
updated_at: graduate.updated_at
}
})
}
Get for the table graduates (on MySQL, when I use "SELECT * FROM graduates", I get the same values, the only difference being the time)
var dateTime = moment().tz("America/Sao_Paulo").format();
try {
const query = 'INSERT INTO graduates (id, nomeGrad, description, created_at, updated_at) VALUES (?,?,?,?,?)';
const result = await mysql.execute(query, [
req.body.id,
req.body.nomeGrad,
req.body.description,
created_at = dateTime,
updated_at = dateTime
]);
And this is how I Post the graduates. Now for the outputs:
{
"id": "43",
"nomeGrad": "iiiiiiiiiiiiiiiiiiiiiii",
"description": "ssssssssssssssssssssssssss",
"created_at": "2021-10-26T23:44:10.000Z",
"updated_at": "2021-10-26T23:44:10.000Z"
}
The above output is from Insomnia / Browser (Time is 23:44)
# id, nomeGrad, description, created_at, updated_at
'43', 'iiiiiiiiiiiiiiiiiiiiiii', 'ssssssssssssssssssssssssss', '2021-10-26 20:44:10', '2021-10-26 20:44:10'
The above output is from directly typing "SELECT * FROM graduates" on MySQL (Time is 20:44)
Thank you for your time and patience for reading this.

Related

Mongoose lte method not working for moment

I am fetching Date saved in db. Then, I am doing a small date maths to substract date from today from 3, which is giving me Date in Format - (DD-MM-YYYY). Date saved in db format is also same - (DD-MM-YYYY). Can anyone help me out in validating $lte for that date. I am not getting any log for DipData.
nodeCron.schedule("* * * * *", async function () {
var DateNow = await moment().subtract(3, "days").format("DD-MM-YYYY");
console.log("Test Date Cron",DateNow);
console.log("-->",new Date(DateNow.format("DD-MM-YYYY")));
let DipData = await userModel.find({}, { LastAppOpenedTime: { $lte : new Date(DateNow.format("DD-MM-YYYY")) }})
console.log("-----DipData ------->", DipData);
});
First thing you need to identify if there is date which is stored in document of mongo collection is string or regular date format or epoch format. If it's string the query may gives not accurate result. If there is date format or epoch format, you can easily queried your result with proper result.
Therefore in case if there is string in LastAppOpenedTime document key you can have query with $toDate under find query.
If key is not in string format in stored document following code will work.
var DateNow = moment().subtract(3, "days");
const DipData = await userModel.find({ LastAppOpenedTime: { $lte: new Date(DateNow) } });
For the above two scenario would work if your query is in accurate form like removing the first empty braces.
userModel.find({}, { LastAppOpenedTime: { $lte : new Date(DateNow) }})
to
userModel.find({ LastAppOpenedTime: { $lte : new Date(DateNow) }})
Hello I got this working by making a few changes
const DateNow = await moment().subtract(3, "days");
console.log("Test Date Cron", DateNow);
console.log("-->", new Date(DateNow));
const DipData = await userModel.find({ createdAt: { $lte: new Date(DateNow) } });
console.log("-----DipData ------->", DipData);
res.status(200).json({ success: true, message: "Request was successful", DipData });
I noticed you had the .format("DD-MM-YYYY") at the end of your moment function but it returned a string that couldn't be converted with the new Date(DateNow). I removed mine when testing as the response from the moment was working fine without it.
And also I updated your userModel.find({}, { LastAppOpenedTime: { $lte : new Date(DateNow.format("DD-MM-YYYY")) }}) to remove the first empty {}. So you would have userModel.find({ createdAt: { $lte: new Date(DateNow) } });

TypeORM query all records from today

I am trying to query all records from today but I get nothing, so My question is:
How to query with date validations in TypeORM?
My code:
all = await connection
.createQueryBuilder(Earnings, 't0')
.addSelect('t3.id', 't3_id')
.addSelect('t3.UID', 't3_UID')
.addSelect('t3.name', 't3_name')
.addSelect('t3.chips', 't3_chips')
.addSelect('t3.tickets', 't3_tickets')
.addSelect('t3.masteredLevel', 't3_masteredLevel')
.addSelect('t2.UID', 't2_UID')
.addSelect('t2.name', 't2_name')
.addSelect('t2.rule', 't2_rule')
.addSelect('t1.id', 't1_id')
.innerJoin(Questions, 't1', 't0.questionID = t1.id')
.innerJoin(Lessons, 't2', 't1.lessonUID = t2.UID')
.innerJoin(Topics, 't3', 't2.topicUID = t3.UID')
.where('t0.challenge = 1')
.andWhere('t0.createdAt = :today')
.andWhere('t0.userID = :userID')
.setParameters({ userID: user.id })
.setParameters({ today: moment() })
.getRawMany()
Your .andWhere('t0.createdAt = :today') only selects rows created at the instant of today parameter. You have set this parameter as moment(), which is not a date.
Since we can safely assume no rows will be created in the future, your simplest solution here is: .andWhere('t0.createdAt >= :today'), which selects rows created AFTER 00:00 today.
You can combine the addWhere and setParameters into one:
.andWhere('t0.createdAt >= :today', { today: moment().toDate() }) // note moment.toDate()
Alternatively use the MySql CURDATE() function to get the current date:
.andWhere('t0.createdAt >= CURDATE()')
When you test this, I recommend that you turn on TypeOrm full logging so you can see the actual generated SQL and you will be able to quickly solve any problems. See TypeOrm logging.
For TypeORM + PSQL
Sort items by today's date
.andWhere('t0.createdAt >= CURRENT_DATE')

Query by date and time only, without year using SQLite

I am storing birthdays in my SQLite database, they are dates converted to my own timezone from another timezone, every hour I want to query my database to get the dates that are the same day and hour
// Stored in DB:
const date = parseFromTimeZone(`2020-${bdayReply} 13:42:00`, { timeZone });
// Query
const birthday = await Birthday.findOne({ where: { date: new Date() } });
// Generated query
query: SELECT "Birthday"."id" AS "Birthday_id", "Birthday"."userId" AS "Birthday_userId", "Birthday"."date" AS "Birthday_date", "Birthday"."birthdayConfigGuildId" AS "Birthday_birthdayConfigGuildId" FROM "birthday" "Birthday" WHERE "Birthday"."date" = ? LIMIT 1 -- PARAMETERS: ["2020-02-03T07:42:00.005Z"]
// Output of new Date() at the time of running the query
2020-02-03T07:42:00.023Z
// Example of record active in my DB at that point (date var from earlier)
2020-02-03 07:42:00.000
The ORM I'm using allows for raw queries as well, now I was wondering what my query should look like to return the above record in the example, or maybe I can use a date library like date-fns to convert the new Date() to match the format of the database, what would that look like?
If you want to use an SQL raw query, it should looks like this :
SELECT * FROM my_table WHERE MONTH(my_date) = MONTH(NOW()) AND DAY(my_date) = DAY(NOW())
In SQLite, the syntax is :
SELECT * FROM my_table WHERE strftime('%m',my_date) = strftime('%m','now') AND strftime('%d',my_date) = strftime('%d','now')

javascript + postgres: timezone and timestamp usage

I'm not quite understanding the timestamp usage,
e.g.
User create article and they can choose PublishDate , the system also store CreateDate automatically.
a. Should I make PublishDate and CreateDate timestamp with time zone and set utc?
b. User post string and then I convert like below use momentjs to utc timestamp and store, when someone select this row , show them as user client time reverse use momentjs
c. I use CURRENT_TIMESTAMP to the CreateDate, the CURRENT_TIMESTAMP does that mean the server time? am I doing correct?
My thinking is I always insert utc timezone timestamp to the database, and wherever the place user/client read, convert the data to user/client timezone? am I doing correct?
a. my database(postgres) created by
CREATE TABLE IF NOT EXISTS "Article"(
"ArticleId" SERIAL NOT NULL,
"PublishDate" timestamp with time zone,
"Active" bit NOT NULL,
"CreateByUserId" integer,
"CreateDate" timestamp with time zone,
PRIMARY KEY ("ArticleId")
);
SET timezone = 'UTC';
b. user submit post to store (nodejs)
// publishDate: '{"y":2015,"m":8,"d":16,"h":15,"mi":46,"s":24}
var publishDate = JSON.parse(req.body.publishDate);
var leadingZeroAndDateFormat = function(publishDate) {
return new Promise(function (fulfill, reject){
if (publishDate.m < 10) { publishDate.m = '0'+publishDate.m; }
if (publishDate.d < 10) { publishDate.d = '0'+publishDate.d; }
if (publishDate.h < 10) { publishDate.h = '0'+publishDate.h; }
if (publishDate.mi < 10) { publishDate.mi = '0'+publishDate.mi; }
if (publishDate.s < 10) { publishDate.s = '0'+publishDate.s; }
var str = publishDate.y+'-'+publishDate.m+'-'+publishDate.d+' '+publishDate.h+':'+publishDate.mi+':'+publishDate.s;
var utc = moment(str).unix();
fulfill(utc);
});
};
c. insert to database the CreateDate use CURRENT_TIMESTAMP
var insertArticle = function(publishDate, active, createByUserId) {
return new Promise(function (fulfill, reject){
var query = 'INSERT INTO "Article" ("PublishDate","Active","CreateByUserId","CreateDate") VALUES ($1,$2,$3,CURRENT_TIMESTAMP) RETURNING "ArticleId"';
dbClient.query(query,[publishDate,active,createByUserId], function(error, result) {
if (error) {
reject(error);
} else {
fulfill(result);
}
});
});
};
Update
When I change all column without timezone then I execute insertArticle shows the error
{ [error: date/time field value out of range: "1439717298"]
name: 'error',
length: 158,
severity: 'ERROR',
code: '22008',
detail: undefined,
hint: 'Perhaps you need a different "datestyle" setting.',
position: undefined,
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'datetime.c',
line: '3775',
routine: 'DateTimeParseError' }
var insertArticle = function(publishDate, active, createByUserId) {
return new Promise(function (fulfill, reject){
var query = 'INSERT INTO "Article" ("PublishDate","Active","CreateByUserId","CreateDate") VALUES ($1,$2,$3,$4) RETURNING "ArticleId"';
dbClient.query(query,[publishDate,active,createByUserId,moment.utc().unix()], function(error, result) {
if (error) {
reject(error);
} else {
fulfill(result);
}
});
});
};
The simplest way is to always store time stamps without time zone and in UTC. This way it is always easy to use them for display and calculations. A difference is just a subtraction and comparisons go directly.
If the column was a time stamp with time zone, then the input would be converted to UTC anyway, but the output would be in the currently set time zone and if it's not set properly it might show wrong values. It also makes the database less efficient.
In the presentation layer the timestamps can be shown in the proper time zone and values input can also be converted to UTC for storage.
This is the simplest, most efficient and most flexible way of handling timestamps.
Using CURRENT_TIMESTAMP will get the timestamp from the server at the time of execution.
The incoming timestamps without timezone are parsed in local time instead of UTC -- I'd call this a bug in node-postgres. Anyway, you can override it to do the right thing by adding the following code:
pg.types.setTypeParser(1114, function(stringValue) {
console.log(stringValue);
return new Date(Date.parse(stringValue + "+0000"));
})

Problems in setting a date constraint on a parse query

I'm trying to make a parse query and put a date constraint on the query via javascript API.
This is the Result table/object (on parse.com) which I'm making a query for:
Column Data type
objectId String
createdDate Date
updatedAt Date
obtainedPonts Number
relatedDriver Relation
relatedTest Relation
ACL ACL
resultCeasesToBeValid Date
didPassTheTest Boolean
Some example data from resultCeasesToBeValid:
This is my goal: I want the query to give me a set of Result where today < resultCeasesToBeValid.
My problem is that I always recieve an Result array with .length = 0 when I'm trying to put date constraints on the query.
function IsApprovedAndHasValidResults(currentDriverObjectId) {
var Driver = Parse.Object.extend('Driver');
var currentDriverObject = new Driver();
currentDriverObject.id = currentDriverObjectId;
var queryResult = new Parse.Query(Result);
//set the constraints
queryResult.equalTo('relatedDriver', currentDriverObject); //this constraint works as expected
/****************************************************************************************************
*var today = new Date(); // "today" is as time of writing 3 oct 2014 *
* *
* //will give me a parseResults[] of .length=0: *
*queryResult.lessThan('resultCeasesToBeValid', today); *
* *
* //will give me a parseResults[] of .length=0: *
*queryResult.lessThan('resultCeasesToBeValid', { "__type": "Date", "iso": today.toISOString() }); *
* *
*****************************************************************************************************/
queryResult.find({
success: function (parseResults) {
// results is an array of Parse.Object.
/*when the code gets here parseResults array.lenght equals 0*/
},
error: function (error) {
// error is an instance of Parse.Error.
/*will never be here*/
}
});
}
Other developers seem to have the same problem, user Abhishek suspects a bug. According to Héctor Ramos (Parse), long time ago: "You should use a Date object, not a string, when dealing with dates in JavaScript.". Obviously this doesn't work!
Is my code wrong in some way?
Workaround:
queryResult._where.resultCeasesToBeValid = {'$lt' :{ "__type": "Date", "iso": today}}};
_where is a "private property" though and i wouldn't rely on it too much. Parse should fix this.
If you can [change the column type], i would suggest storing the date as a unix timestamp to avoid this kind of issues:
var timestamp = +new Date();
result.save({'resultCeasesToBeValid': timestamp});

Categories

Resources