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
Related
Hi I'm trying to work out how would you group items into the first and 2nd half of each month for a given year and month?
i.e.
Say for example I have to list the name of item on the 6th of every month and the 15th of every month.
say for example I have
Flight Name Flight Date
Flight 1 01/07/2012
Flight 2 12/07/2012
Flight 3 18/07/2012
Flight 4 28/07/2012
how would i split it up so I'd like to group flights by fortnights within a year/month
i.e
Flights For July week 1 and 2 - 2012
Flights for July week 3 and 4 - 2012
so this is what I have so far..
eventually it'll have to be some kind of view model using automapper etc i am not sure as of yet how it'd get that neatly into some kind of ViewModel form...
var flightEntities = from f in flightsAsViewModels
select new
{
YearGroups = from flightYearGroup in context.Flights
group flightYearGroup by flightYearGroup.FlightDateTime.Year
into yearGroup
orderby yearGroup.Key descending
select new
{
Year = yearGroup.Key,
MonthGroups = from flightMonthGroup in yearGroup
group flightMonthGroup by flightMonthGroup.FlightDateTime.Month
into monthGroup
orderby monthGroup.Key ascending
select new {
Month = monthGroup.Key,
HalfMonthGroups = from months in monthGroup
group months by (months.FlightDateTime.Day <= 15 ? 1 : 2) into splitMonthFlights
orderby splitMonthFlights.Key
select new { WhichHalfOfMonth = splitMonthFlights.Key, Flights = splitMonthFlights }
}
}
};
I hereby pasted Linq code for the requirement. But not sure, this still can be achievable in shortest way. Please let me know if so.
var monthGroupedDates = from d in dates
group d by d.Month into fd
select new { Month = fd.Key, Dates = fd };
foreach (var g in monthGroupedDates)
{
var groupByHalf = from n in g.Dates
group n by (n.Day <= 15 ? 1 : 2) into gd
orderby gd.Key
select new { WhichHalf = gd.Key, Dates = gd };
foreach (var gh in groupByHalf)
{
string printString = (gh.WhichHalf == 1 ? "First" : "Second") + " week dates are:";
foreach (var h in gh.Dates)
{
printString += h.ToString("dd/MM/yyyy") + ";";
}
Console.WriteLine(printString);
}
}
Please note, dates are one which is mentioned in your requirement. If its Linq with SQL, this may need slight alterations.
Raj
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)
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.
I am having a problem with flex.
How can I get the number of Days in a particular month in Flex?
Thanks
Use the Date object , setting the day to 0, getDate will return the last day in the month which is also the day count; you have also to give the year you want to check, because you know february can have 29 days.
function getDayCount(year:int, month:int):int{
var d:Date=new Date(year, month, 0);
return d.getDate();
}
trace(getDayCount(2012,2));
The example above doesn't work for January!
new Date(2011,0,0) returns 12/31/2010
new Date(2011, 1, 0) returns 01/31/2011
new Date(2011, 1, 1) returns 02/01/2011
Create a new date object by specifying the year, desired month + 1, and a day of 0. This will create a date object for the last day of the desired month. Then call getDate() on the object to return the last day.
Note that months are zero based in Flex, so Jan = 0, Feb = 1, and so on. Therefore, if you want to know what the last day in Feb was for 2012 you would do the following:
var FEB:int = 1;
var date:Date = new Date(2012, FEB + 1, 0);
var lastDayInFeb:Number = date.getDate();
Here is a more complete example with a couple of non-unit tests and a reusable static method for returning the last day of a month.
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