Getting actual offset of a SQLServer DateTimeOffset column in Node - node.js

Using Node + mssql, I need to get the offset for the date that is returned from SQL Server for this query:
SELECT getutcdate() AT TIME ZONE 'UTC' AT TIME ZONE 'Mountain Standard Time'
The issue is it comes out of mssql/tedious already parsed as a JavaScript Date() object, set to the time zone of the script/host machine. There is no way that I can see to tell what time zone/offset the original value is actually in.
Other tools, such as Azure Data Studio, correctly show the raw value in the table for DateTimeOffset columns, including showing the stored offset.
Output in Node:
[ { value: 2020-03-21T03:07:54.193Z } ]
Output in Azure Data Studio:
2020-03-20 21:07:22.9970000 -06:00
Code:
const sql = require('mssql');
sql.connect('mssql://sa:<password>#localhost?useUTC=false')
.then(() => {
const request = new sql.Request();
request.query(query, (err, result) => {
console.dir(result.recordset)
});
});

Related

Issue with date range on nodeJS

I have issues while filtering data from mongodb using nodejs and nextjs.
I am not getting some of the data stored in the database especially if the moment is not this month.
My Routes:
module.exports.getFulfullmentByDateRange = (params) => {
return Fulfillment.find({ createdOn: { $gte: moment(params.dateFrom).format('YYYY-MM-DD'), $lte: moment(params.dateTo).format('YYYY-MM-DD') } }).then(fulfillment => {
return fulfillment
})
}
This only allows me to filter selected data. What I'm trying to achieve is to get all data using the selected range from the from and to datetime picker.

Sequelize failed to update datetime datatype in SQL Server

