如何计算在两个日期之间经过的 "quarters" 的数量,其中季度不仅仅是一年中的一个季度,而是特定日期?
How can I calculate the number of "quarters" that have passed between 2 dates, where quarters are not simply a quarter of a year, but specific dates?
我正在尝试使用 Javascript 制作一个 "Rent Arrears Calculator",我想要的功能之一是可以选择计算每周、每月或每季度的租金。
如果按季交房租,过了某一天,迟交的季度数就会增加。这些季度日是每年的 25/03、24/06、29/09/ 和 25/12。
当输入日期的月份大于季度日期的月份,但其日期小于季度日期时,我的代码目前 returns 值不正确。
即对于 2014 年 6 月 24 日的 "First missed payment date" 和 2015 年 4 月 22 日的日期,这应该是 return 4,而不是 returns 1。它应该是 return 4 因为这次已经过了 4 个季度日期(24/06/2014、29/09/2014、25/12/2014 和 25/03/2015)。
这是我的代码:
function getNumberPeriods() {
var years = (getNumberYears());
var days = (getNumberDays());
if ((getPeriodLength()) == "Weekly") {
return ((days - (days % 7)) / 7);
} else if ((getPeriodLength()) == "Monthly") {
var months = ((((options.untilDate).getMonth()) + 1) - (((options.dueDate).getMonth()) + 1) + (12 * years));
if (((options.untilDate).getDate()) < ((options.dueDate).getDate())) {
months--;
}
return (months + 1);
} else if ((getPeriodLength()) == "Quarterly") {
if ((options.dueDate).getMonth() == 2) {
if (((options.untilDate).getMonth() <= 5) && ((options.untilDate).getDate() < 24)) {
return (1+(years * 4));
}
else if (((options.untilDate).getMonth() <= 5) && ((options.untilDate).getDate() >= 24)) {
return (2+(years * 4));
}
else if (((options.untilDate).getMonth() <= 8) && ((options.untilDate).getDate() < 29)) {
return (2 + (years * 4));
}
else if (((options.untilDate).getMonth() <= 8) && ((options.untilDate).getDate() >= 29)) {
return (3 + (years * 4));
}
else if (((options.untilDate).getMonth() <= 11) && ((options.untilDate).getDate() < 25)) {
return (3 + (years * 4));
}
else if (((options.untilDate).getMonth() <= 11) && ((options.untilDate).getDate() >= 25)) {
return ((years * 4)+4);
}
else return (years * 4);
}
else if ((options.dueDate).getMonth() == 5) {
if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() < 25) {
return (3 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() >= 25) {
return (4+(years * 4));
}
else if ((options.untilDate).getMonth() <= 8 && (options.untilDate).getDate() < 29) {
return ((years * 4)+1);
}
else if ((options.untilDate).getMonth() <= 8 && (options.untilDate).getDate() >= 29) {
return ((years * 4)+2);
}
else if ((options.untilDate).getMonth() <= 11 && (options.untilDate).getDate() < 25) {
return (2 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 11 && (options.untilDate).getDate() >= 25) {
return (3 + (years * 4));
}
else return (years * 4);
}
else if ((options.dueDate).getMonth() == 8) {
if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() < 25) {
return (2 + (years * 4));
}
if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() >= 25) {
return (3 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 5 && (options.untilDate).getDate() < 24) {
return (3 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 5 && (options.untilDate).getDate() >= 24) {
return (4+(years * 4));
}
else if ((options.untilDate).getMonth() <= 11 && (options.untilDate).getDate() < 25) {
return ((years * 4)+1);
}
else if ((options.untilDate).getMonth() <= 11 && (options.untilDate).getDate() >= 25) {
return ((years * 4)+2);
}
else return (years * 4);
}
else if ((options.dueDate).getMonth() == 11) {
if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() < 25) {
return ((years * 4)+1);
}
else if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() >= 25) {
return ((years * 4)+2);
}
else if ((options.untilDate).getMonth() <= 5 && (options.untilDate).getDate() < 24) {
return (2 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 5 && (options.untilDate).getDate() >= 24) {
return (3 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 8 && (options.untilDate).getDate() < 29) {
return (3 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 8 && (options.untilDate).getDate() >= 29) {
return ((years * 4)+4);
}
else return (years * 4);
}
else alert("not werkin");
}
}
function getNumberDays() {
return ((((options.untilDate)) - ((options.dueDate))) / (1000 * 60 * 60 * 24));
}
function getNumberYears() {
var dueMonth = (options.dueDate).getMonth();
var dueDay = (options.dueDate).getDate();
var dueYear = (options.dueDate).getFullYear();
var untilYear = (options.untilDate).getFullYear();
var untilMonth = (options.untilDate).getMonth();
var untilDay = (options.untilDate).getDate();
var diffyears = untilYear - dueYear;
if (untilMonth < dueMonth - 1){
diffyears--;
}
if (dueMonth - 1 == untilMonth && untilDay < dueDay){
diffyears--;
}
return diffyears;
而 this 是我的 JS fiddle 的 link(我知道 fiddle 的其他部分无法正常工作,但我还没有还没到那些)。
任何帮助将不胜感激!
泽赫拉
以下代码将经过的季度计入 passed
var quarters = [{'month':3, 'day':25}, {'month':6, 'day':24},
{'month':9, 'day':29}, {'month':12, 'day':25}];
var year = options.dueDate.getFullYear();
var passed = 0; // this is the number of passed quarters
var quarterIndex = 0;
do {
// month is 0 based
var reference = new Date(
year,
quarters[quarterIndex].month - 1,
quarters[quarterIndex].day);
if( (reference >= options.dueDate) && (reference <= options.untilDate) ) {
passed ++;
}
quarterIndex++;
if(4 == quarterIndex) {
quarterIndex = 0;
year++;
}
} while(reference < options.untilDate);
在您的代码中,您试图掩盖所有可能存在的情况。对于这个问题(以及大多数其他有大量案例的问题),这不是一个很好的方法。相反,尝试以不同的方式思考:您可以遍历季度日期并查看它们是否在 dueDate
和 untilDate
之间的时间段内。但是,您缺少日期的 year
部分来执行此操作。我建议在开始时使用 dueDate
的年份来构造 Date
对象,然后在每次迭代中增加年份,直到 year
变得大于 untilDate
的年份.
这是代码清单:
} else if ((getPeriodLength()) == "Quarterly") {
// We have an array of all the quarter dates
var quarterDates = [
{
'm': 3,
'd': 25
},
{
'm': 6,
'd': 24
},
{
'm': 9,
'd': 29
},
{
'm': 12,
'd': 25
}];
// The count of missed periods
var count = 0;
// Initial year value
var year = options.dueDate.getFullYear();
// Condition on when to stop
while (year <= options.untilDate.getFullYear()) {
for(var i in quarterDates) {
// Just a precaution, because foreach in js
// loops through all properties of the object
// and there might be functions and we want to
// skip them
if (typeof(quarterDates[i]) != 'function') {
// Construct a Date object
// Note: months in js have numbers from 0 to 11
var qDate = new Date(year, quarterDates[i].m - 1, quarterDates[i].d);
// If the date is in the given period
if (qDate >= options.dueDate && qDate <= options.untilDate) {
// Increase the counter
count++;
}
}
}
// Increase the value
year++;
}
return count;
}
我正在尝试使用 Javascript 制作一个 "Rent Arrears Calculator",我想要的功能之一是可以选择计算每周、每月或每季度的租金。
如果按季交房租,过了某一天,迟交的季度数就会增加。这些季度日是每年的 25/03、24/06、29/09/ 和 25/12。
当输入日期的月份大于季度日期的月份,但其日期小于季度日期时,我的代码目前 returns 值不正确。
即对于 2014 年 6 月 24 日的 "First missed payment date" 和 2015 年 4 月 22 日的日期,这应该是 return 4,而不是 returns 1。它应该是 return 4 因为这次已经过了 4 个季度日期(24/06/2014、29/09/2014、25/12/2014 和 25/03/2015)。
这是我的代码:
function getNumberPeriods() {
var years = (getNumberYears());
var days = (getNumberDays());
if ((getPeriodLength()) == "Weekly") {
return ((days - (days % 7)) / 7);
} else if ((getPeriodLength()) == "Monthly") {
var months = ((((options.untilDate).getMonth()) + 1) - (((options.dueDate).getMonth()) + 1) + (12 * years));
if (((options.untilDate).getDate()) < ((options.dueDate).getDate())) {
months--;
}
return (months + 1);
} else if ((getPeriodLength()) == "Quarterly") {
if ((options.dueDate).getMonth() == 2) {
if (((options.untilDate).getMonth() <= 5) && ((options.untilDate).getDate() < 24)) {
return (1+(years * 4));
}
else if (((options.untilDate).getMonth() <= 5) && ((options.untilDate).getDate() >= 24)) {
return (2+(years * 4));
}
else if (((options.untilDate).getMonth() <= 8) && ((options.untilDate).getDate() < 29)) {
return (2 + (years * 4));
}
else if (((options.untilDate).getMonth() <= 8) && ((options.untilDate).getDate() >= 29)) {
return (3 + (years * 4));
}
else if (((options.untilDate).getMonth() <= 11) && ((options.untilDate).getDate() < 25)) {
return (3 + (years * 4));
}
else if (((options.untilDate).getMonth() <= 11) && ((options.untilDate).getDate() >= 25)) {
return ((years * 4)+4);
}
else return (years * 4);
}
else if ((options.dueDate).getMonth() == 5) {
if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() < 25) {
return (3 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() >= 25) {
return (4+(years * 4));
}
else if ((options.untilDate).getMonth() <= 8 && (options.untilDate).getDate() < 29) {
return ((years * 4)+1);
}
else if ((options.untilDate).getMonth() <= 8 && (options.untilDate).getDate() >= 29) {
return ((years * 4)+2);
}
else if ((options.untilDate).getMonth() <= 11 && (options.untilDate).getDate() < 25) {
return (2 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 11 && (options.untilDate).getDate() >= 25) {
return (3 + (years * 4));
}
else return (years * 4);
}
else if ((options.dueDate).getMonth() == 8) {
if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() < 25) {
return (2 + (years * 4));
}
if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() >= 25) {
return (3 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 5 && (options.untilDate).getDate() < 24) {
return (3 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 5 && (options.untilDate).getDate() >= 24) {
return (4+(years * 4));
}
else if ((options.untilDate).getMonth() <= 11 && (options.untilDate).getDate() < 25) {
return ((years * 4)+1);
}
else if ((options.untilDate).getMonth() <= 11 && (options.untilDate).getDate() >= 25) {
return ((years * 4)+2);
}
else return (years * 4);
}
else if ((options.dueDate).getMonth() == 11) {
if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() < 25) {
return ((years * 4)+1);
}
else if ((options.untilDate).getMonth() <= 2 && (options.untilDate).getDate() >= 25) {
return ((years * 4)+2);
}
else if ((options.untilDate).getMonth() <= 5 && (options.untilDate).getDate() < 24) {
return (2 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 5 && (options.untilDate).getDate() >= 24) {
return (3 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 8 && (options.untilDate).getDate() < 29) {
return (3 + (years * 4));
}
else if ((options.untilDate).getMonth() <= 8 && (options.untilDate).getDate() >= 29) {
return ((years * 4)+4);
}
else return (years * 4);
}
else alert("not werkin");
}
}
function getNumberDays() {
return ((((options.untilDate)) - ((options.dueDate))) / (1000 * 60 * 60 * 24));
}
function getNumberYears() {
var dueMonth = (options.dueDate).getMonth();
var dueDay = (options.dueDate).getDate();
var dueYear = (options.dueDate).getFullYear();
var untilYear = (options.untilDate).getFullYear();
var untilMonth = (options.untilDate).getMonth();
var untilDay = (options.untilDate).getDate();
var diffyears = untilYear - dueYear;
if (untilMonth < dueMonth - 1){
diffyears--;
}
if (dueMonth - 1 == untilMonth && untilDay < dueDay){
diffyears--;
}
return diffyears;
而 this 是我的 JS fiddle 的 link(我知道 fiddle 的其他部分无法正常工作,但我还没有还没到那些)。
任何帮助将不胜感激!
泽赫拉
以下代码将经过的季度计入 passed
var quarters = [{'month':3, 'day':25}, {'month':6, 'day':24},
{'month':9, 'day':29}, {'month':12, 'day':25}];
var year = options.dueDate.getFullYear();
var passed = 0; // this is the number of passed quarters
var quarterIndex = 0;
do {
// month is 0 based
var reference = new Date(
year,
quarters[quarterIndex].month - 1,
quarters[quarterIndex].day);
if( (reference >= options.dueDate) && (reference <= options.untilDate) ) {
passed ++;
}
quarterIndex++;
if(4 == quarterIndex) {
quarterIndex = 0;
year++;
}
} while(reference < options.untilDate);
在您的代码中,您试图掩盖所有可能存在的情况。对于这个问题(以及大多数其他有大量案例的问题),这不是一个很好的方法。相反,尝试以不同的方式思考:您可以遍历季度日期并查看它们是否在 dueDate
和 untilDate
之间的时间段内。但是,您缺少日期的 year
部分来执行此操作。我建议在开始时使用 dueDate
的年份来构造 Date
对象,然后在每次迭代中增加年份,直到 year
变得大于 untilDate
的年份.
这是代码清单:
} else if ((getPeriodLength()) == "Quarterly") {
// We have an array of all the quarter dates
var quarterDates = [
{
'm': 3,
'd': 25
},
{
'm': 6,
'd': 24
},
{
'm': 9,
'd': 29
},
{
'm': 12,
'd': 25
}];
// The count of missed periods
var count = 0;
// Initial year value
var year = options.dueDate.getFullYear();
// Condition on when to stop
while (year <= options.untilDate.getFullYear()) {
for(var i in quarterDates) {
// Just a precaution, because foreach in js
// loops through all properties of the object
// and there might be functions and we want to
// skip them
if (typeof(quarterDates[i]) != 'function') {
// Construct a Date object
// Note: months in js have numbers from 0 to 11
var qDate = new Date(year, quarterDates[i].m - 1, quarterDates[i].d);
// If the date is in the given period
if (qDate >= options.dueDate && qDate <= options.untilDate) {
// Increase the counter
count++;
}
}
}
// Increase the value
year++;
}
return count;
}