[PATCH 19/23] kcalendarsystem: Move most week related code out ouf the way of regular calendar system code.

Jon Severinsson jon at severinsson.net
Fri Oct 12 15:13:54 UTC 2012


This commit changes no code whatsoever, it only moves it around a bit so the rest becomes more manageable.
---
 kdecore/CMakeLists.txt               |    1 +
 kdecore/date/kcalendarsystem.cpp     |  232 --------------------------
 kdecore/date/kcalendarsystem.h       |  306 +++++++++++++++++-----------------
 kdecore/date/kcalendarsystemweek.cpp |  254 ++++++++++++++++++++++++++++
 4 filer ändrade, 408 tillägg(+), 385 borttagningar(-)
 create mode 100644 kdecore/date/kcalendarsystemweek.cpp

diff --git a/kdecore/CMakeLists.txt b/kdecore/CMakeLists.txt
index ed8471f..068919f 100644
--- a/kdecore/CMakeLists.txt
+++ b/kdecore/CMakeLists.txt
@@ -163,6 +163,7 @@ set(kdecore_LIB_SRCS
    date/kcalendarsystemjulian.cpp
    date/kcalendarsystemminguo.cpp
    date/kcalendarsystemthai.cpp
+   date/kcalendarsystemweek.cpp
    date/kdatetime.cpp
    date/kdatetimeformatter.cpp
    date/kdatetimeparser.cpp
diff --git a/kdecore/date/kcalendarsystem.cpp b/kdecore/date/kcalendarsystem.cpp
index 92db979..69f1494 100644
--- a/kdecore/date/kcalendarsystem.cpp
+++ b/kdecore/date/kcalendarsystem.cpp
@@ -149,120 +149,6 @@ KCalendarSystemPrivate::~KCalendarSystemPrivate()
     delete m_eraList;
 }
 
-int KCalendarSystemPrivate::isoWeekNumber(const QDate &date, int *yearNum) const
-{
-    int y, m, d;
-    q->julianDayToDate(date.toJulianDay(), y, m, d);
-
-    QDate firstDayWeek1, lastDay;
-    int week;
-    int weekDay1, dayOfWeek1InYear;
-
-    // let's guess 1st day of 1st week
-    firstDayWeek1 = firstDayOfYear(y);
-    weekDay1 = q->dayOfWeek(firstDayWeek1);
-
-    // iso 8601: week 1  is the first containing thursday and week starts on monday
-    if (weekDay1 > 4 /*Thursday*/) {
-        firstDayWeek1 = q->addDays(firstDayWeek1 , 7 - weekDay1 + 1);   // next monday
-    }
-
-    dayOfWeek1InYear = dayOfYear(firstDayWeek1);
-
-    // our date in prev year's week
-    if (dayOfYear(date) < dayOfWeek1InYear) {
-        if (yearNum) {
-            *yearNum = addYears(y, - 1);
-        }
-        return isoWeeksInYear(addYears(y, - 1));
-    }
-
-    // let's check if its last week belongs to next year
-    lastDay = lastDayOfYear(y);
-
-    // if our date is in last week && 1st week in next year has thursday
-    if ((dayOfYear(date) >= daysInYear(y) - q->dayOfWeek(lastDay) + 1)
-            && q->dayOfWeek(lastDay) < 4) {
-        if (yearNum) {
-            * yearNum = addYears(y, 1);
-        }
-        week = 1;
-    } else {
-        // To calculate properly the number of weeks from day a to x let's make a day 1 of week
-        if (weekDay1 < 5) {
-            firstDayWeek1 = q->addDays(firstDayWeek1, -(weekDay1 - 1));
-        }
-
-        if (yearNum) {
-            * yearNum = y;
-        }
-
-        week = firstDayWeek1.daysTo(date) / 7 + 1;
-    }
-
-    return week;
-}
-
-int KCalendarSystemPrivate::regularWeekNumber(const QDate &date, int weekStartDay, int firstWeekNumber, int *weekYear) const
-{
-    int y, m, d;
-    q->julianDayToDate(date.toJulianDay(), y, m, d);
-
-    int firstWeekDayOffset = (q->dayOfWeek(date) - weekStartDay + 7) % 7;
-    int dayInYear = date.toJulianDay() - firstDayOfYear(y).toJulianDay();   // 0 indexed
-    int week = ((dayInYear - firstWeekDayOffset + 7) / 7);
-
-    if (q->dayOfWeek(firstDayOfYear(y)) != weekStartDay) {
-        week = week + firstWeekNumber;
-    }
-
-    if (week < 1) {
-        y = y - 1;
-        week = regularWeeksInYear(y, weekStartDay, firstWeekNumber);
-    }
-
-    if (weekYear) {
-        *weekYear = y;
-    }
-
-    return week;
-}
-
-int KCalendarSystemPrivate::simpleWeekNumber(const QDate &date, int *yearNum) const
-{
-    int y, m, d;
-    q->julianDayToDate(date.toJulianDay(), y, m, d);
-    if (yearNum) {
-        *yearNum = y;
-    }
-    return ((date.toJulianDay() - firstDayOfYear(y).toJulianDay()) / 7) + 1;
-}
-
-int KCalendarSystemPrivate::isoWeeksInYear(int year) const
-{
-    QDate lastDayOfThisYear = lastDayOfYear(year);
-
-    int weekYear = year;
-    int lastWeekInThisYear = isoWeekNumber(lastDayOfThisYear, &weekYear);
-
-    // If error, or the last day of the year is in the first week of next year use the week before
-    if (lastWeekInThisYear < 1 || weekYear != year) {
-        lastWeekInThisYear = isoWeekNumber(q->addDays(lastDayOfThisYear, -7), &weekYear);
-    }
-
-    return lastWeekInThisYear;
-}
-
-int KCalendarSystemPrivate::regularWeeksInYear(int year, int weekStartDay, int firstWeekNumber) const
-{
-    return regularWeekNumber(lastDayOfYear(year), weekStartDay, firstWeekNumber, 0);
-}
-
-int KCalendarSystemPrivate::simpleWeeksInYear(int year) const
-{
-    return simpleWeekNumber(lastDayOfYear(year), 0);
-}
-
 // Reimplement if special maths handling required, e.g. Hebrew.
 // Works for calendars with constant number of months, or where leap month is last month of year
 // Will not work for Hebrew or others where leap month is inserted in middle of year
