previous quarters in javascript - javascript

Forgive me I tried several searches here and other places in general but cant seem to fix issue I am having at the moment. Can someone please help me figure out?
I am trying to find quarter strings from inputdate in JavaScript. For "01/31/2009" it should give Q1,2013 Q4,2012 etc based on offset given as input parameter. when offset is 0 then current quarter, 1 then previous, 2 then previous 2 quarter etc...
my current code: jsfiddle
function getQuarterStrings(id) {
var d = new Date();
var d = new Date("01/31/2009");
var str;
switch (id) {
...
}
Remaining code is in jsfiddle. As you can see, it fails on second last condition even though everything seems ok. Please help me figure out my mistake. Thank you!

Some of your comparisons are off, and Date tries to compensate for months that don't have as many days when you setMonth. This code should work:
function getQuarterStrings(id) {
var d = new Date("03/31/2009");
d.setDate(1);
d.setMonth(d.getMonth() - id * 3);
var month = d.getMonth() + 1;
var year = d.getFullYear();
var quarter = Math.ceil(month / 3);
return ("Q" + quarter + ", " + year);
}

This works, and is a lot more concise. It also allows you to use any offset instead of a limited set of values:
function getQuarterStrings(date, id) {
// quarter is 0-based here
var quarter = Math.floor(date.getMonth() / 3),
year = date.getFullYear();
quarter -= id;
if(quarter < 0) {
var yearsChanged = Math.ceil(-quarter / 4);
year -= yearsChanged;
// Shift quarter back to a nonnegative number
quarter += 4 * yearsChanged;
}
return "Q" + (quarter + 1) + ", " + year;
}
http://jsfiddle.net/dPmf2/6/

You can also get rid of the switch statement by doing this:
function getQuarterStrings(id) {
var d = new Date();
var d = new Date("01/31/2009");
var str;
if (id !== 0){
d.setMonth(d.getMonth() - 3*id);
}
str = getQuarter(d);
return str;
}

Related

Reducing dates not working in javascript

Trying to work out how I can get 10 days preceding current date in a select box, populated using ng-option. This is the code for reducing dates
var n = 1;
var d = new Date();
var dateList = [];
while (n < 10) {
d.setDate(d.getDate() - n);
dateList.push(d);
n++;
}
console.log(dateList);
I have swapped n for 1 or any number, but for some reason, I only get the same date gets repeated 10 times.
Many thanks in advance
Because you push the same date nine times and mutate that in the loop. You want to get 9 different date objects, which you can easily clone as:
dateList.push(new Date(d));
dayinms = 86400000
da = [];
for (i=1;i<=10;i++) {
d= new Date()
d.setTime(d.getTime() - (dayinms * i))
ds = d.getDate() + '/' + d.getMonth() + '/' + d.getFullYear()
da[i-1]=ds
}
console.log(da)

Javascript: Tabbed time period charts

I'm trying to produce a graph like the following:
From an array of events as follows:
var events = {
"0": {"guid": "78926349827546", "created": "2017-07-07 14:14:21" },
"1": {"guid": "78926349827546", "created": "2017-07-08 15:44:10" },
"2": {"guid": "20936752065745", "created": "2017-07-09 12:09:24" },
"3": {"guid": "20936752065745", "created": "2017-07-11 06:55:42" },
"4": {"guid": "20936752065745", "created": "2017-07-11 22:10:29" },
...
};
I'm currently using the Google Line Chart. Although I'm happy with the aesthetic, I still need to find a way to produce a tabbed display of several timescales, e.g. Today, Last 7 Days, Last Month and Total.
Programmatically, this is proving to be a sisyphean task, as I have to count occurrences across (in one instance) every hour in the last day, and then (in another instance) every day in the last week etc.
And there's a lot of date conversion, counting backwards from today and so on.
Is there a way of taking my array and producing a new array of human-readable dates relative from today, across several timescales?
This is really a duplicate of a couple of questions like Where can I find documentation on formatting a date in JavaScript?, How to add months to a date in JavaScript? and Add days to JavaScript Date. So there are plenty of existing examples to work from.
Also, Google Charts has its own date formatter.
Anyway, you might use a function that takes a start date, end date and increment and returns an array of timestamps in a particular format. Formatting the strings can use a second function or the Google Charts formatter.
A bare bones version is very little code, to add some logic for forward or backward series takes a few more lines.
// Return date string in YYYY-MM-DD HH:mm:ss format
function formatDate(date) {
function z(n){return (n<10? '0':'') + n}
return date.getFullYear() + '-' +
z(date.getMonth() + 1) + '-' +
z(date.getDate()) + ' ' +
z(date.getHours()) + ':' +
z(date.getMinutes()) + ':' +
z(date.getSeconds());
}
// Return date strings from start date to end date
// with increment inc in hours
function getDateSeries(start, end, inc) {
var d = new Date(+start);
inc = +inc;
var dates = [];
// Deal with backwards sequences
var reverse = false, t;
if (start > end) {
t = start;
start = end;
end = t;
reverse = true;
}
if (inc < 0) {
reverse = true;
inc *= -1;
}
while (start <= end) {
dates.push(formatDate(start));
start.setHours(start.getHours() + inc);
}
return reverse? dates.reverse() : dates;
}
// Hourly intervals over 2 days forwards
console.log(getDateSeries(new Date(2017,7,18), new Date(2017,7,19), 1));
// 6 hourly intervals over 10 days backwards
console.log(getDateSeries(new Date(2017,7,28), new Date(2017,7,18), -6));
// Hourly intervals from now going back 24 hours
var now = new Date();
var end = new Date(+now);
end.setDate(end.getDate() - 1);
console.log(getDateSeries(now, end, -1))
// Daily intervals from today going back 30 days
var now = new Date();
now.setHours(0,0,0,0);
var end = new Date(+now);
end.setDate(end.getDate() - 30);
console.log(getDateSeries(now, end, -24))
There are plenty of libraries around to help with formatting, incrementing and decrementing dates but if this is all you want to do, it doesn't take much to write.
This could be modified so the start is always "now" or "today" and use an interval in days rather than a start and end date with hours.
Where a library would come in handy is if you want say monthly intervals on the last day of the month or similar (since months aren't of equal length). So using moment.js you could do:
function getMonthlySequenceStart(months) {
var format = 'YYYY-MM-DD HH:mm:ss'
var now = moment().startOf('month');
var count = Math.abs(months);
var direction = months < 0? -1 : 1;
var result = [];
while (count--) {
result.push(now.format(format));
now.add(direction, 'months');
}
return result;
}
console.log(getMonthlySequenceStart(-12));
function getMonthlySequenceEnd(months) {
var format = 'YYYY-MM-DD HH:mm:ss'
var now = moment().endOf('month').startOf('day');
var count = Math.abs(months);
var direction = months < 0? -1 : 1;
var result = [];
while (count--) {
result.push(now.format(format));
now.add(direction, 'months');
now.endOf('month').startOf('day');
}
return result;
}
console.log(getMonthlySequenceEnd(-12));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
Not using a library isn't too hard either. The following sets the date to the first of the month as then it's easy to decrement by 1 month, then get the day before (the last day of the previous month) for the string:
// Sequence of end of months from current month
// back for num months
function getMonthlySequenceEnd(num) {
var now = new Date();
now.setHours(0,0,0,0);
var t, result = [];
// Set to first day of next month
now.setMonth(now.getMonth() + 1, 1)
while (num--) {
t = new Date(+now);
t.setDate(t.getDate() - 1);
result.push(formatDate(t));
now.setMonth(now.getMonth() - 1);
}
return result;
}
function formatDate(date) {
function z(n) {return (n < 10 ? '0' : '') + n}
return date.getFullYear() + '-' + z(date.getMonth() + 1) + '-' + z(date.getDate()) + ' ' +
z(date.getHours()) + ':' + z(date.getMinutes()) + ':' + z(date.getSeconds());
}
console.log(getMonthlySequenceEnd(24));
So I think you now have enough to do whatever is required.

How to make this function not return a negative date diffence?

The function is trying to fund the difference between to dates, but I am struggling to not return a negative number if the date is past a certain point. I have tried a few work around like using ABS but it can cause problems in future areas.
var DateCalc = {};
DateCalc.totalDaysLeft = 0;
DateCalc.calculate = function(dateToParse) {
DateCalc.init(dateToParse);
return DateCalc.stringify(DateCalc.years(), DateCalc.months(), DateCalc.days());
};
DateCalc.init = function(dateToParse) {
var date = DateCalc.parseDate(dateToParse);
var today = Date.now();
var oneDay = 24 * 60 * 60 * 1000;
DateCalc.totalDaysLeft = Math.floor((date - today) / oneDay);
};
DateCalc.parseDate = function(dateToParse) {
var dateVars = dateToParse.split(',').map(Number);
return new Date(dateVars[0], dateVars[1] - 1, dateVars[2]);
};
DateCalc.years = function() {
var years = Math.floor(DateCalc.totalDaysLeft / 365);
DateCalc.totalDaysLeft -= Math.floor(years * 365);
return years;
};
DateCalc.months = function() {
var months = Math.floor(DateCalc.totalDaysLeft / 30);
DateCalc.totalDaysLeft -= Math.floor(months * 30);
return months;
};
DateCalc.days = function() {
return Math.floor(DateCalc.totalDaysLeft / 24);
};
DateCalc.stringify = function(years, months, days) {
var dateString = "";
if (years !== 0)
dateString += years + " years, ";
if (months !== 0)
dateString += months + " months, ";
dateString += days + " day(s).";
return dateString;
};
//here is the .abs() code.
function age(year, month, day) {
var yearDifference = Math.abs(new Date().getFullYear() - year);
var monthDifference = Math.abs(new Date().getMonth() - month + 1);
var dayDifference = Math.abs(new Date().getDate() - day);
var differences = {
year: yearDifference,
month: monthDifference,
day: dayDifference
};
var final = [];
for (var time in differences) {
if (differences[time] > 0) {
var addString = differences[time] + " " + time;
if (differences[time] > 1) {
addString += "s"
}
final.push(addString);
}
}
return final.join(" ");
};
console.log(age(2017, 11, 17));
console.log(age(2016, 1, 2));
//if you tried to look up how far away next January is while you're in December, it will tell you it is 1 year 11 months from now instead of 1 month. This is because it adds the 11 months instead of subtracting it.I am trying to find a solution, as this function is more conscise but the other is more versatile. The function above, I replaced .floor() with rounds the value down with .abs() hoping it would just use the absolute value of the given operation, however, this was not the case.
The problem is that you are using the .abs() function in an inappropriate way. Most mathematical functions do no obey the distributive rule, and the .abs() function belongs to these. For an easier understanding, let us forget your current problem for a moment and let us examine a simple, reduced example:
Let's say you want to know the absolute value of -10. Obviously, the correct result is +10.
On the other hand, -10 could be written as (-20 + 10). But nevertheless, you can not compute abs(-10) using that knowledge:
abs(-20 + 10) = 10, but
abs(-20) + abs(+10) = 30
Applying that knowledge to your problem, we see that abs(Y years + M months + D days) is generally NOT equal to (abs(Y years) + abs(M months) + abs(D days)).
Regarding this problem, there is the additional oddity that each of the terms of the result has another unit, and that the terms depend on each other (e.g. there can be no term like "13 months", because that would be "1 year plus 1 month"), but I won't go into further detail here.
There is a simple solution:
1) Determine the desired resolution of your result (i.e. should your result be accurate to seconds, attoseconds, days or something else).
2) Convert the two dates into the unit determined in step 1), using a randomly chosen, yet fixed point in time as the common starting point.
3) Now you can subtract the two (converted) dates and use the .abs() function without problems.
4) Convert the result back into human readable form.
How do you do that in practice? Well, steps 1), 3) and 4) are easy, but what about step 2)?
Nearly every OS I know (and thus, nearly every programming language) does the conversion needed in step 2) for you. More often than not, the fixed point in time is 1970-01-01 00:00:00, and the OS / programming language provides routines to convert any date / time to the number of seconds (or some other unit) which have elapsed since this fixed point.
For example, in JavaScript, the myDate.getTime() function returns the number of milliseconds which have passed since 1970-01-01 up to myDate.
So convert both dates to "milliseconds since 1970-01-01" and subtract them. Use the .abs() function on the result. Then you have the desired time span as a value of positive milliseconds. Convert that back to human readable form, i.e. years, months and days (which is no problem, is it?)
A second simple solution (just for avoiding negative results):
I hope that you agree with me that comparing two dates is much easier than computing the difference between them (first compare the year; if the years differ, you have undoubtedly found the "greater" date; if the years are equal, do the same with the months, and so on). Then exchange the two dates if necessary. That way, you always can make sure that you subtract the "smaller" date from the "greater" date and that the result always will be positive.
But please note that even when doing so there will still be negative results in parts of the calculation when actually subtracting the dates, so you would have exactly the same problems when using the .abs() function.
A more complicated solution:
You could do the subtraction yourself as well, but then the .abs() function won't help you much. One of the algorithms I can think of could work like a subtraction which is done by hand (I mean the subtraction of normal numbers you have learned in school):
Begin with the least significant unit (for example the days). Subtract the days; if the result is negative, then add 28, 29, 30 or 31 (depending on the month) and make a carry to the months, otherwise keep the result; then do the same thing with the months, and so on. But as I already wrote in my comment, there are many pitfalls when doing so (leap years, months have different numbers of days, and so on), and the .abs() function will not help you here.
Conclusion:
Personally, I would prefer the first (simple) solution I have given. It is easy, understandable and future-proof.
//initial variables
var today = new Date();
var day = today.getDate();
var month = today.getMonth() + 1;
var year = today.getFullYear();
var otherDate = new Date();
var day2 = 0;
var month2 = 0;
var year2 = 0;
if (day < 10) {
day = '0' + day;
}
if (month < 10) {
month = '0' + month;
}
function age(day2, month2, year2) {
dayConv = day2;
monthConv = month2;
yearConv = year2;
newDate = day - dayConv;
newMonth = month - monthConv;
newYear = year - yearConv;
}
function mathDate() {
if (newYear >= 1) {
if (newMonth >= 1) {
if (newDate >= 1) {
console.log(newYear + " years and " + newMonth + " months and " + newDate + " days.");
return newYear + " years and " + newMonth + " months and " + newDate + " days.";
} else if (newDate <= 0) {
console.log(newYear + " years and " + newMonth + " months.");
return newYear + " years and " + newMonth + " months.";
}
} else if (newMonth <= 0) {
console.log(newYear + " years and " + newDate + " days.");
return newYear + " years and " + newDate + " days.";
}
} else if (newYear <= 1) {
if (newMonth >= 1) {
console.log(newMonth + " months and " + newDate + " days.");
return newMonth + " months and " + newDate + " days.";
} else if (newDate <= 0) {
console.log(newMonth + " months.");
return newMonth + " months.";
} else if (newMonth <= 0) {
console.log(newDate + " days.");
return newDate + " days.";
}
}
}
age(13, 4, 2016);
mathDate();
Here is the answer I was able to create.

