How to parse JSON Date object in NodeJS? - node.js

How to parse json date like /Date(1391802454790-0700)/ to (01/31/2014 11:44 AM) in NodeJS.
JSON Date Object:
{
...,
"BirthDate":"\/Date(1391802454790-0700)\/",
...
}
I tried below code but it doesn't work:
var jsondate = "/Date(1391802454790-0700)/";
const data = JSON.parse(jsondate);
console.log(data);

let obj = {
birthday: "/Date(1391802454790-0700)/",
};
let regex = /\(([^)]+)\-\d+/g;
let match = regex.exec(obj.birthday);
if (match) {
console.log(match[1]);
console.log(new Date(Number(match[1]))); // 2014-02-07T19:47:34.790Z - You can use libs to format date
}

uhmm, You just gotta use the value of Birthdate and replace the unwanted characters so you can obtain 1391802454790 part; after that you just need to create a valid date out of this 1391802454790 in the desired format with new Date():
let data = {
...,
"BirthDate":"\/Date(1391802454790-0700)\/",
...
};
let birthdate = data.Birthdate;
birthdate = birthdate.replace("/Date(", "").replace("-0700)/", "");
let formatedBirthdate = new Date(birthdate);

Related

fs.readFileSync gives duplicated results when reading JSON files in node.js

I got two JSON files that I'm processing:
sorted/apr-total2.json
sorted/may-total2.json
There are files for other months of the year, but for debugging purposes I'm focusing on these two because they are causing the problem.
They contain simple data in the following format:
[
["John", 1403],
["Peter", 1159],
...
]
However, John is available only in sorted/apr-total2.json file and not in sorted/may-total2.json.
My code is the following:
let months = ["apr", "may"];
let dataToSort = {};
function getDataFromJSONFile(month) {
let jsonData = fs.readFileSync(`sorted/${month}-total2.json`);
let convertedData = JSON.parse(jsonData);
return convertedData;
}
function arrayToObject(data) {
data.forEach((user) => {
dataToSort[user[0].toString()] = user[1];
});
return dataToSort;
}
for (let i in months) {
let currentMonth = months[i];
console.log("Current month is " + currentMonth);
let getDataForMonth = getDataFromJSONFile(currentMonth);
let convertedMonth = arrayToObject(getDataForMonth);
if (convertedMonth.hasOwnProperty("John") == true) {
console.log(true);
}
}
My output is the following:
Current month is apr
true
Current month is may
true
This isn't correct, since user John isn't available in sorted/may-total2.json. So why is this happening? It seems that the object convertedMonth is causing the issue.
If I add the following code at the end of the for loop and delete the ConvertedMonth object properties:
for (let item in convertedMonth) {
delete convertedMonth[item];
}
It works as intended:
Current month is apr
true
Current month is may
I want to know why this object is causing the issue, because I reused the same code in another place of my project.
Your arrayToObject function uses a single global dataToSort, so any entries will be accumulated and overwritten there. See:
> let dataToSort = {};
> function arrayToObject(data) {
... data.forEach((user) => {
... dataToSort[user[0].toString()] = user[1];
... });
... return dataToSort;
... }
> arrayToObject([["foo", 123]])
{ foo: 123 }
> arrayToObject([["foo", 456], ["bar", 567]])
{ foo: 456, bar: 567 }
Your program simplifies to something like
let months = ["apr", "may"];
for (let currentMonth of months) {
console.log("Current month is " + currentMonth);
let jsonData = JSON.parse(fs.readFileSync(`sorted/${month}-total2.json`));
let convertedMonth = Object.fromEntries(jsonData);
if (convertedMonth["John"]) {
console.log(true);
}
}
which
uses for..of for correct and simpler iteration over the months
uses Object.fromEntries to convert an array of 2-arrays into a plain object (which is what your arrayToObject did)

Get Date from Nested Array of Objects and set that date as an Key in Node.js

