admin管理员组文章数量:1405298
I'm writing a function to calculate the time interval between an input date in years, months and days and the date now. I need to be able to take an input date from the past or the future, to account for leap years and to return it all in years, months (luckily I can use 30 days per months as an average) and days in a single object and to have it all work in one larger function that I can call on an input date. I've spent So much time on this, basically, I calculate the interval in days using UTC time, account for leap year and add days for each leap year that passed and then create a dictionary using my values but after so much work, I feel like I still have inaccuracies & that there could probably be a problem at the end when I'm converting the values & taking care of if months is > 12 by adding 1 to year count (I feel like if it was 24 months or higher that I'd run into problems). I've worked alot on this in the past 2 days & feel like I"ve cleared up Alot of my prior problems but it's still not pletely right I feel like & feel like there are some flaws in my calculations... Here's my code:
var timeInterval = function(inputYear, inputMonth, inputDay) {
var intervalInDays = function(inputYear, inputMonth, inputDay) {
var now = new Date();
var then = new Date(inputYear, (inputMonth - 1), inputDay);
var now_utc = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
var then_utc = new Date(then.getUTCFullYear(), then.getUTCMonth(), then.getUTCDate());
var intervalInMill = then_utc - now_utc;
var intervalInDays = (intervalInMill / (1000 * 60 * 60 * 24));
return Math.abs(Math.round(intervalInDays));
///return Math.round(intervalInMill / (1000 * 60 * 60 * 24));
};
var countLeapYears = function(inputYear, inputMonth, inputDay) {
var yearNow = new Date().getFullYear(),
yearThen = inputYear,
beginYear = 0,
endYear = 0,
leapYearCount = 0;
var isLeapYear = function(year) {
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
};
if (yearNow < inputYear) {
beginYear = yearNow;
endYear = inputYear;
} else if (yearNow > inputYear) {
beginYear = inputYear;
endYear = yearNow;
} else if (yearNow == inputYear) {
beginYear = inputYear;
endYear = inputYear;
}
for (i = beginYear; i <= endYear; i++) {
if (isLeapYear(i)) {
leapYearCount++;
}
}
return leapYearCount;
};
var totalDays = intervalInDays(inputYear, inputMonth, inputDay);
var leapYearCount = countLeapYears(inputYear, inputMonth, inputDay);
var years = Math.abs(Math.trunc(totalDays / 365));
var months = Math.abs(Math.trunc((totalDays - ((years * 365) - leapYearCount)) / 30));
if (months >= 12) {
years += 1;
months = months - 12;
}
var days = Math.abs(totalDays - (years * 365) - (months * 30) - leapYearCount);
///Math.abs((totalDays - ((years * 365) - leapYearCount)) % 30);
var intervalDict = {
"years": years,
"months": months,
"days": days,
};
return intervalDict;
};
console.log(timeInterval(2014, 11, 3));
console.log(timeInterval(2016, 2, 5));
console.log(timeInterval(2015, 2, 5));
console.log(timeInterval(2005, 2, 5));
console.log(timeInterval(1982, 3, 10));
I'm writing a function to calculate the time interval between an input date in years, months and days and the date now. I need to be able to take an input date from the past or the future, to account for leap years and to return it all in years, months (luckily I can use 30 days per months as an average) and days in a single object and to have it all work in one larger function that I can call on an input date. I've spent So much time on this, basically, I calculate the interval in days using UTC time, account for leap year and add days for each leap year that passed and then create a dictionary using my values but after so much work, I feel like I still have inaccuracies & that there could probably be a problem at the end when I'm converting the values & taking care of if months is > 12 by adding 1 to year count (I feel like if it was 24 months or higher that I'd run into problems). I've worked alot on this in the past 2 days & feel like I"ve cleared up Alot of my prior problems but it's still not pletely right I feel like & feel like there are some flaws in my calculations... Here's my code:
var timeInterval = function(inputYear, inputMonth, inputDay) {
var intervalInDays = function(inputYear, inputMonth, inputDay) {
var now = new Date();
var then = new Date(inputYear, (inputMonth - 1), inputDay);
var now_utc = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
var then_utc = new Date(then.getUTCFullYear(), then.getUTCMonth(), then.getUTCDate());
var intervalInMill = then_utc - now_utc;
var intervalInDays = (intervalInMill / (1000 * 60 * 60 * 24));
return Math.abs(Math.round(intervalInDays));
///return Math.round(intervalInMill / (1000 * 60 * 60 * 24));
};
var countLeapYears = function(inputYear, inputMonth, inputDay) {
var yearNow = new Date().getFullYear(),
yearThen = inputYear,
beginYear = 0,
endYear = 0,
leapYearCount = 0;
var isLeapYear = function(year) {
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
};
if (yearNow < inputYear) {
beginYear = yearNow;
endYear = inputYear;
} else if (yearNow > inputYear) {
beginYear = inputYear;
endYear = yearNow;
} else if (yearNow == inputYear) {
beginYear = inputYear;
endYear = inputYear;
}
for (i = beginYear; i <= endYear; i++) {
if (isLeapYear(i)) {
leapYearCount++;
}
}
return leapYearCount;
};
var totalDays = intervalInDays(inputYear, inputMonth, inputDay);
var leapYearCount = countLeapYears(inputYear, inputMonth, inputDay);
var years = Math.abs(Math.trunc(totalDays / 365));
var months = Math.abs(Math.trunc((totalDays - ((years * 365) - leapYearCount)) / 30));
if (months >= 12) {
years += 1;
months = months - 12;
}
var days = Math.abs(totalDays - (years * 365) - (months * 30) - leapYearCount);
///Math.abs((totalDays - ((years * 365) - leapYearCount)) % 30);
var intervalDict = {
"years": years,
"months": months,
"days": days,
};
return intervalDict;
};
console.log(timeInterval(2014, 11, 3));
console.log(timeInterval(2016, 2, 5));
console.log(timeInterval(2015, 2, 5));
console.log(timeInterval(2005, 2, 5));
console.log(timeInterval(1982, 3, 10));
Share
Improve this question
edited Feb 4, 2016 at 8:33
KindeR66
asked Feb 3, 2016 at 20:42
KindeR66KindeR66
372 gold badges4 silver badges10 bronze badges
7
- So you just want to get number of days between two dates? – Harry Bomrah Commented Feb 4, 2016 at 5:57
- sort of- I need to take an input date in years, months and days, calculate the amount of time between that date and today and return the time interval in days, months (if over 30 days- I can use an avg of 30 days/month) and years (if more than 12 months) and account for leap year too :-) @ Harry Bomrah – KindeR66 Commented Feb 4, 2016 at 7:03
- do you need the whole code? – Harry Bomrah Commented Feb 4, 2016 at 7:06
- I feel like there's something wrong w/the way I'm using that long chain of conditional statements at the very end to convert the days back into years, months and days- (at first I just subtracted the values w/o conditionals until I noticed I was about 2 days off so then I added a few conditions & then I was getting 12 months instead of 1 yr so I added them all & I started getting NaN's {sorry, I'm a programming student so super new to this :-) @Harry Bomrah - I just did an algebraic array analysis which I did w/o any trouble but I've had such a hard time w/datetime}... Thank U! – KindeR66 Commented Feb 4, 2016 at 7:23
- Yeah date and time can be annoying.. I ll see what i can do.. I ll post an answer when i get time today. cheers :) – Harry Bomrah Commented Feb 4, 2016 at 7:27
3 Answers
Reset to default 2Short answer: instead of reinventing the wheel you could just use moment.js and your script would be over in one lines :
interval = moment().diff(moment([inputYear, inputMonth, inputDay]))
And then you could access the day / month / year through interval.days(), interval.months(), interval.years()
Long answer: you misunderstand the declaration of variable of javascript. If you declare a var inside a function or a loop, it will be available ONLY in this context. For example you define years
inside if (intervalInDays > 365)
so right after the closing }
your variable years is not available.
On the same register, you declare twice intervalInDays
, once in your general function and once inside the function named intervalInDays
. When you are using it to define the dict it will actually refer to the function, and not its result, probably not what you want.
In your second example you are trying to use a years
variable that does not exist so it obviously fail.
Conclusion: your variable MUST be declared at the highest level where they need to be available, otherwise you won't be able to access them.
Firstly, I think that you misunderstand your input dates:
timeInterval(2016, 2, 5) equals 2016, March, 5. If thats what you want nevermind but I think you mean 2016, February, 5 which would be timeInterval(2016, 1, 5).
function timeInterval(inputYear, inputMonth, inputDay) {
var now = new Date();
var then = new Date(inputYear, inputMonth, inputDay);
var dayCount = 0;
while (now.setHours(1, 3, 3, 7) > then.setHours(1, 3, 3, 7)) {
then.setDate(then.getDate() + 1);
dayCount++;
}
while (now.setHours(1, 3, 3, 7) < then.setHours(1, 3, 3, 7)) {
now.setDate(now.getDate() + 1);
dayCount++;
}
var years = Math.floor(dayCount/365);
dayCount = dayCount - years*365;
var months = Math.floor(dayCount/30);
dayCount = dayCount - months*30;
var days = dayCount;
return { years, months, days };
}
// this is today: 4th february 2016
console.log(timeInterval(2016, 1, 4));
console.log(timeInterval(2014, 11, 3));
console.log(timeInterval(2016, 2, 5));
console.log(timeInterval(2015, 2, 5));
console.log(timeInterval(2005, 2, 5));
console.log(timeInterval(1982, 3, 10));
output:
{ years: 0, months: 0, days: 0 }
{ years: 1, months: 2, days: 3 }
{ years: 0, months: 1, days: 0 }
{ years: 0, months: 11, days: 6 }
{ years: 10, months: 11, days: 8 }
{ years: 33, months: 10, days: 8 }
Still inaccurate but you stated you could use 30 days a month as an average. And after all its a homework so try to understand and improve the code.
Well this is not 100% accurate but very close
Date.prototype.diff = function(y,m,d){
var cleanDate = function(x){
x.setHours(0);
x.setMinutes(0);
x.setSeconds(0);
return x;
}
var dateToCompare = new Date(y,m,d),
date = cleanDate(this),
daysCount = [31,28,31,30,31,30,31,31,30,31,30,31],
d = (date > dateToCompare ? date : dateToCompare),
d1 = (date < dateToCompare ? date : dateToCompare),
days = 0,
months = 0,
years = 0;
var yearDiff = function(){
years = d.getFullYear() - (d1.getFullYear() + 1);
years = years < 0 ? 0 : years;
}
var monthDiff = function(){
months = d.getFullYear() == d1.getFullYear() ? (d.getMonth() - 1) - d1.getMonth() : d.getMonth() + (12 - (d1.getMonth() + 1));
if(months >= 12){
years = years + Math.floor(months / 12)
months = months % 12;
}
}
var getAdjustedDays = function(){
var adjustedDays = 0;
for(i = (d1.getMonth() + 1); i <= 12; i++){
if(daysCount[i] == 31){
adjustedDays++;
}
}
return adjustedDays;
}
var dayDiff = function(){
var month = d1.getMonth();
if(month == 1 && months == 0 && years == 0){
days = d.getDate() - d1.getDate();
}else if(month == 1){
days = (isLeapYear(d1.getFullYear()) ? 29 - d1.getDate() : 28 - d1.getDate()) + d.getDate() + (d1.getDate() == d.getDate() ? 1 : 2);
days = Math.ceil(days - (getAdjustedDays() / 2));
}else{
days = (daysCount[month] - d1.getDate()) + d.getDate() + (d1.getMonth() == d.getMonth() ? 2 : 1);
days = Math.ceil(days - (getAdjustedDays() / 2));
}
getAdjustedDays();
if(days >= 30){
months = months + Math.floor(days / 30); //averge are 30 days
days = days % 30;
}
}
var isLeapYear = function(year) {
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
yearDiff();
monthDiff();
dayDiff();
return {"years" : years, "months" : months, "days" : days};
}
console.log(new Date().diff(1987, 2, 4));
console.log(new Date().diff(2005, 8, 25));
console.log(new Date().diff(2018, 8, 25));
本文标签: functionDate interval calculation in JavaScriptStack Overflow
版权声明:本文标题:function - Date interval calculation in JavaScript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744291350a2599128.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论