how to compare a user entered date to the current date and change a fields background color?

I am new to javascript and am working on a fallible PDF form and trying to set it to do multiple things. The first is I need to compare a user entered date to the current date to see if it is withing 5 years to the day. The second thing I need it to do is to change a fields background color if that date is at the 5 year time or outside of that range. This is the code I have been trying but it hasn't worked so far. There are 37 fields that need to be checked by this.
for(i=1;i<38;i++){
var Y = d.getFullYear();
var d = new Date();
var M = d.getMonth();
var d = new Date();
var D = d.getDay(); //n =2
var strDate = this.getField("Text"+[i]).value;
var arrDate = strDate.split('/');
var month = arrDate[0];
var day = arrDate[1];
var year = arrDate[2];
if(year+5>=Y){
if(M<=month){
if(D<=day){
this.getField("Text[i]").fillColor=color.red;
}}}}
I have updated this, it working now, can you try this now ?
for(i=1;i<38;i++)
{
var todayDate = new Date();
var strDate = "12/25/2009";
var arrDate = strDate.split('/');
var month = arrDate[0];
var day = arrDate[1];
var year = parseInt(arrDate[2]) + 5;
var userEnteredDate = new Date(year, month, day);
if(userEnteredDate <= todayDate)
{
//Color change code here...
}
}
The simplest approach so far as I know, is to instantiate a Date that is five years ago based on current time:
var t = new Date()
t.setFullYear(t.getFullYear() - 5) // t is five years ago
Then you just need to substract the user input date with this one, and see if the result is positive or negative:
var ut = new Date("......") // the Date instance from user input
if(ut - t >= 0) {
// within 5 years
} else {
// more than 5 years ago
}
The reason you can do so, is because when you substract two Date instances one another, they will be internally converted to timestamps. The less a timestamp is, the earlier the time is. So the result of substraction (a number) represents the time in between, in milliseconds.
If you don't care how long in between, you could just compare them:
var ut = new Date("......") // the Date instance from user input
if(ut >= t) {
// within 5 years
} else {
// more than 5 years ago
}
Try this
var d = new Date(),
Y = d.getFullYear(),
M = d.getMonth() + 1, // since this returns 0 - 11
D = d.getDay() + 1, // since this returns 0 - 30
strDate,
arrDate,
month,
day,
year;
for(var i = 1; i < 38; i++) {
strDate = this.getField("Text" + i).value;
arrDate = strDate.split('/');
month = parseInt(arrDate[0], 10);
day = parseInt(arrDate[1], 10);
year = parseInt(arrDate[2], 10);
if (((Y + 5) * 12 + M < year * 12 + month) || ((Y + 5) * 12 + M === year * 12 + month && D < day)) {
this.getField("Text" + i).fillColor = color.red;
}
}

