Get the next highest date value after excluding values from an array - javascript

I have a myDate variable with the value 18-Nov-2013.Each day its value is being changed.Tommorow this myDate variable will have the value 19-Nov-2013.I have a list of values that i have mapped into a single array named exclude which contains some dates that are to be excluded ,now it has values ["20-Nov-2013",21-Nov-2013", "23-Nov-2010"] .How could i filter my value from the list of values from the exclude array.I need the next highest value from the array.So here i need the value 22-Nov-2013 after tommorrows date.Could someone help me with this.

var excluded = ["30-Nov-2013","01-Dec-2013","02-Dec-2013"];
var myDate = "29-Nov-2013";
var month = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var current = new Date(myDate);
while(true){
current = new Date((current.getDate()+1<10? "0"+(current.getDate()+1):(current.getDate()+1))+ "-" + month[current.getMonth()] + "-" + current.getFullYear());
var checkDate = (current.getDate()<10? "0"+(current.getDate()):(current.getDate()))+ "-" + month[current.getMonth()] + "-" + current.getFullYear();//this is necessary for when the +1 on day of month passes the month barrier
if(-1 == excluded.indexOf(checkDate))
break;
}
alert(checkDate);

I don't know if this is the best approach, or if is the best algorithm, but you may try this:
var myDate = ["17-Nov-2013", "18-Nov-2013"];
var excluded = ["20-Nov-2013", "21-Nov-2013", "23-Nov-2013"];
var months = {"Nov": 10}; // Add others months "Jan": 1, "Fev": 2 etc...
function findExcluded(date)
{
for (var i = 0; i < excluded.length; i++)
{
if (excluded[i] === date)
{
return true;
}
}
return false;
}
function nextDate()
{
var last = myDate[(myDate.length - 1)];
var s = last.split("-");
var d = new Date(s[2], months[s[1]], s[0]);
var next = new Date(d);
var chkDate = "";
do
{
next.setDate(next.getDate() + 1);
chkDate = next.getDate() + "-" + findMonth(next.getMonth()) + "-" + next.getFullYear();
} while(findExcluded(chkDate));
return chkDate;
}
function findMonth(m)
{
var i = 10; // When you fill all months on 'months' array, this variable should start at '0' in order to loop to works.
for (var month in months)
{
if (i == m)
{
return month;
}
i++;
}
}
var nd = nextDate();
alert(nd);
See it woring here.

No code ? Well here will be my method:
1.Get next date for mydate. Say that is var nextDate.
2.Check whether that date exist in the array.
3.If exists add one more day to nextDate. Again check in the array.
4.Do it until you get a date which is not present in your exclude array
For checking whether it exists in the array you can use arrValues.indexOf(nextDateInProperFormat) > -1

Related

Calculation with Array values not working in JS

in my current project I need a Pie Chart in which calculated values should be displayed.
I have now five values as array, which I need to add, so that I have the desired value.
But now I am a bit confused, because no matter if I convert the arrays to sting, or use them directly in the addition, they are always lined up and not added.
What am I missing here?
In a subtraction directly after the calculation works, but here I still have a date value (number of days in the month) in the calculation.
Why does this calculation work?
My Problem
For example I get here "02400" as result and not "6".
var training = training_intervall + training_longrun + training_speedwork + training_stabilisation + training_competition;
My JS function:
function userDiaryMonthTrainingStats(user_id) {
$.ajax({
url: "../diary/includes/training/diary-training-monthly-training-stats.php?user_id=" + user_id,
type: "GET",
success: function(monthly_training_stats) {
var training_intervall = [];
var training_longrun = [];
var training_speedwork = [];
var training_stabilisation = [];
var training_competition = [];
var training_injury = [];
for(var i in monthly_training_stats) {
training_intervall.push(monthly_training_stats[i].training_intervall),
training_longrun.push(monthly_training_stats[i].training_longrun),
training_speedwork.push(monthly_training_stats[i].training_speedwork),
training_stabilisation.push(monthly_training_stats[i].training_stabilisation),
training_competition.push(monthly_training_stats[i].training_competition),
training_injury.push(monthly_training_stats[i].training_injury)
}
var date = new Date();
var month = date.getMonth() + 1;
var year = date.getFullYear();
daysInMonth = new Date(year, month, 0).getDate();
training_intervall = training_intervall.toString();
training_longrun = training_longrun.toString();
training_speedwork = training_speedwork.toString();
training_stabilisation = training_stabilisation.toString();
training_competition = training_competition.toString();
var training = training_intervall + training_longrun + training_speedwork + training_stabilisation + training_competition;
var training_free = daysInMonth - training_intervall - training_longrun - training_speedwork - training_stabilisation - training_competition - training_injury;
var userMonthlyTrainingStatsData = {
datasets: [{
data: [training, training_injury, training_free],
backgroundColor: ['#36a2eb', '#e33b3b', '#4bc07d']
}],
labels: [
'Training',
'Injury',
'Free'
]
};
........
}
})
}
use parseInt() to change from a string to int then you can add the strings as they are now numbers
var training = parseInt(training_intervall) + parseInt(training_longrun) + parseInt(training_speedwork + parseInt(training_stabilisation) + parseInt(training_competition);
if you want the result back to a string simply put after this
training=""+training
Two problems in your code:
training_intervall and the other 4 variables you want to add are arrays, you should iterate them.
The values are strings, using + with strings results in a new concatenated string. To convert easily a string number to a number (example "1" to 1), you can:
const myString = "1"
const myNumber = myString * 1 // myNumber = 1

Google Script does not trigger as expected given row conditions

I have the 2 columns in my table schema:
Column D= Date, i.e. 20180611 [yyymmdd]
Column F= Continuous Value, i.e. 0.1, 0.6, -0.3 etc.
This is what I want to happen:
Check in column D for yesterday's date. Then, take in the corresponding row, and check if column F is greater than 0.5 (for yesterday's date). If TRUE, then send an email alert.
This is the script I have but it does not trigger for some reason. What is wrong with it?
function readCell() {
var sheet = SpreadsheetApp.getActive().getSheetByName('test');
var dates = sheet.getRange('D1:D').getValues();
var date = null;
var dateRow = 0;
var dateCount = dates.length;
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
var yesterdayString = yesterday.toDateString();
for (dateRow; dateRow < dateCount; ++dateCount) {
try {
date = dates[dateRow].toDateString();
if (date === yesterdayString) {
++dateRow;
// To account for zero-based array
break;
}
} catch (error) {
Logger.log(error);
}
}
var value = sheet.getRange('F' + dateRow).getValue();
if (value >= 0.5) {
var result = ('Alert found on: ' + date);
MailApp.sendEmail('blabla#gmail.com', 'Alert', result);
}
};
Here is the data
The problem could be due to the use of an open reference D2:D to get values and then use dates.length to set the number of iterations on the for loop because it could be a number too large.
One "quick and dirty" way that could solve the above issue is to replace
var dateCount = dates.length;
by
var dateCount = sheet.getDataRange().getValues().length;

extract and format value in JSON string

I just started working with JSON strings. i have an array of json strings that contains json strings like
{"ID":"3", "LinkFilename":"Test.txt", "Sender":"abc#hotmail.com", "Created":"2014-07-07T20:13:18.000Z"}
what i want to do is to take change the value of "Created" key (which is a date) and omit its time part so it must show only date part. i want to produce something like:
{"ID":"3", "LinkFilename":"Test.txt", "Sender":"abc#hotmail.com", "Created":"2014-07-07"}
The code to produce Json is as follows:
var ItemsEntries = [];
var listItemInfo = '';
var itemsCount = this.collListItem.get_count();
for (i = 0; i < itemsCount; i++) {
var item = this.collListItem.itemAt(i);
var ItemEntry = JSON.stringify(item.get_fieldValues());
ItemsEntries.push(ItemEntry);
listItemInfo += ItemsEntries[i].toString(); + '\n';
}
Please guide me through this.
If you have the Javascript object:
var item = {
"ID":"3",
"LinkFilename":"Test.txt",
"Sender":"abc#hotmail.com",
"Created":"2014-07-07T20:13:18.000Z"
}
and you want to change the Created field in the way you described, you can first create a new Date object out of the Created field value and just extracting the pieces you care about with the functions included in the Date API (http://www.w3schools.com/jsref/jsref_obj_date.asp).
This code should be able to change obj to the format you require:
var formatItem = function(item){
var date = new Date(item["Created"]);
var formattedDate = date.getFullYear()
+ '-'
+ date.getMonth() + 1 // zero-based index...
+ '-'
+ date.getDate();
item["Created"] = formattedDate;
};
One caveat is that the month won't be padded on the left by a 0 if it's a single digit, but that's easy enough to fix on a case-by-case basis.

Loop from startdate to enddate from inputs with javascript

I've got a startdate and enddate from inputs. And I need to put all the dates from the startdate until the enddate into the database. Therefore I need to make a loop like this:
FOR i = startdate; i <= enddate; i + 1 day
{
here i use the date
}
How do I make such a loop with dates from input boxes?
I get 'invalid date' if I try to do this:
var endDate = new Date($("#enddate").val());
And I can't use the endDate.getTime() like I need as you said in the answer, if I do it like this.
var endDate = $("#enddate").val());
var endDateTime = endDate.getTime();
So basically: How can I convert the input to a date? The input of enddate is like this: dd/mm/yyyy.
No it's not an SQL question, I need to do this is javascript because I need to check the dates first.
Thank you for helping me out ;)
Would a loop like this work?:
var current_date = new Date("01/13/2013");
var end_date = new Date("01/20/2013");
var end_date_time = end_date.getTime();
while (current_date.getTime() < end_date_time) {
console.log(current_date);
current_date.setDate(current_date.getDate()+1);
}
http://jsfiddle.net/Sn6Ws/
Depending on the format of your textboxes' values, you can set it up like this:
$(document).ready(function () {
$("#btn").on("click", function () {
dateLooper(function (cur, end) {
console.log("Current date: " + cur.toString() + ", End Date: " + end.toString());
});
});
});
function dateLooper(callback) {
var start_date_text = document.getElementById("start_date").value;
var end_date_text = document.getElementById("end_date").value;
var current_date = new Date(start_date_text);
var end_date = new Date(end_date_text);
var end_date_time = end_date.getTime();
while (current_date.getTime() < end_date_time) {
//console.log(current_date);
callback.call(this, current_date, end_date);
current_date.setDate(current_date.getDate()+1);
}
}
http://jsfiddle.net/Sn6Ws/1/
Per your comments that explain the date are in the format "dd/mm/yyyy", you could use something like this:
var start_date_text = document.getElementById("start_date").value;
var start_split = start_date_text.split("/");
if (start_split.length != 3) {
return false;
}
start_date_text = start_split[1] + "/" + start_split[0] + "/" + start_split[2];
var end_date_text = document.getElementById("end_date").value;
var end_split = end_date_text.split("/");
if (end_split.length != 3) {
return false;
}
end_date_text = end_split[1] + "/" + end_split[0] + "/" + end_split[2];
to get the dates in the right format before passing them to new Date. Here's an updated jsFiddle that demonstrates it:
http://jsfiddle.net/Sn6Ws/4/
Of course, be careful that if the dates don't come in with the specified format (in case users can type this in or something), the code will most likely throw an error. You can obviously put more checks in to make sure certain things set before proceeding with certain operations (like making sure each item is a number/integer, making sure the days are in the range 1 to 31, etc.). So for that reason, you may want to go the route of regular expressions. At least with regular expressions, you can specify a specific pattern and know whether it matches perfectly or not, and immediately get the values you need to build a date.
Using regular expressions, here's an example that isn't complete but should hopefully help:
function dateLooper(callback) {
var re = /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/;
var start_date_text = document.getElementById("start_date").value;
var start_match = re.exec(start_date_text);
if (start_match) {
var valid = true;
// Set `valid` variable based on the following
// Validate start_match[1] is valid day
// Validate start_match[2] is valid month
// Validate start_match[3] is valid year
if (valid) {
start_date_text = combineDate(start_match);
} else {
return false;
}
} else {
return false;
}
var end_date_text = document.getElementById("end_date").value;
var end_match = re.exec(end_date_text);
if (end_match) {
var valid = true;
// Set `valid` variable based on the following
// Validate end_match[1] is valid day
// Validate end_match[2] is valid month
// Validate end_match[3] is valid year
if (valid) {
end_date_text = combineDate(end_match);
} else {
return false;
}
} else {
return false;
}
var current_date = new Date(start_date_text);
var end_date = new Date(end_date_text);
var end_date_time = end_date.getTime();
var days_spent = 0;
while (current_date.getTime() < end_date_time) {
days_spent++;
callback.call(this, current_date, end_date, days_spent);
current_date.setDate(current_date.getDate()+1);
}
return days_spent;
}
function combineDate(re_match) {
return re_match[2] + "/" + re_match[1] + "/" + re_match[3];
}
http://jsfiddle.net/Sn6Ws/6/

