im looking for mathematical formulas to add and subtract months to/from a date. i only need to know the year and month, therefor days can be ignored.
this is the adding months pseudo code i came up with:
OldYear = 2012 // current year
OldMonth = 3 // current month
AddMonths = 0 // the months to be added
FooBar = OldMonth + AddMonths
NewYear = OldYear + FooBar / 12
NewMonth = FooBar % 12
IF NewMonth = 0
NewYear = NewYear - 1
NewMonth = 12
END IF
// set AddMonths to 0 and the result will be 2012.03
// set AddMonths to 6 and the result will be 2012.09
// set AddMonths to 9 and the result will be 2012.12
// set AddMonths to 11 and the result will be 2013.02
// set AddMonths to 23 and the result will be 2014.02
// set AddMonths to 38 and the result will be 2015.05
and it works really great, but is there an even better way? i dont really like the need for the IF NewMonth = 0 readjustments.
but my actual problem is, that i couldnt come up with a counterpart formula to substract months. i tried various things, but everything failed and its driving me insane. so any help would be much appreciated!
It is a combination of my comment in #Matt's answer, and answer of #Matt
The formula can be greatly reduced if you adopt a 0-based month scheme.
pseudocode:
year = 2012; // year 2012
month = 6; // July (NOT June)
monthToAdd = -20; // +ve/-ve means add/subtract
resultYear = (year * 12 + month + monthToAdd) /12;
resultMonth = (year * 12 + month + monthToAdd) mod 12;
// resultYear == 2010
// resultMonth == 10 , which means November
Edit: The original answer above assumed a zero-based month scheme, which seem being overlooked by some people. To avoid confusion, we can of course use more intuitive 1-based month scheme, and do the 0-base conversion during calculation (though it make the calculation slightly messier):
year = 2012; // year 2012
month = 7; // July
monthToAdd = -20; // +ve/-ve means add/subtract
resultYear = (year * 12 + (month - 1) + monthToAdd) /12;
resultMonth = ((year * 12 + (month - 1) + monthToAdd) mod 12) + 1
// resultYear == 2010
// resultMonth == 11 , which means November
One possible solution would be to multiply OldYear by 12 (thus converting it to months), adding or subtracting AddMonths or SubMonths, respectively, and then converting back to NewYear and NewMonth by using integer and modular division (depending on your programming language, you may be able to simplify this).
Full credit to Adrian Shum for building the main logic but I think there is a edge case which the code is not 100% accurate for cases where we go back the same number of months as the month we are in. For example, if we are in March and we go back 3 months we should end up at Dec (Feb, Jan and Dec) .
here is the modified version:
year = 2020;
month = 4;
monthToAdd = -1;
resultYear = (year * 12 + month + monthToAdd) /12;
resultMonth = (year * 12 + month + monthToAdd) % 12;
if month+monthToAdd == 0:
resultMonth=12
elif (abs(monthToAdd)%month)==0:
resultMonth=month
print(resultMonth)
print(resultYear)
Related
Given the start day (Wednesday = 4), and the number of days in a month (31), what is an elegant way to find the number of week rows a calendar of the month would require?
For the current month (startDay = 4, daysInMonth = 31), it would be 5. But if daysInMonth = 33, it would be 6 rows.
This doesn't quite work:
int numRows = (startDay+daysInMonth)/daysInWeek;
if ((startDay+daysInMonth) % daysInWeek != 0) {
numRows++;
}
Just change to
int numRows = (startDay + daysInMonth - 1) / daysInWeek;
if ((startDay+daysInMonth - 1) % daysInWeek != 0) {
numRows++;
}
and you should get the correct result.
EDIT: just to slightly expand on it : you have the right idea, you just forgot to account for the fact that the offset for day 1 is 0, not 1.
Actually, I think your original algorithm is correct, just need to subtract 1 when doing modulo daysInWeek.
daysInWeek = 7
startDay = 3 # Zero based day of week array, 3 = Wednesday
daysInMonth = 31
numRows = (startDay+daysInMonth)/daysInWeek
if ((startDay+daysInMonth - 1) % daysInWeek != 0)
numRows += 1
end
print numRows
It shows 6 correctly. (BTW, why do you need a month with 33 days?) It should be 6 rows for a 33 day month (if there was such a thing).
int temp = daysInMonth;
temp = temp - (7 - startDay);
int result = ceiling(temp / 7) + 1;
Here is a generic way to do it in C#, which works by counting the Saturdays in a month and then adding one if there's any left over days. Since it literally reads a calendar like a human would, there's no strange calendar arithmetic needed. It's all offloaded to the C# DateTime code, we just piggyback off that.
I chose Saturday because most calendars go Sunday (far left) to Saturday (far right). You can just choose a different day if you wish to denote the end of a week.
public static int RowsForMonth(int year, int month)
{
int days = DateTime.DaysInMonth(year, month);
int rows = 0;
int i = 0;
while(i < days)
{
i++;
DateTime date = new DateTime(year, month, i);
if (date.DayOfWeek == DayOfWeek.Saturday || i == days)
rows++;
}
return rows;
}
Jan 2022 -> 6
Feb 2022 -> 5
Mar 2022 -> 5
I have 2 radMonthYearPicker(1 is for start Date another 1 is for end Date)
I want to calculate the month different between this 2 date.
for my start Date, I set my month as dec and year 2012.
for my end Date, I set my month as dec and year 2013
Base on this 2 RadMonthYearPicker, the month apart should be 12 month
The only code I can find out is RadMonthYearPicker.selectedDate
P.S. I was not allow to upload image file due to lack of repulation point
int monthsApart = 12 * (startDate.Year - endDate.Year) +
startDate.Month - endDate.Month;
int result = Math.Abs(monthsApart);
I want to get the Sunday & Saturday of the week from which a date is provided.
I have access to the following functions only:
getDate() returns a number from 0-6 (0 being sunday)
getDay() returns a number from 1-31
getMonth() returns a number from 0-11
getFullYear() returns the current year
I am doing this on titanium.
Per your description above, I came up with:
var sat = new Date(input.getFullYear(), input.getMonth(), 6 - input.getDate() + getDay());
var sun = new Date(input.getFullYear(), input.getMonth(), getDay() + (input.getDate() - 6));
If I follow the MDN doc, I come up with (works in Ti too):
var sat = new Date(input.getFullYear(), input.getMonth(), 6 - input.getDay() + input.getDate());
var sun = new Date(input.getFullYear(), input.getMonth(), input.getDate() + (input.getDay() - 6));
Where input is a javascript Date object.
The date object will take care or changing the month and/or year if necessary.
Hope this helps.
How do I get the date of this current week's Monday. Where Monday is the first day of the week. So if I was to look up this weeks it would return the date 1/16/2012
I am using VBScript and ASP
Many thanks in advance..
Paul
Effectively, the Weekday function returns Sunday=1, Monday=2, etc. To get the Monday of the same week, you want to subtract:
Sunday (1): 6 days
Monday (2): 0 days
Tuesday(3): 1 day
...
Saturday(7): 5 days.
Or
Days to subtract = (Weekday - 2 + 7) Mod 7
So if d is a date, the Monday of the same week can be written as:
mondayofsameweek = DateAdd("d", -((Weekday(d) + 7 - 2) Mod 7), d)
VBScript has a function called WeekDay, it return 1 - 7, not sure whether 1 is Monday though, usually you can twiddle with that.
Either way get the weekday Thursday = 4? , so then you just need to take three days off your date with thae DateAdd function
In VBScript WeekDay returns the day of the week, starting with Sunday=1 (VBScript can be quirky like that). So just subtract two (Monday=2) from that value and call DateAdd.
monday = DateAdd("d",(WeekDay(Date())-2),Date())
I know the topic is a bit old, but I figured I'd share my working solution that I think is a bit more concise.
Where dDate is your current date:
dDate = DateAdd("d", -(WeekDay(dDate, vbMonday) - 1), dDate)
The second parameters of WeekDay is the day you want the week to 'start'. For me, in the US, WeekDay corresponds the default second parameter to vbSunday. Specifying vbMonday, we just get the difference (base 1) between our current weekday and Monday.
Subtract 1 and add the inverse to your current date should obtain your result.
Example:
WeekDay(2018-03-20, vbMonday) = -((2) - 1) = DateAdd("d", -1, 2018-03-20)
I want to calculate the total no of weeks in current month. Starting from Sunday or Monday.
Is it possible to do in Qt
I would say this problem is not specific to Qt, but Qt can help you with the QDate class.
With this class you can get the current month :
QDate CurrentDate = QDate::currentDate();
The number of days of a given month :
CurrentDate.daysInMonth();
For the number of week calculation, it depends if you only want the number of full weeks in a month, or the number of weeks, taking partial weeks into account.
For the latter, here is how I would do it (considering the week starts on monday) :
const DAYS_IN_WEEK = 7;
QDate CurrentDate = QDate::currentDate();
int DaysInMonth = CurrentDate.daysInMonth();
QDate FirstDayOfMonth = CurrentDate;
FirstDayOfMonth.setDate(CurrentDate.year(), CurrentDate.month(), 1);
int WeekCount = DaysInMonth / DAYS_IN_WEEK;
int DaysLeft = DaysInMonth % DAYS_IN_WEEK;
if (DaysLeft > 0) {
WeekCount++;
// Check if the remaining days are split on two weeks
if (FirstDayOfMonth.dayOfWeek() + DaysLeft - 1 > DAYS_IN_WEEK)
WeekCount++;
}
This code has not been fully tested and is not garanteed to work !
floor(Number of Days / 7)
QDate::weekNumber can give you the number of the week in the year.
Here is an example of how to use it to obtain the number of weeks in a month, including those shorter than seven days:
QDate dateCurrent = QDate::currentDate();
int year = dateCurrent.year(), month = dateCurrent.month(),
daysInMonth = dateCurrent.daysInMonth(), weeksInMonth;
weeksInMonth = QDate(year, month, daysInMonth).weekNumber()
- QDate(year, month, 1).weekNumber() + 1;
Some months have 4 weeks and others have 5. Qt states that:
In accordance with ISO 8601, weeks start on Monday and the first Thursday of a year is always in week 1 of that year. Most years have 52 weeks, but some have 53.
For that matter my first Thursday in a month is the starting point when counting the number of weeks in a month. The function below works for me:
int myClass::weeksInMonth(QDate cdate)
{
QDate sDte = QDate(cdate.year(),cdate.month(),1);
QDate eDte = QDate(cdate.year(),cdate.month(),cdate.daysInMonth());
int wks = 0;
for(QDate stD = sDte; stD <= eDte; stD = stD.addDays(1)){
if(stD.dayOfWeek() == Qt::Thursday)++wks;
}
return wks;
}
Here's a function that wraps the top answer for PyQt5. However the ISO 8601 definition for week 01 is the week with the first Thursday of the Gregorian year; this solution will give a negative number of weeks on dec and jan on certain years..
def weeksInMonth(date: QDate):
year = date.year(), month = date.month()
daysInMonth = date.daysInMonth()
return QDate(year, month, daysInMonth).weekNumber()[0] - QDate(year, month, 1).weekNumber()[0] + 1