Customize javascript Date

I have a simple code that echos the current Hour+Minute+Date as one number sequence.
I need to add 1 to all the numbers outputted, individually.
Example: If the current time and date is: 22321512 then i need jQuery to output: 33432623.
My knowledge in jQuery is pretty slim, How can this be achieved?
HTML:
<span id="date"></span>
Code:
var now = dateFormat(new Date(), "HHMMddmm");
$('#date').append(now);
You need to do the following roughly:
var currentDate = new Date();
var myDate = new Date(currentDate.getYear() + 1, currentDate.getMonth() + 1, currentDate.getDay() + 1);
alert(myDate.getTime());
Should solve your problem.
If you want to merely increment each unit by 1 and let the JavaScript engine advance the date and time on overflow, then Captain John's answer will work perfectly.
This means that, for example, if this routine were to be run at 11:59 PM on December 31, your output would be 00000100.
If you want each unit to be incremented by 1 without the date being advanced, you will have to stop relying on Steven Levithan's [excellent] dateFormat library and do it yourself:
var now = new Date(),
hours = now.getHours() + 1, // add 1 hour
minutes = now.getMinutes() + 1, // add 1 minute
date = now.getDate() + 1, // add 1 day
month = now.getMonth() + 1, // add 1 month
padLeft = function (val) { // make a formatter
while (val.length < 2) {
val = '0' + val; // string is less than 2 characters, pad left side with '0'
}
return val; // return formatted string
},
formatted = padLeft(hours) + padLeft(minutes) + padLeft(date) + padLeft(month);
$('#date').append(formatted);
Getting number length as string you can easily sum 1 to each number.
The result is given as timestamp
To get Date object, use new Date(result);
var now = new Date().getTime(); // 22321512 on your example
// Answer
var result = 0;
var str = now.toString();
for(var i = 0; i < str.length; i++) {
result += Math.pow(10, i);
}
result += now; // Ex.: 22321512 + 11111111

Categories

Resources