Bug 131342 - KCalendarSystem::addMonths() does not always work for Hijri and Jalali calendars
Summary: KCalendarSystem::addMonths() does not always work for Hijri and Jalali calendars
Status: RESOLVED INTENTIONAL
Alias: None
Product: kdelibs
Classification: Frameworks and Libraries
Component: kdecore (show other bugs)
Version: unspecified
Platform: Gentoo Packages Linux
: NOR normal
Target Milestone: ---
Assignee: John Layt
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-07-25 11:32 UTC by nq
Modified: 2009-03-15 19:41 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description nq 2006-07-25 11:32:11 UTC
Version:            (using KDE KDE 3.5.3)
Installed from:    Gentoo Packages
Compiler:          gcc-4.1.1 
OS:                Linux

addMonths(const QDate &date, int nmonths) in KCalendarSystemHijri and KCalendarSystemJalali does not return an incremented date if the day of initial date does not exist in the new month.

Example (with Hijri selected as calendar system):

QDate date;
KGlobal::locale()->calendar()->setYMD(date, 1427, 3, 30);
date = KGlobal::locale()->calendar()->addMonths(date, 1);
//date has not changed

Solution:

If day of initial date is greater than days in new month, then set day to last day in new month. 

change line 563 in kcalendarsystemhijri.cpp and line 300 in kcalendarsystemjalali.cpp from

setYMD( result, y, m, day(date));

to something like

setYMD(result, y, m, 1);
int d = day(date), nDaysInMonth = daysInMonth(result);
if(d > nDaysInMonth) setYMD(result, y, m, nDaysInMonth);
else setYMD(result, y, m, d);

or just copy  KCalendarSystemHebrew::addMonths()
Comment 1 nq 2006-07-25 12:32:56 UTC
KCalendarSystemHebrew::addMonths() does not work correctly either as it adds the number of days in the current month. 

Example:

QDate date;
KGlobal::locale()->calendar()->setYMD(date, 5766, 7, 30);
date = KGlobal::locale()->calendar()->addMonths(date, 1);
// date is now at month 9, day 1

Comment 2 nq 2006-07-28 12:00:06 UTC
Same problem with addYears().

Here is my generic functions for working solving the problems:

QDate KCalendarSystem::addMonths(const QDate &date, int nmonths) {
	QDate result = date;
	int m = month(date);
	int d =  day(date);
	if(nmonths > 0) {
		int nMonthsInYear = monthsInYear(result);
		while(nmonths > 0 && m + nmonths > nMonthsInYear) {
			setYMD(result, year(result) + 1, 1, 1);
			nmonths -= nMonthsInYear - m + 1;
			m = 1;
			nMonthsInYear = monthsInYear(result);
		}
		if(nmonths > 0) {
			setYMD(result, year(result), m + nmonths, 1);
		}
		if(d != 1) {
			int nDaysInMonth = daysInMonth(result);
			if(d > nDaysInMonth) result = addDays(result, nDaysInMonth - 1);
			else result = addDays(result, d - 1);
		}		
	} else if(nmonths < 0) {
		while(nmonths < 0 && m + nmonths < 1) {
			setYMD(result, year(result) - 1, 1, 1);
			int nMonthsInYear = monthsInYear(result);
			setYMD(result, year(result), nMonthsInYear, 1);
			nmonths += m;
			m = nMonthsInYear;
		}
		if(nmonths < 0) {
			setYMD(result, year(result), m + nmonths, 1);
		}
		if(d != 1) {
			int nDaysInMonth = daysInMonth(result);
			if(d > nDaysInMonth) result = addDays(result, nDaysInMonth - 1);
			else result = addDays(result, d - 1);
		}
	}
	return result;
}

QDate KCalendarSystem::addYears(const QDate &date, int nyears) {
	QDate result = date;
	int y = year(date) + nyears;
	int d = day(date);
	int m = month(date);
	setYMD(result, y, 1, 1);
	if(m > monthsInYear(result)) {
		setYMD(result, y + 1, 1, 1);
		addDays(result, -1);
	}	
	setYMD(result, y, m, 1);
	if(d > daysInMonth(result)) {
		d = daysInMonth(result);
	}
	setYMD(result, y, m, d);
	return result;
}
Comment 3 John Layt 2008-10-16 21:37:22 UTC
Assign to me to work on.  Check KDE4 which should be correct and back-port if possible.
Comment 4 John Layt 2009-03-15 19:41:35 UTC
Works OK in KDE4, will not be back-ported to KDE3 as there will probably not be anymore KDE3 releases.