I am trying to update SQL Server 2012 via sequelize CRM and getting the below error. My datatype for the column ins DateTime.
(node:33100) UnhandledPromiseRejectionWarning: SequelizeDatabaseError: Conversion failed when converting date and/or time from character string.
Configuration
const Sequelize = require('sequelize');
const config = require('../config/config');
// Override timezone formatting for MSSQL
Sequelize.DATE.prototype._stringify = function _stringify(date, options) {
return this._applyTimezone(date, options).format('YYYY-MM-DD HH:mm:ss.SSS');
};
class SequelizeConnection {
connect() {
const sequelize = new Sequelize(config.database, config.username, config.password, config.options);
sequelize
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
return sequelize
}
get() {
return this.connect()
}
}
const sequelize = new SequelizeConnection().get()
module.exports = sequelize;
in my model as below...
const { Sequelize } = require("sequelize");
const sequelize = require("../db/sequelize");
const User = sequelize.define('DB_USER', {
......
....
DATE_OF_BIRTH: {
type: Sequelize.DATE,
notEmpty: true,
allowNull: false,
},
.....
module.exports = User
My update command to the table as follows
else if (arg.table === 'users') {
console.log(`table type is users ${arg.id} - ${arg.table}`)
if (arg.type === 0) {
User.update(data, {
where: { USER_ID: arg.id },
}).then(e => {}).then(e => {
event.sender.send('asynchronous-reply', _sync());
})
}
There are many string formats supported for date & time by SQL Server - see the MSDN Books Online on CAST and CONVERT. Most of those formats are dependent on what settings you have - therefore, these settings might work some times - and sometimes not. And also, the DATETIME datatype is notoriously picky about what string literals it considers valid dates&times.
The way to solve this is to use the (slightly adapted) ISO-8601 date format that is supported by SQL Server - this format works always - regardless of your SQL Server language and dateformat settings.
The ISO-8601 format is supported by SQL Server comes in two flavors:
YYYYMMDD for just dates (no time portion); note here: no dashes!, that's very important! YYYY-MM-DD is NOT independent of the dateformat settings in your SQL Server and will NOT work in all situations!
or:
YYYY-MM-DDTHH:MM:SS for dates and times - note here: this format has dashes (but they can be omitted), and a fixed T as delimiter between the date and time portion of your DATETIME.
This is valid for SQL Server 2000 and newer.
If you use SQL Server 2008 or newer and the DATE datatype (only DATE - not DATETIME!), then you can indeed also use the YYYY-MM-DD format and that will work, too, with any settings in your SQL Server.
Don't ask me why this whole topic is so tricky and somewhat confusing - that's just the way it is. But with the YYYYMMDD format, you should be fine for any version of SQL Server and for any language and dateformat setting in your SQL Server.
The recommendation for SQL Server 2008 and newer is to use DATE if you only need the date portion, and DATETIME2(n) when you need both date and time. You should try to start phasing out the DATETIME datatype if ever possible

Timezone problems with MongoDB and NodeJs

So the problem I'm currently having is :
I've a list of gym classes, which every class has an OpeningTime. I want to fetch all the classes from the current day, but. I'm not getting the same result locally and in production, cause for some reason, when Im deploying my backend to Heroku, the timezone is being setted by default to UTC (when I've a GMT-3 timezone).
Here is my query :
var now = moment();
var startOfDay = now.startOf('day').format();
var endOfDay = now.endOf('day').format();
var clasesDB = await Clase.find({ $and: [{ openingTime: { $gte: startOfDay } }, { openingTime: { $lte: endOfDay } }] })
So, like I said before, the problem is ocurring when, for example:
When I fetch the classes at my local time (Ex: 02-26-19 21:00hs ( GMT-3) ), the queries are actually showing the classes from 02-27, because, at MINE 21:00hs, on the server side is already 00:00, so, the date is not 02-26 anymore. And I dont want this kind of output.
How can I get a workaround to solve this?
Thanks in advance! :)
Don't use .format(), this makes a string. Compare directly Date values, i.e. use
var now = moment();
var startOfDay = now.startOf('day').toDate();
var endOfDay = now.endOf('day').toDate();
By default moment uses local times, so moment().startOf('day') returns midnight of local time. If you want to get midnight of UTC then use moment.utc().startOf('day').
If you don't rely on "local" time zone, then you can specify it like moment.tz("America/New_York").startOf('day')
No matter which time you need, never compare Date values by string, use always actual Date value.
By default in MongoDB a date field is stored in UTC, You can create a date with offset while writing to store it in your timeZone. But you've not done it while writing documents then you need to convert date field to your required timeZone while reading data from database. Check this below example.
JavaScript Code :
const today = new Date().toLocaleDateString(undefined, {
day: '2-digit',
month: '2-digit',
year: 'numeric'
}) // 02/26/2020. If your Heroic server is in different location then specify your locale in place of undefined - whereas undefined picks local time by default. Ex:- 'en-Us' for USA
Query :
db.collection.aggregate([
{ $addFields: { timewithOffsetNY: { $dateToString: { format: "%m/%d/%Y", date: "$openingTime", timezone: "America/New_York" } } } },
{ $match: { timewithOffsetNY: today } }, { $project: { timewithOffsetNY: 0 } }
])
Above query is written for New York timeZone, you can convert it according to your timeZone, In test url you can see 1st doc is not returned though it is on 2020-02-26 cause offset to New York as of today is 5hrs, So after converting date becomes as 2020-02-25.
Test : MongoDB-Playground
Ref : $dateToString

Cassandra - NodeJS - Issue while retrieving map type values

I am using helenus in my node-js project to get/set values in cassandra. I have a MapType field inside my Table, but when I retrieve the value from the table, I get an empty key-value set.
Below is the schema for my table
CREATE TABLE datapoints (
id uuid PRIMARY KEY,
created_at timestamp,
properties map<text,text>
);
I have inserted the values from cql using the query below
INSERT INTO datapoints (id, properties) VALUES (24053e20-63e9-11e3-8d81-0002a5d5c51b, { 'fruit' : 'apple', 'band' : 'Beatles' });
Below is my nodejs code:
var helenus = require('/usr/local/lib/node_modules/helenus')
var pool = new helenus.ConnectionPool({
hosts : ['localhost:9160'],
keyspace : 'mykeyspace',
timeout : 3000
});
pool.connect(function(err, keyspace){
if(err){
console.log("connect me error")
throw(err);
} else {
pool.cql("SELECT * FROM datapoints", [], function(err,results){
console.log("results", results)
results.forEach(function(row){
props = row.get('properties').value;
var id = row.get('id').value;
console.log("properties", props);
console.log("id", id);
});
})
}
});
The line console.log("properties", props); returns me a function, and when I call that function, I get an empty key value set. Please help.
It seems there was an issue with the deserialization of the collection types. The pull request that was made in the past broke the deserialization. I just pushed a fix to version 0.6.8 that should take care of this.

How to set expiry for the CouchBase using couchnode

I am storing the data in CouchBase from Node.js app using the following codes (couchnode client):
//Expiry information of couchbase doucumenets. fetched from config.json
//Expiry is less than 30*24*60*60 (30 days)
//The value is interpreted as the number of seconds from the point of storage or update.
//Expiry is greater than 30*24*60*60
//The value is interpreted as the number of seconds from the epoch (January 1st, 1970).
//Expiry is 0
//This disables expiry for the item.
CouchBaseDB.set(keytosave, 60, doctosave, function (err, meta) {
if (err) { console.log(err); } else {console.log('saved');}
});
Unfortunately, the above code is not working (its saving 60 itself instead of object doctosave) and no where its explained how to set expiry othere than Chapter 4. Java Method Summary - 4.4. Expiry Values.
Does any one came across the same and found any work-around/solution or any document support for the same. If explained it would be of great HELP.
Thanks in advance.
Set function looks like this:
function set(key, doc, meta, callback) { ... }
If you want to add expiry for stored key just create meta = {} object and add field expiry to it: meta.expiry = 1000.
Here is link to sources
So to store your doc you need:
var meta = {"expiry":60};
CouchBaseDB.set(keytosave, doctosave, meta, function (err, meta) {
if (err) { console.log(err); } else {console.log('saved');}
});
Note: Also if that key is retreived form couchbase via CouchBaseDB.get(), meta could be extracted from that get function.

Resources