I'm using Node.js I have data like this:
const data= [
{"id":"1","date":"2022-09-07T15:56:32.279Z","req_id":"98"},
{"id":"2","date":"2022-09-08T15:48:19.075Z","req_id":"97"},
{"id":"3","date":"2022-09-06T15:48:19.073Z","req_id":"96"}
{"id":"4","date":"2022-09-06T15:48:19.073Z","req_id":"96"}
]
I want data in this format:
expected Output:
"2022-09-06":[
{"id":"4","date":"2022-09-06T15:48:19.073Z","req_id":"96"},
{"id":"3","date":"2022-09-06T15:48:19.073Z","req_id":"96"}
]
"2022-09-08":[
{"id":"2","date":"2022-09-08T15:48:19.075Z","req_id":"97"}
]
"2022-09-07":[
{"id":"1","date":"2022-09-07T15:56:32.279Z","req_id":"98"}
]
Assuming the dates are always in the same format, I would do something like this:
function mapData(data){
// returns the given date as an string in the "%dd-%mm-%yyyy" format
const getDateWithoutTime = (dateString) => dateString.split("T")[0];
const mappedData = [];
for(const req of data){
const formattedDate = getDateWithoutTime(req.date);
// if the key already exists in the array, we add a new item
if(mappedData[formattedDate]) mappedData[formattedDate].push(req);
// if the key doesn't exist, we create an array with that single item for that key
else mappedData[formattedDate] = [req];
}
return mappedData;
}
Straightforward solution using regex:
let result = new Map();
for (const item of data) {
let date = item['date'].match(/\d{4}-\d{2}-\d{2}/)[0];
let items = result.get(date) || [];
items.push(item);
result.set(date, items)
}

Knex get formatted time from a time column and date column

I have a column defined with type time and column defined with type date.
knex.schema.createTable('receipt', function(table) {
...
table.date('t_date');
table.time('t_time');
...
});
It stores data in 24hour format in Database. eg: 22:00:00. Date as '2018-11-30'. But when I run a select query it returns.
{
...
"transactionDate": "2018-11-29T00:00:00.000Z",
"transactionTime": "1970-01-01T22:20:00.000Z",
...
}
How to get date from select query with date with format YYYY-MM-dd and time as HH:mm:ssAM/PM?
Next snippet works like a charm for me:
const { setTypeParser, builtins } = require('pg').types;
const typesToReset = [
builtins.DATE,
builtins.TIME,
builtins.TIMETZ,
builtins.TIMESTAMP,
builtins.TIMESTAMPTZ,
];
function resetPgDateParsers() {
for (const pgType of typesToReset) {
setTypeParser(pgType, val => String(val)); // like noParse() function underhood pg lib
}
}
...and call this function before using your pg or library/orm depends on pg (knex, objection etc.) requests.
sources: https://github.com/Vincit/objection.js/issues/663#issuecomment-351678734 and console.log(pg.types)
Selecting the format in which dates etc. column types are returned in javascript is done by database driver and not in knex.
For postgresql
Can we always fetch date column as string (varchar) with knex and postgres?
and for mysql
Knexjs returning mysql timestamp, datetime columns as Javascript Date object
should help.
oracleDb Users have to set this environment variable
export ORA_SDTZ='UTC'
Further info: https://community.oracle.com/docs/DOC-1008911
This solution is working fine for me with PostgreSQL 12.
Moment will also resolve the timezone.
const knex = require('knex');
const moment = require('moment');
const { setTypeParser, builtins } = require('pg').types;
setTypeParser(builtins.DATE, val => moment(val).format('YYYY-MM-DD'));
setTypeParser(builtins.TIME, val => moment(val).format('HH:mm:ss'));
setTypeParser(builtins.TIMETZ, val => moment(val).format('HH:mm:ss'));
setTypeParser(builtins.TIMESTAMP, val => moment(val).format('YYYY-MM-DD HH:mm:ss'));
setTypeParser(builtins.TIMESTAMPTZ, val => moment(val).format('YYYY-MM-DD HH:mm:ss'));
const db = knex({
client: 'pg',
connection: {
host : 'localhost',
user : 'MHamzaRajput',
password : 'My#pass#123',
database : 'my_db',
}
})
var data = {
"transactionDate": "2018-11-29T00:00:00.000Z",
"transactionTime": "1970-01-01T2:22:00.000Z"
}
var date = data.transactionDate.split("T")[0];
var time = data.transactionTime.split("T")[1].split(".000Z")[0];
let h = parseInt(time.split(":")[0]);
let m = time.split(":")[1];
let s = time.split(":")[2];
let suffix = "AM";
if(h >= 12){
h = h==12 ? 12: h%12;
suffix = "PM";
}
time =("0" + h).slice(-2)+":"+m+":"+s+"/"+suffix;
console.log(date);
console.log(time);