@@ -790,50 +676,6 @@ bool KCalendarSystem::isValid(const QString &eraName, int yearInEra, int month,
     return (era.isValid() && isValid(era.year(yearInEra), month, day));
 }
 
-// NOT VIRTUAL - If override needed use shared-d
-bool KCalendarSystem::isValidIsoWeekDate(int year, int isoWeekNumber, int dayOfIsoWeek) const
-{
-    Q_D(const KCalendarSystem);
-
-    //Tests Year value in standard YMD isValid()
-    if (!isValid(year, 1, 1)) {
-        return false;
-    }
-
-    //Test Week Number falls in valid range for this year
-    int weeksInThisYear = weeksInYear(year);
-    if (isoWeekNumber < 1 || isoWeekNumber  > weeksInThisYear) {
-        return false;
-    }
-
-    //Test Day of Week Number falls in valid range
-    if (dayOfIsoWeek < 1 || dayOfIsoWeek > 7) {
-        return false;
-    }
-
-    //If not in earliest or latest years then all OK
-    //Otherwise need to check don't fall into previous or next year that would be invalid
-    if (year == d->earliestValidYear() && isoWeekNumber == 1) {
-        //If firstDayOfYear falls on or before Thursday then firstDayOfYear falls in week 1 this
-        //year and if wanted dayOfIsoWeek falls before firstDayOfYear then falls in previous year
-        //and so in invalid year
-        int dowFirstDay = dayOfWeek(d->firstDayOfYear(year));
-        if (dowFirstDay <= 4 && dayOfIsoWeek < dowFirstDay) {
-            return false;
-        }
-    } else if (year == d->latestValidYear() && isoWeekNumber == weeksInThisYear) {
-        //If lastDayOfYear falls on or after Thursday then lastDayOfYear falls in last week this
-        //year and if wanted dayOfIsoWeek falls after lastDayOfYear then falls in next year
-        //and so in invalid year
-        int dowLastDay = dayOfWeek(d->lastDayOfYear(year));
-        if (dowLastDay >= 4 && dayOfIsoWeek > dowLastDay) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
 bool KCalendarSystem::setDate(QDate &date, int year, int month, int day) const
 {
     date = QDate();
@@ -879,35 +721,6 @@ bool KCalendarSystem::setDate(QDate &date, QString eraName, int yearInEra, int m
     return (era.isValid() && setDate(date, era.year(yearInEra), month, day));
 }
 
-// NOT VIRTUAL - If override needed use shared-d
-bool KCalendarSystem::setDateIsoWeek(QDate &date, int year, int isoWeekNumber, int dayOfIsoWeek) const
-{
-    Q_D(const KCalendarSystem);
-
-    date = QDate();
-
-    if (isValidIsoWeekDate(year, isoWeekNumber, dayOfIsoWeek)) {
-
-        QDate calcDate = d->firstDayOfYear(year);
-        int dowFirstDayOfYear = dayOfWeek(calcDate);
-
-        int daysToAdd = (7 * (isoWeekNumber - 1)) + dayOfIsoWeek;
-
-        if (dowFirstDayOfYear <= 4) {
-            calcDate = calcDate.addDays(daysToAdd - dowFirstDayOfYear);
-        } else {
-            calcDate = calcDate.addDays(7 + daysToAdd - dowFirstDayOfYear);
-        }
-
-        if (isValid(calcDate)) {
-            date = calcDate;
-            return true;
-        }
-    }
-
-    return false;
-}
-
 // Deprecated
 bool KCalendarSystem::setYMD(QDate &date, int year, int month, int day) const
 {
@@ -1168,28 +981,6 @@ int KCalendarSystem::monthsInYear(int year) const
     return -1;
 }
 
-int KCalendarSystem::weeksInYear(int year, KLocale::WeekNumberSystem weekNumberSystem) const
-{
-    Q_D(const KCalendarSystem);
-
-    if (!isValid(year, 1, 1))
-        return -1;
-
-    switch (weekNumberSystem) {
-    case KLocale::IsoWeekNumber:
-        return d->isoWeeksInYear(year);
-    case KLocale::FirstFullWeek:
-        return d->regularWeeksInYear(year, locale()->weekStartDay(), 0);
-    case KLocale::FirstPartialWeek:
-        return d->regularWeeksInYear(year, locale()->weekStartDay(), 1);
-    case KLocale::SimpleWeek:
-        return d->simpleWeeksInYear(year);
-    case KLocale::DefaultWeekNumber:
-    default:
-        return weeksInYear(year, locale()->weekNumberSystem());
-    }
-}
-
 int KCalendarSystem::daysInYear(const QDate &date) const
 {
     Q_D(const KCalendarSystem);
@@ -1249,29 +1040,6 @@ int KCalendarSystem::dayOfYear(const QDate &date) const
     return -1;
 }
 
-
-int KCalendarSystem::week(const QDate &date, KLocale::WeekNumberSystem weekNumberSystem, int *yearNum) const
-{
-    Q_D(const KCalendarSystem);
-
-    if (!isValid(date))
-        return -1;
-
-    switch (weekNumberSystem) {
-    case KLocale::IsoWeekNumber:
-        return d->isoWeekNumber(date, yearNum);
-    case KLocale::FirstFullWeek:
-        return d->regularWeekNumber(date, locale()->weekStartDay(), 0, yearNum);
-    case KLocale::FirstPartialWeek:
-        return d->regularWeekNumber(date, locale()->weekStartDay(), 1, yearNum);
-    case KLocale::SimpleWeek:
-        return d->simpleWeekNumber(date, yearNum);
-    case KLocale::DefaultWeekNumber:
-    default:
-        return week(date, locale()->weekNumberSystem(), yearNum);
-    }
-}
-
 bool KCalendarSystem::isLeapYear(int year) const
 {
     Q_D(const KCalendarSystem);
diff --git a/kdecore/date/kcalendarsystem.h b/kdecore/date/kcalendarsystem.h
index 742713a..1635a68 100644
--- a/kdecore/date/kcalendarsystem.h
+++ b/kdecore/date/kcalendarsystem.h
@@ -226,18 +226,6 @@ public:
     bool isValid(const QString &eraName, int yearInEra, int month, int day) const;
 
     /**
-     * @since 4.4
-     *
-     * Returns whether a given date is valid in this calendar system.
-     *
-     * @param year the year portion of the date to check
-     * @param isoWeekNumber the ISO week portion of the date to check
-     * @param dayOfIsoWeek the day of week portion of the date to check
-     * @return @c true if the date is valid, @c false otherwise
-     */
-    bool isValidIsoWeekDate(int year, int isoWeekNumber, int dayOfIsoWeek) const;
-
-    /**
      * Returns whether a given date is valid in this calendar system.
      *
      * @param date the date to check
@@ -291,19 +279,6 @@ public:
     bool setDate(QDate &date, QString eraName, int yearInEra, int month, int day) const;
 
     /**
-     * @since 4.4
-     *
-     * Set a date using the year number, ISO week number and day of week number.
-     *
-     * @param date date to change
-     * @param year year
-     * @param isoWeekNumber ISO week of year
-     * @param dayOfIsoWeek day of week Mon..Sun (1..7)
-     * @return @c true if the date is valid, @c false otherwise
-     */
-    bool setDateIsoWeek(QDate &date, int year, int isoWeekNumber, int dayOfIsoWeek) const;
-
-    /**
      * @deprecated Use setDate() instead
      *
      * Some implementations reject year range 00 to 99, but extended date
@@ -510,35 +485,6 @@ public:
     int monthsInYear(int year) const;
 
     /**
-     * @since 4.7
-     *
-     * Returns the number of Weeks in a year using the specified Week Number System.
-     *
-     * @see week()
-     * @see formatDate()
-     * @param date the date to obtain year from
-     * @param weekNumberSystem the week number system to use
-     * @return number of weeks in the year, -1 if  date invalid
-     */
-    inline int weeksInYear(const QDate &date, KLocale::WeekNumberSystem weekNumberSystem = KLocale::DefaultWeekNumber) const
-    {
-        return isValid(date) ? weeksInYear(year(date), weekNumberSystem) : -1;
-    }
-
-    /**
-     * @since 4.7
-     *
-     * Returns the number of Weeks in a year using the specified Week Number System.
-     *
-     * @see week()
-     * @see formatDate()
-     * @param year the year
-     * @param weekNumberSystem the week number system to use
-     * @return number of weeks in the year, -1 if  date invalid
-     */
-    int weeksInYear(int year, KLocale::WeekNumberSystem weekNumberSystem = KLocale::DefaultWeekNumber) const;
-
-    /**
      * Returns the number of days in the given year.
      *
      * @param date the date to obtain year from
@@ -578,26 +524,6 @@ public:
     int daysInMonth(int year, int month) const;
 
     /**
-     * @deprecated use 7 instead
-     *
-     * Returns the number of days in the given week.
-     *
-     * @note This API is misdesigned, does not work, and have never worked. The
-     *       number of days in a week does not depend on the calendar system or
-     *       the date, only on the week number system used. For all week number
-     *       system ever supported by @c KCalendarSystem it returns, and has
-     *       always returned, @c 7.
-     *
-     * @param date ignored
-     * @return 7
-     */
-    KDECORE_DEPRECATED inline int daysInWeek(const QDate &date) const
-    {
-        Q_UNUSED(date);
-        return 7;
-    }
-
-    /**
      * Returns the day number of year for the given date
      *
      * The days are numbered 1..daysInYear()
@@ -608,85 +534,6 @@ public:
     virtual int dayOfYear(const QDate &date) const;
 
     /**
-     * Returns the weekday number for the given date
-     *
-     * The weekdays are numbered 1..7 for Monday..Sunday.
-     *
-     * This value is @em not affected by the value of weekStartDay()
-     *
-     * @param date the date to obtain day from
-     * @return day of week number, -1 if input date not valid
-     */
-    inline int dayOfWeek(const QDate &date) const
-    {
-        return isValid(date) ? date.dayOfWeek() : -1;
-    }
-
-    /**
-     * @deprecated use week() instead
-     *
-     * Returns the ISO week number for the given date.
-     *
-     * ISO 8601 defines the first week of the year as the week containing the first Thursday.
-     * See http://en.wikipedia.org/wiki/ISO_8601 and http://en.wikipedia.org/wiki/ISO_week_date
-     *
-     * If the date falls in the last week of the previous year or the first week of the following
-     * year, then the yearNum returned will be set to the appropriate year.
-     *
-     * @param date the date to obtain week from
-     * @param yearNum returns the year the date belongs to
-     * @return ISO week number, -1 if input date invalid
-     */
-    KDECORE_DEPRECATED inline int weekNumber(const QDate &date, int *yearNum = 0) const
-    {
-        return week(date, KLocale::IsoWeekNumber, yearNum);
-    }
-
-    /**
-     * Returns the localized Week Number for the date.
-     *
-     * This may be ISO, US, or any other supported week numbering scheme.  If
-     * you specifically require the ISO Week or any other scheme, you should use
-     * the week(KLocale::WeekNumberSystem) form.
-     *
-     * If the date falls in the last week of the previous year or the first
-     * week of the following year, then the yearNum returned will be set to the
-     * appropriate year.
-     *
-     * @see weeksInYear()
-     * @see formatDate()
-     * @param date the date to obtain week from
-     * @param yearNum returns the year the date belongs to
-     * @return localized week number, -1 if input date invalid
-     */
-    inline int week(const QDate &date, int *yearNum) const
-    {
-        return week(date, KLocale::DefaultWeekNumber, yearNum);
-    }
-
-    /**
-     * Returns the Week Number for the date in the required Week Number System.
-     *
-     * Unless you want a specific Week Number System (e.g. ISO Week), you should
-     * use the localized Week Number form of week().
-     *
-     * If the date falls in the last week of the previous year or the first
-     * week of the following year, then the yearNum returned will be set to the
-     * appropriate year.
-     *
-     * Technically, the ISO Week Number only applies to the ISO/Gregorian Calendar
-     * System, but the same rules will be applied to the current Calendar System.
-     *
-     * @see weeksInYear()
-     * @see formatDate()
-     * @param date the date to obtain week from
-     * @param weekNumberSystem the Week Number System to use
-     * @param yearNum returns the year the date belongs to
-     * @return week number, -1 if input date invalid
-     */
-    int week(const QDate &date, KLocale::WeekNumberSystem weekNumberSystem = KLocale::DefaultWeekNumber, int *yearNum = 0) const;
-
-    /**
      * Returns whether a given year is a leap year.
      *
      * Input year must be checked for validity in current Calendar System prior to calling, no
@@ -1390,6 +1237,159 @@ public:
     int applyShortYearWindow(int inputYear) const;
 
     /**
+     * Returns the weekday number for the given date
+     *
+     * The weekdays are numbered 1..7 for Monday..Sunday.
+     *
+     * This value is @em not affected by the value of weekStartDay()
+     *
+     * @param date the date to obtain day from
+     * @return day of week number, -1 if input date not valid
+     */
+    inline int dayOfWeek(const QDate &date) const
+    {
+        return isValid(date) ? date.dayOfWeek() : -1;
+    }
+
+    /**
+     * Returns the Week Number for the date in the required Week Number System.
+     *
+     * Unless you want a specific Week Number System (e.g. ISO Week), you should
+     * use the localized Week Number form of week().
+     *
+     * If the date falls in the last week of the previous year or the first
+     * week of the following year, then the yearNum returned will be set to the
+     * appropriate year.
+     *
+     * Technically, the ISO Week Number only applies to the ISO/Gregorian Calendar
+     * System, but the same rules will be applied to the current Calendar System.
+     *
+     * @see weeksInYear()
+     * @see formatDate()
+     * @param date the date to obtain week from
+     * @param weekNumberSystem the Week Number System to use
+     * @param yearNum returns the year the date belongs to
+     * @return week number, -1 if input date invalid
+     */
+    int week(const QDate &date, KLocale::WeekNumberSystem weekNumberSystem = KLocale::DefaultWeekNumber, int *yearNum = 0) const;
+
+    /**
+     * Returns the localized Week Number for the date.
+     *
+     * This may be ISO, US, or any other supported week numbering scheme.  If
+     * you specifically require the ISO Week or any other scheme, you should use
+     * the week(KLocale::WeekNumberSystem) form.
+     *
+     * If the date falls in the last week of the previous year or the first
+     * week of the following year, then the yearNum returned will be set to the
+     * appropriate year.
+     *
+     * @see weeksInYear()
+     * @see formatDate()
+     * @param date the date to obtain week from
+     * @param yearNum returns the year the date belongs to
+     * @return localized week number, -1 if input date invalid
+     */
+    inline int week(const QDate &date, int *yearNum) const
+    {
+        return week(date, KLocale::DefaultWeekNumber, yearNum);
+    }
+
+    /**
+     * @deprecated use week() instead
+     *
+     * Returns the ISO week number for the given date.
+     *
+     * ISO 8601 defines the first week of the year as the week containing the first Thursday.
+     * See http://en.wikipedia.org/wiki/ISO_8601 and http://en.wikipedia.org/wiki/ISO_week_date
+     *
+     * If the date falls in the last week of the previous year or the first week of the following
+     * year, then the yearNum returned will be set to the appropriate year.
+     *
+     * @param date the date to obtain week from
+     * @param yearNum returns the year the date belongs to
+     * @return ISO week number, -1 if input date invalid
+     */
+    KDECORE_DEPRECATED inline int weekNumber(const QDate &date, int *yearNum = 0) const
+    {
+        return week(date, KLocale::IsoWeekNumber, yearNum);
+    }
+
+    /**
+     * @since 4.7
+     *
+     * Returns the number of Weeks in a year using the specified Week Number System.
+     *
+     * @see week()
+     * @see formatDate()
+     * @param date the date to obtain year from
+     * @param weekNumberSystem the week number system to use
+     * @return number of weeks in the year, -1 if  date invalid
+     */
+    inline int weeksInYear(const QDate &date, KLocale::WeekNumberSystem weekNumberSystem = KLocale::DefaultWeekNumber) const
+    {
+        return isValid(date) ? weeksInYear(year(date), weekNumberSystem) : -1;
+    }
+
+    /**
+     * @since 4.7
+     *
+     * Returns the number of Weeks in a year using the specified Week Number System.
+     *
+     * @see week()
+     * @see formatDate()
+     * @param year the year
+     * @param weekNumberSystem the week number system to use
+     * @return number of weeks in the year, -1 if  date invalid
+     */
+    int weeksInYear(int year, KLocale::WeekNumberSystem weekNumberSystem = KLocale::DefaultWeekNumber) const;
+
+    /**
+     * @deprecated use 7 instead
+     *
+     * Returns the number of days in the given week.
+     *
+     * @note This API is misdesigned, does not work, and have never worked. The
+     *       number of days in a week does not depend on the calendar system or
+     *       the date, only on the week number system used. For all week number
+     *       system ever supported by @c KCalendarSystem it returns, and has
+     *       always returned, @c 7.
+     *
+     * @param date ignored
+     * @return 7
+     */
+    KDECORE_DEPRECATED inline int daysInWeek(const QDate &date) const
+    {
+        Q_UNUSED(date);
+        return 7;
+    }
+
+    /**
+     * @since 4.4
+     *
+     * Returns whether a given date is valid in this calendar system.
+     *
+     * @param year the year portion of the date to check
+     * @param isoWeekNumber the ISO week portion of the date to check
+     * @param dayOfIsoWeek the day of week portion of the date to check
+     * @return @c true if the date is valid, @c false otherwise
+     */
+    bool isValidIsoWeekDate(int year, int isoWeekNumber, int dayOfIsoWeek) const;
+
+    /**
+     * @since 4.4
+     *
+     * Set a date using the year number, ISO week number and day of week number.
+     *
+     * @param date date to change
+     * @param year year
+     * @param isoWeekNumber ISO week of year
+     * @param dayOfIsoWeek day of week Mon..Sun (1..7)
+     * @return @c true if the date is valid, @c false otherwise
+     */
+    bool setDateIsoWeek(QDate &date, int year, int isoWeekNumber, int dayOfIsoWeek) const;
+
+    /**
      * Use this to determine which day is the first day of the week.
      *
      * Uses the calendar system's internal locale set when the instance was
diff --git a/kdecore/date/kcalendarsystemweek.cpp b/kdecore/date/kcalendarsystemweek.cpp
new file mode 100644
index 0000000..ba7fff4
--- /dev/null
+++ b/kdecore/date/kcalendarsystemweek.cpp
@@ -0,0 +1,254 @@
+/*
+    Copyright (c) 2002 Carlos Moro <cfmoro at correo.uniovi.es>
+    Copyright (c) 2002 Hans Petter Bieker <bieker at kde.org>
+    Copyright 2007, 2008, 2009, 2010 John Layt <john at layt.net>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "kcalendarsystem.h"
+#include "kcalendarsystemprivate_p.h"
+
+
+int KCalendarSystemPrivate::isoWeekNumber(const QDate &date, int *yearNum) const
+{
+    int y, m, d;
+    q->julianDayToDate(date.toJulianDay(), y, m, d);
+
+    QDate firstDayWeek1, lastDay;
+    int week;
+    int weekDay1, dayOfWeek1InYear;
+
+    // let's guess 1st day of 1st week
+    firstDayWeek1 = firstDayOfYear(y);
+    weekDay1 = q->dayOfWeek(firstDayWeek1);
+
+    // iso 8601: week 1  is the first containing thursday and week starts on monday
+    if (weekDay1 > 4 /*Thursday*/) {
+        firstDayWeek1 = q->addDays(firstDayWeek1 , 7 - weekDay1 + 1);   // next monday
+    }
+
+    dayOfWeek1InYear = dayOfYear(firstDayWeek1);
+
+    // our date in prev year's week
+    if (dayOfYear(date) < dayOfWeek1InYear) {
+        if (yearNum) {
+            *yearNum = addYears(y, - 1);
+        }
+        return isoWeeksInYear(addYears(y, - 1));
+    }
+
+    // let's check if its last week belongs to next year
+    lastDay = lastDayOfYear(y);
+
+    // if our date is in last week && 1st week in next year has thursday
+    if ((dayOfYear(date) >= daysInYear(y) - q->dayOfWeek(lastDay) + 1)
+            && q->dayOfWeek(lastDay) < 4) {
+        if (yearNum) {
+            * yearNum = addYears(y, 1);
+        }
+        week = 1;
+    } else {
+        // To calculate properly the number of weeks from day a to x let's make a day 1 of week
+        if (weekDay1 < 5) {
+            firstDayWeek1 = q->addDays(firstDayWeek1, -(weekDay1 - 1));
+        }
+
+        if (yearNum) {
+            * yearNum = y;
+        }
+
+        week = firstDayWeek1.daysTo(date) / 7 + 1;
+    }
+
+    return week;
+}
+
+int KCalendarSystemPrivate::regularWeekNumber(const QDate &date, int weekStartDay, int firstWeekNumber, int *weekYear) const
+{
+    int y, m, d;
+    q->julianDayToDate(date.toJulianDay(), y, m, d);
+
+    int firstWeekDayOffset = (q->dayOfWeek(date) - weekStartDay + 7) % 7;
+    int dayInYear = date.toJulianDay() - firstDayOfYear(y).toJulianDay();   // 0 indexed
+    int week = ((dayInYear - firstWeekDayOffset + 7) / 7);
+
+    if (q->dayOfWeek(firstDayOfYear(y)) != weekStartDay) {
+        week = week + firstWeekNumber;
+    }
+
+    if (week < 1) {
+        y = y - 1;
+        week = regularWeeksInYear(y, weekStartDay, firstWeekNumber);
+    }
+
+    if (weekYear) {
+        *weekYear = y;
+    }
+
+    return week;
+}
+
+int KCalendarSystemPrivate::simpleWeekNumber(const QDate &date, int *yearNum) const
+{
+    int y, m, d;
+    q->julianDayToDate(date.toJulianDay(), y, m, d);
+    if (yearNum) {
+        *yearNum = y;
+    }
+    return ((date.toJulianDay() - firstDayOfYear(y).toJulianDay()) / 7) + 1;
+}
+
+int KCalendarSystemPrivate::isoWeeksInYear(int year) const
+{
+    QDate lastDayOfThisYear = lastDayOfYear(year);
+
+    int weekYear = year;
+    int lastWeekInThisYear = isoWeekNumber(lastDayOfThisYear, &weekYear);
+
+    // If error, or the last day of the year is in the first week of next year use the week before
+    if (lastWeekInThisYear < 1 || weekYear != year) {
+        lastWeekInThisYear = isoWeekNumber(q->addDays(lastDayOfThisYear, -7), &weekYear);
+    }
+
+    return lastWeekInThisYear;
+}
+
+int KCalendarSystemPrivate::regularWeeksInYear(int year, int weekStartDay, int firstWeekNumber) const
+{
+    return regularWeekNumber(lastDayOfYear(year), weekStartDay, firstWeekNumber, 0);
+}
+
+int KCalendarSystemPrivate::simpleWeeksInYear(int year) const
+{
+    return simpleWeekNumber(lastDayOfYear(year), 0);
+}
+
+
+int KCalendarSystem::weeksInYear(int year, KLocale::WeekNumberSystem weekNumberSystem) const
+{
+    Q_D(const KCalendarSystem);
+
+    if (!isValid(year, 1, 1))
+        return -1;
+
+    switch (weekNumberSystem) {
+    case KLocale::IsoWeekNumber:
+        return d->isoWeeksInYear(year);
+    case KLocale::FirstFullWeek:
+        return d->regularWeeksInYear(year, locale()->weekStartDay(), 0);
+    case KLocale::FirstPartialWeek:
+        return d->regularWeeksInYear(year, locale()->weekStartDay(), 1);
+    case KLocale::SimpleWeek:
+        return d->simpleWeeksInYear(year);
+    case KLocale::DefaultWeekNumber:
+    default:
+        return weeksInYear(year, locale()->weekNumberSystem());
+    }
+}
+
+int KCalendarSystem::week(const QDate &date, KLocale::WeekNumberSystem weekNumberSystem, int *yearNum) const
+{
+    Q_D(const KCalendarSystem);
+
+    if (!isValid(date))
+        return -1;
+
+    switch (weekNumberSystem) {
+    case KLocale::IsoWeekNumber:
+        return d->isoWeekNumber(date, yearNum);
+    case KLocale::FirstFullWeek:
+        return d->regularWeekNumber(date, locale()->weekStartDay(), 0, yearNum);
+    case KLocale::FirstPartialWeek:
+        return d->regularWeekNumber(date, locale()->weekStartDay(), 1, yearNum);
+    case KLocale::SimpleWeek:
+        return d->simpleWeekNumber(date, yearNum);
+    case KLocale::DefaultWeekNumber:
+    default:
+        return week(date, locale()->weekNumberSystem(), yearNum);
+    }
+}
+
+bool KCalendarSystem::isValidIsoWeekDate(int year, int isoWeekNumber, int dayOfIsoWeek) const
+{
+    Q_D(const KCalendarSystem);
+
+    //Tests Year value in standard YMD isValid()
+    if (!isValid(year, 1, 1)) {
+        return false;
+    }
+
+    //Test Week Number falls in valid range for this year
+    int weeksInThisYear = weeksInYear(year);
+    if (isoWeekNumber < 1 || isoWeekNumber  > weeksInThisYear) {
+        return false;
+    }
+
+    //Test Day of Week Number falls in valid range
+    if (dayOfIsoWeek < 1 || dayOfIsoWeek > 7) {
+        return false;
+    }
+
+    //If not in earliest or latest years then all OK
+    //Otherwise need to check don't fall into previous or next year that would be invalid
+    if (year == d->earliestValidYear() && isoWeekNumber == 1) {
+        //If firstDayOfYear falls on or before Thursday then firstDayOfYear falls in week 1 this
+        //year and if wanted dayOfIsoWeek falls before firstDayOfYear then falls in previous year
+        //and so in invalid year
+        int dowFirstDay = dayOfWeek(d->firstDayOfYear(year));
+        if (dowFirstDay <= 4 && dayOfIsoWeek < dowFirstDay) {
+            return false;
+        }
+    } else if (year == d->latestValidYear() && isoWeekNumber == weeksInThisYear) {
+        //If lastDayOfYear falls on or after Thursday then lastDayOfYear falls in last week this
+        //year and if wanted dayOfIsoWeek falls after lastDayOfYear then falls in next year
+        //and so in invalid year
+        int dowLastDay = dayOfWeek(d->lastDayOfYear(year));
+        if (dowLastDay >= 4 && dayOfIsoWeek > dowLastDay) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool KCalendarSystem::setDateIsoWeek(QDate &date, int year, int isoWeekNumber, int dayOfIsoWeek) const
+{
+    Q_D(const KCalendarSystem);
+
+    date = QDate();
+
+    if (isValidIsoWeekDate(year, isoWeekNumber, dayOfIsoWeek)) {
+
+        QDate calcDate = d->firstDayOfYear(year);
+        int dowFirstDayOfYear = dayOfWeek(calcDate);
+
+        int daysToAdd = (7 * (isoWeekNumber - 1)) + dayOfIsoWeek;
+
+        if (dowFirstDayOfYear <= 4) {
+            calcDate = calcDate.addDays(daysToAdd - dowFirstDayOfYear);
+        } else {
+            calcDate = calcDate.addDays(7 + daysToAdd - dowFirstDayOfYear);
+        }
+
+        if (isValid(calcDate)) {
+            date = calcDate;
+            return true;
+        }
+    }
+
+    return false;
+}
-- 
1.7.10.4



More information about the Kde-frameworks-devel mailing list