datepicker with unavailable date from/until

I have an array of unavailable dates set at unavailableDates and weekends.
Array:
<script type="text/javascript">//<![CDATA[
var unavailableDates = [];
{foreach $fixed.rows as $row}
var row = {};
row['date_from'] = "{$row.fixed_date_from.value}";
row['date_until'] = "{$row.fixed_date_until.value}";
row['name'] = "{$row.fixed_name.value} ({$row.fixed_type.value})";
unavailableDates.push(row);
{/foreach}
//]]></script>
Q1) How can I add an extra check for the until date. I have got it working as shown below for the from date?
Q2) Can I improve the code to use in_array instead of loop through each of the dates for each calendar day?
var days = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
var unavailableDays = ["Saturday","Sunday"];
$("#.datePicker").datepicker($.extend(true, {}, $.initDatePickers.defaults, {
beforeShowDay: function(date) {
ymd = date.getFullYear() + "-" + ("0"+(date.getMonth()+1)).slice(-2) + "-" + ("0"+date.getDate()).slice(-2);
day = new Date(ymd).getDay();
result = null;
// Check if date in unavailable array or weekend
for(var i = 0; i < unavailableDates.length; i++){
if ((ymd == unavailableDates[i].date_from) && $.inArray(days[day], unavailableDays) < 0) {
return [false,"unavailable",unavailableDates[i].name];
}
}
if(result){
return result;
} else {
return [true, "available", ""];
}
}
}));
Use the befreShowDay option to parse your data array to determine if day is selectable or not
beforeShowDayType: Function( Date date )
A function takes a date as a parameter and must return an array with [0] equal to true/false indicating whether or not this date is selectable, 1 equal to a CSS class name or "" for the default presentation, and [2] an optional popup tooltip for this date. It is called for each day in the datepicker before it is displayed.

Categories

Resources