Parse string (node js ) .Find array of numbers into string

\n54766392632990,178.32.243.13,wfsdsfsdfs23432,\n54766393632990,178.32.243.13,
Above u can see example of string which I want to parse.. I want to get array if numbers which exist between (\n....,178.32.243.13) .. In this example it will be smth like :
[54766392632990,54766393632990] - how to make it
Please run this script it full file your requirement
var ss = "\n54766392632990,178.32.243.13,wfsdsfsdfs23432,\n54766393632990,178.32.243.13,"
var ddd = ss.split(",")
console.log(ddd)
var dfd = []
ddd.forEach(function(res){
if(res.startsWith("\n"))
{
dfd.push(res.replace("\n",""))
}
})
console.log(dfd)
Result [ '54766392632990', '54766393632990' ]
"\n54766392632990,178.32.243.13,wfsdsfsdfs23432,\n54766393632990,178.32.243.13,"
.split("\n")
.filter((n)=> n!== "")
.map(n=> parseInt(n.split(",")[0]))
You can do something like this to parse this string
let s = "\n54766392632990,178.32.243.13,wfsdsfsdfs23432,\n54766393632990,178.32.243.13,"
s = s.split("\n");
let array = [];
for(let i=0;i<s.length;i++) {
let v = s[i].split(",178.32.243.13,");
for(let j=0;j<v.length;j++) {
if(!isNaN(parseInt(v[j]))) {
array.push(v[j]);
}
}
}
console.log(array);

moment.js reverse .fromNow()

So i'm working with moment.js.
I see you can translate a date into a human-friendly format using moment().fromNow();
Is there a way to do the opposite?
For example, I want to turn this --> "2 weeks ago" into a normal date format or UNIX timestamp.
I sifted through the documentation but couldnt find anything. Any direction would help, thanks.
Depending on how complicated/different the input strings can be, you could do this:
//parse out the number and the duration
var inputString = "2 weeks ago";
var myRegExp = /^(\d+)\s(\w+)\sago$/;
var results = myRegExp.exec(inputString);
var num = results[1];
var duration = results[2];
moment().subtract(duration,num).toString() //or whatever format you prefer
Note this will work for input strings of the format "number duration ago".
Hope that helps!
In some cases .fromNow() returns string like "30+ days ago". The regex provided in above solution doesn't handle to parse that properly.
Here's the updated regex to handle that case:
var myRegExp = /^(\d+)\+?\s(\w+)\sago$/;
Here is the method that I used to reverse it for the current moment.js locale. I tested it on a few locales and it should work for every locale but it might not.
Change the last two .toString() functions to .valueOf() to get numerical values.
Moment actually doesn't have the week name data for all languages right now, so the function will assume that the string is a week if it could not find the value.
Some languages use translation functions instead of having built in values so the script will not work on those either! If you manually specify your language data then it should work.
//test en locale
moment.locale("en");
console.log(reversefromNow("5 days ago"));
console.log(reversefromNow("in 5 days"));
//test ja locale
moment.locale("ja");
console.log(reversefromNow("5 日前"));
console.log(reversefromNow("5 日後"));
function reversefromNow(input) {
let relativeLocale = JSON.parse(JSON.stringify(moment.localeData()._relativeTime));
let pastfutureObject = {
future: relativeLocale.future,
past: relativeLocale.past
};
delete relativeLocale.future;
delete relativeLocale.past;
//detect if past or future
let pastfuture;
for (const [key, value] of Object.entries(pastfutureObject)) {
if (input.indexOf(value.replace("%s", "")) != -1) {
pastfuture = key;
}
}
//detect the time unit
let unitkey;
for (const [key, value] of Object.entries(relativeLocale)) {
if (input.indexOf(value.replace("%d", "")) != -1) {
unitkey = key.charAt(0);
}
}
//if its not in the data, then assume that it is a week
if (unitkey == null) {
unitkey = "w";
}
const units = {
M: "month",
d: "day",
h: "hour",
m: "minute",
s: "second",
w: "week",
y: "year"
};
//Detect number value
const regex = /(\d+)/g;
let numbervalue = input.match(regex) || [1];
//Add if future, subtract if past
if (pastfuture == "past") {
return moment().subtract(numbervalue, units[unitkey]).valueOf();
} else {
return moment().add(numbervalue, units[unitkey]).valueOf();
}
}

Resources