How to find maximum time from array? - ionic-framework

I have an array. I want to find the maximum time from array.
I tried the follwing code.
var maxtm = Math.max.apply(null, this.my_arr.map(function (e) {
return e['time'];
}));
this.my_arr = [{
date: '21-jun-2019',
time: '21:22:00'
}, {
date: '21-june-2019',
time: '11:33:23',
}, {
date: '21-june-2019',
time: '12:12:00'
}]
I expect the output '21:22:00', but the actual output is NaN.

Try convert to int parseInt(time.split(':').join(''), 10)
Example
var maxtm = Math.max.apply(null, this.my_arr.map(function (e) { return parseInt(e['time'].split(':').join(''), 10);}));
After you need convert max back to time

Related

Compare data with present date google script

Hi i want to compare column with date (i.e "Referral Date" column)
with present day , here is what i have
function newF(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Worksheet');
var range = ss.getDataRange();
var headers = range.getValues()[0];
var colIndex = headers.indexOf("Referral Date");
var today = new Date();
var searchRange = ss.getRange(2,colIndex+1,ss.getLastRow()-1);
for (i=0;i<range.getLastRow();i++){
var dates = searchRange.getValues();
if (today.valueOf()>dates.valueOf()){
updatelFilter()
} else{
SpreadsheetApp.getUi().alert('Future Date Error');
break;
}
}
}
The problem i have is, it throws alert Future Date Error irrespective of date in column (Referral Date). Let me know if additional information is required.
My goal:
1)if date column (Referral Date) is greater than present date : Throw alert error & should not run updateFilter
2)if (Referral Date) is lesser than present date: Run updateFilter function
Issues
searchRange.getValues() yields a two dimensional array. So dates[0][0] points to a date, while dates[0] points to an array.
var dates = searchRange.getValues(); is being called inside the loop repeatedly, when it should ideally be called outside once since the value will not change; calling it inside the loop is costly and redundant
for (i=0;i<range.getLastRow();i++){ the condition can be replaced with i<dates.length if point 2 is followed
if (today.valueOf()>dates.valueOf()){ I believe is supposed to have dates[0] instead
Modified Code
function newF(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Worksheet');
var range = ss.getDataRange();
var headers = range.getValues()[0];
var colIndex = headers.indexOf("Referral Date");
var today = new Date();
var searchRange = ss.getRange(2,colIndex+1,ss.getLastRow()-1);
var dates = searchRange.getValues().map(d=>d[0]);
for (i=0;i<dates.length;i++) {
if (today.valueOf()>dates[i].valueOf()){
updateFilter()
} else {
SpreadsheetApp.getUi().alert('Future Date Error');
break;
}
}
}
To run updateFilter only if no future dates
Replace the loop with the following -
if(dates.some(d => today.valueOf() < d.valueOf())) {
SpreadsheetApp.getUi().alert('Future Date Error');
} else {
for (let i=0; i<dates.length; i++) {
updateFilter();
}
}

How can I define Date in my defined mongoose Schema such as to return a nicely formated date and time?

So I want to create a task/todo model for my app and for every task I want to have a nice looking date and time of creation in the footer. I have already achieved this successfuly on a similar client side only app,:
function getCurrentDateTime () {
const date = new Date();
let day = date.getDate().toString().length <= 1 ? '0' + date.getDate() : date.getDate();
let month = date.getMonth().toString().length <= 1 ? `0${parseInt(date.getMonth() + 1)}` : date.getMonth();
let year = date.getFullYear().toString().length <= 1 ? '0' + date.getFullYear() : date.getFullYear();
let hours = date.getHours().toString().length <= 1 ? '0' + date.getHours() : date.getHours();
let minutes = date.getMinutes().toString().length <= 1 ? '0' + date.getMinutes() : date.getMinutes();
let seconds = date.getSeconds().toString().length <= 1 ? '0' + date.getSeconds() : date.getSeconds();
return { day, month, year, hours, minutes, seconds };
}
function createTask (statePlaceholder, currentTaskText) {
let newTask = {
id: uuid(),
text: currentTaskText,
completed: false,
creationDateTime: {
date: `${getCurrentDateTime().day}/${getCurrentDateTime().month}/${getCurrentDateTime().year}`,
time: `${getCurrentDateTime().hours}:${getCurrentDateTime().minutes}:${getCurrentDateTime().seconds}`
}
};
...
}
and it looks like this:
I want to save all the tasks elements(text, completed or not and date/time of creation) on MongoDB, and I don't know how to define the date and time so that I get what you see in the image, but comming from MongoDB.
const TaskSchema = new mongoose.Schema({
text: { type: String, required: true },
completed: Boolean,
creationDateTime: {
date: // day/month/year,
time: // timestamp
}
});
How can I properly define the date and time on the mongoose schema defined by me?
What you're trying to store as creationDateTime should definitely be of type Date and you should not store it as string or object. It will make any future querying easier and will let you avoid some unexpected issues which may happen if you stored this value as string. You can take advantage of mongoose's default feature which will run Date.now any time you store a new document so your schema can look like this:
const TaskSchema = new mongoose.Schema({
text: { type: String, required: true },
completed: Boolean,
creationDateTime: {
type: Date,
default: Date.now
}
});
When it comes to formatting, mongoose offers a nice capability of defining virtual properties. Such field will not be stored in a database but will by dynamically evaluated and this is where you can reuse your formatting logic:
function dateTimeToParts(date) {
let day = date.getDate().toString().length <= 1 ? '0' + date.getDate() : date.getDate();
let month = date.getMonth().toString().length <= 1 ? `0${parseInt(date.getMonth() + 1)}`: date.getMonth();
let year = date.getFullYear().toString().length <= 1 ? '0' + date.getFullYear() : date.getFullYear();
let hours = date.getHours().toString().length <= 1 ? '0' + date.getHours() : date.getHours();
let minutes = date.getMinutes().toString().length <= 1 ? '0' + date.getMinutes() : date.getMinutes();
let seconds = date.getSeconds().toString().length <= 1 ? '0' + date.getSeconds() : date.getSeconds();
return { day, month, year, hours, minutes, seconds };
}
TaskSchema.virtual('createdOn').get(function() {
let { day, month, year, hours, minutes, seconds } = dateTimeToParts(
this.creationDateTime
);
return {
date: `${day}/${month}/${year}`,
time: `${hours}:${minutes}:${seconds}`
};
});
So having below document in your MongoDB database:
{
"_id" : ObjectId("5e2e7c93397e8124b81dfcaa"),
"creationDateTime" : ISODate("2020-01-27T06:00:51.409Z"),
"text" : "abc",
"__v" : 0
}
You can run following code:
let task = await Task.findOne({ _id: ObjectId("5e2e7c93397e8124b81dfcaa") });
console.log(task.createdOn);
To get following output:
{ date: '26/01/2020', time: '22:00:51' }

how we can get all document that have period time more than some min

Let assume we have 3 documents. The first one is created 6:00, the second one at 6:25 and the third one at 7:00. How can I write a query to get all documents after 5:45 that the period of time between them is less than 30 min? In current example i want get first and second because the third one is more than 30 min from the last one.
Save period in number format.
collection.find({ period : { $gt : 5:45, $lt : 30}})
var arr = db.times.find( { time: { $gte: ISODate("2019-12-30T04:00:00.000+00:00") } } ).sort( { time: 1 } ).toArray();
const THIRTY_MINS = 30 * 60 * 1000;
var prevTime = arr[0].time;
var set = new Set();
for ( let i = 1; i < arr.length; i++ ) {
if ( ( arr[i].time - prevTime ) <= THIRTY_MINS ) {
set.add( arr[i - 1] );
set.add( arr[i] );
}
prevTime = arr[i].time;
}
var resultArr = [...set];
Verify with input documents:
{ time: ISODate("2019-12-30T06:00:00.000+00:00") },
{ time: ISODate("2019-12-30T06:25:00.000+00:00") },
{ time: ISODate("2019-12-30T07:00:00.000+00:00") }

MongoDB String to Date?

Following is the JSON of the data:
{
projectName: String,
projectDescription: String,
users: [
],
projectManager: [
],
teamLead: [
],
createdBy: String,
superAdmin: String,
createdAt: Date,
task: [
{
userID: String,
name: String,
taskName: String,
nohrs: Number,
description: String,
comments: String,
date: String,
from: String,
to: String,
lastUpdatedDate: String
}
]
}
The array of task contains many tasks for each project. And each task has a date in string format. I need to convert each string date to ISO date format.
How can we achieve this?
I have tried this :
db.projects.find({}).forEach(function(task){
task.date = new Date(task.date);
db.collection.save(task);})
but this is adding a column date and not editing the date in task array?
You were really close to the solution. The correct code snippet would be:
db.projects.find({}).forEach(function(project){
project.task.forEach(function(task){
task.date = new Date(task.date);
});
db.projects.save(project);
})
You needed one more loop in your code :)
Well guys this worked
db.projects.find({}).forEach(function(project){
project.task.forEach(function(task){
// printjson(task)
task.date = new Date(task.date);
print(task.date)
db.projects.save(project);
})})
db.projects.find({},function(err,data){
//this find query will return the array of documents through which we need to iterate
for(var i =0; i<data.length;i++){
//then we want convert the date string into Date we need to iterate task array with in each document.
for(var j = 0;j<data[i].task.length;j++){
data[i].task[j].date = new Date(data[i].task[j].date);
}
}
//now save the new data
data.save();
})

MapReduce sub-document

I am trying to graph email activity that I am recording in a Mongo db. Whenever I send out an email I create a record, then, when there is activity on the email (open, click, mark as spam) I update the document by adding to it's history.
Here is a sample document:
{
"_id" : new BinData(3, "wbbS0lRI0ESx5DyStKq9pA=="),
"MemberId" : null,
"NewsletterId" : 4,
"NewsletterTypeId" : null,
"Contents" : "[message goes here]",
"History" : [{
"EmailActionType" : "spam",
"DateAdded" : new Date("Sat, 10 Dec 2011 04:17:26 GMT -08:00")
}, {
"EmailActionType" : "processed",
"DateAdded" : new Date("Sun, 11 Dec 2011 04:17:26 GMT -08:00")
}, {
"EmailActionType" : "deffered",
"DateAdded" : new Date("Mon, 12 Dec 2011 04:17:26 GMT -08:00")
}],
"DateAdded" : new Date("Mon, 01 Jan 0001 00:00:00 GMT -08:00")
}
What I would like to do is query the database for a specific history date range. The end result should be a list with an item for each day where there is an activity and a total for each activity type:
date: "20111210", spam: 1, processed: 0, deffered: 0
date: "20111211", spam: 0, processed: 1, deffered: 0
date: "20111212", spam: 0, processed: 0, deffered: 1
Here is what I currently have:
db.runCommand({ mapreduce: Email,
map : function Map() {
var key = this.NewsletterId;
emit(
key,
{ "history" : this.History }
);
}
reduce : function Reduce(key, history) {
var from = new Date (2011, 1, 1, 0, 0, 0, 0);
var to = new Date (2013, 05, 15, 23, 59, 59, 0);
// \/ determine # days in the date range \/
var ONE_DAY = 1000 * 60 * 60 * 24; // The number of milliseconds in one day
var from_ms = from.getTime(); // Convert both date1 to milliseconds
var to_ms = to.getTime(); // Convert both date1 to milliseconds
var difference_ms = Math.abs(from_ms - to_ms); // Calculate the difference in milliseconds
var numDays = Math.round(difference_ms/ONE_DAY); // Convert back to days and return
// /\ determine # days between the two days /\
var results = new Array(numDays); //array where we will store the results. We will have an entry for each day in the date range.
//initialize array that will contain our results for each type of emailActivity
for(var i=0; i < numDays; i++){
results[i] = {
numSpam: 0,
numProcessed: 0,
numDeffered: 0
}
}
//traverse the history records and count each type of event
for (var i = 0; i < history.length; i++){
var to_ms2 = history[i].DateAdded.getTime(); // Convert both date1 to milliseconds
var difference_ms2 = Math.abs(from_ms - to_ms2); // Calculate the difference in milliseconds
var resultsIndex = Math.round(difference_ms2/ONE_DAY); //determine which row in the results array this date corresponds to
switch(history[i].EmailActionType)
{
case 'spam':
results[resultsIndex].numSpam = ++results[resultsIndex].numSpam;
break;
case 'processed':
results[resultsIndex].numProcessed = ++results[resultsIndex].numProcessed;
break;
case 'deffered':
results[resultsIndex].numDeffered = ++results[resultsIndex].numDeffered;
break;
}
}
return results;
}
finalize : function Finalize(key, reduced) {
return {
"numSpam": reduced.numSpam,
"numProcessed": reduced.numProcessed,
"numDeffered": reduced.numDeffered,
};
}
out : { inline : 1 }
});
When I run it, I don't get anything, but I'm also not getting any errors, so not really sure where to look.
Your problem is definitely in your Map / Reduce functions. There is a disconnect between your emit and your expected output.
Your expected output:
date: "20111210", spam: 1, processed: 0, deffered: 0
Map / Reduce always outputs in terms of a key and a value. So your output would look like this:
_id: "20111220", value: { spam: 1, processed: 0, deferred: 0 }
Here is the basic premise. Your emit needs to output data of the correct format. So if you emit(key, value), then you should have:
var key='20111220'
var value={spam:1, processed:0, deferred:0}
In your case, you are emitting several times per document as you loop through History. This is normal.
The reduce function is only run if there are multiple values for the same key. So if you have this:
_id: "20111220", value: { spam: 1, processed: 0, deferred: 0 }
_id: "20111220", value: { spam: 1, processed: 2, deferred: 0 }
Then reduce will pull those together and give you this:
_id: "20111220", value: { spam: **2**, processed: **2**, deferred: 0 }
Here is a quick stab at the answer:
map = function() {
for(var i in this.History) {
var key = get_date(this.History[i].DateAdded);
var value = {spam: 0, processed: 0, deffered: 0};
if(this.History[i].EmailActionType == "Spam") { value.spam++; }
else if(....)
...
emit(key, value);
}
}
reduce = function(key, values) {
// values is an array of these things {spam: 0, processed: 0, deffered: 0}
var returnValue = { spam: 1, processed: 0, deffered: 0 };
for(var i in values) {
returnValue.spam += values[i].spam;
returnValue.processed += values[i].processed;
returnValue.deffered += values[i].deffered;
}
return returnValue;
}
Just remember that the structure of emit has to match the structure of your final values.