diff --git a/src/astroseasons.h b/src/astroseasons.h index 6f4be6d..d04c6fc 100644 --- a/src/astroseasons.h +++ b/src/astroseasons.h @@ -1,103 +1,103 @@ /* This file is part of the kholidays library. Copyright (c) 2004,2006-2007 Allen Winter 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. */ #ifndef KHOLIDAYS_ASTROSEASONS_H #define KHOLIDAYS_ASTROSEASONS_H #include "kholidays_export.h" class QDate; class QString; namespace KHolidays { /** Represents and manages the Astronomical Seasons (solstices and equinoxes). For the purposes of this class, we sometimes use the shorthand of "Season" where we really mean "Astronomical Season". An Astronomical Season can be one of the following: - June solstice - December solstice - March equinox - September equinox A very good description of the astronomical seasons can be read at the Wikipedia, - http://en.wikipedia.org/wiki/Seasons + https://en.wikipedia.org/wiki/Seasons Note that this class represents the "Astronomical Seasons" and not the traditional "Seasons" which vary widely by culture. */ class KHOLIDAYS_EXPORT AstroSeasons //krazy:exclude=dpointer { public: enum Season { JuneSolstice, DecemberSolstice, MarchEquinox, SeptemberEquinox, None }; /** * Return the Gregorian date on which the season occurs in given year. * * @param season Season to return a date for * @param year Year for which to return the date * @since 5.50 */ static QDate seasonDate(Season season, int year); /** Return the season for the specified Gregorian date. The enum 'None' is returned if one of the supported seasons does not occur on the date. @param date compute the season for the specified Gregorian date. */ static Season seasonAtDate(const QDate &date); /** Return the season as a text string for the specified date. A null string is returned if one of the supported seasons does not occur on the date. @param date compute the season for the specified Gregorian date. */ static QString seasonNameAtDate(const QDate &date); /** Return the string representation of season. @param season astronomical season. */ static QString seasonName(Season season); }; } #endif diff --git a/src/holidayregion.h b/src/holidayregion.h index f8a9a49..5586976 100644 --- a/src/holidayregion.h +++ b/src/holidayregion.h @@ -1,246 +1,246 @@ /* This file is part of the kholidays library. Copyright (c) 2001 Cornelius Schumacher Copyright (c) 2004 Allen Winter Copyright (c) 2008 David Jarvie Copyright 2010 John Layt 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. */ #ifndef KHOLIDAYS_HOLIDAYREGION_H #define KHOLIDAYS_HOLIDAYREGION_H #include "kholidays_export.h" #include #include #include "holiday.h" class QDate; class QStringList; class QFileInfo; namespace KHolidays { /** Represents a holiday region. */ class KHOLIDAYS_EXPORT HolidayRegion { public: /** * Creates a new Holiday Region object for a given standard Region Code. * * @param regionCode The code for the Holiday Region. * If null or unknown, an empty instance will be created. */ explicit HolidayRegion(const QString ®ionCode = QString()); /** * Creates a new Holiday Region object from a given holiday file. * If file doesn't exist, an empty instance will be created. * * @param regionFile The code for the Holiday Region. */ explicit HolidayRegion(const QFileInfo ®ionFile); /** * Destroys the holidays object. */ ~HolidayRegion(); /** * @since 4.5 * * Return a list of all available Holiday Region codes. * * One of these can then be passed to the constructor for a new HolidayRegion * object, or to name() or language() to obtain the name and language of the region. * * @see name() * @see languageCode() */ static QStringList regionCodes(); /** * @since 4.6 * * Return a reasonable default Holiday Region code * * If a required country/language is not provided then the current KDE * country/lanaguage is used. * * @param country The country to find a default Holiday Region for * @param language The lanaguage to find a default Holiday Region for * @return the full region code of the default file */ static QString defaultRegionCode(const QString &country = QString(), const QString &language = QString()); /** * @since 4.5 * * Returns the unique Holiday Region code. * * Clients should not infer any meaning from the format of the code. * * @return region code, or null if the instance was constructed with * an unknown region */ QString regionCode() const; /** * @since 4.5 * * Return the ISO 3166 country code of the file * * May be either just a country code ("US" = USA) or may include a regional * identifier ("US-CA" = California). Returns "XX" if not a country. * - * See http://en.wikipedia.org/wiki/ISO_3166-2 + * See https://en.wikipedia.org/wiki/ISO_3166-2 * * @return the full region code of the file */ QString countryCode() const; /** * @since 4.5 * * Return the ISO 3166 country code of a given Holiday Region * * May be either just a country code ("US" = USA) or may include a regional * identifier ("US-CA" = California). Returns "XX" if not a country. * - * See http://en.wikipedia.org/wiki/ISO_3166-2 + * See https://en.wikipedia.org/wiki/ISO_3166-2 * * @param regionCode The code for the Holiday Region. * @return the full region code of the file */ static QString countryCode(const QString ®ionCode); /** * @since 4.5 * * Return the ISO 639-1 language code of the file * * May be either just a language code ("en" = US English) or may include a country * identifier ("en_GB" = British English). * * @return the language code of the file */ QString languageCode() const; /** * @since 4.5 * * Return the ISO 639-1 language code of a given Holiday Region * * May be either just a language code ("en" = US English) or may include a country * identifier ("en_GB" = British English). * * @param regionCode The code for the Holiday Region. * @return the language code of the file */ static QString languageCode(const QString ®ionCode); /** * @since 4.5 * * Return the name of the Holiday Region. * This may be a country, region, or type. * * @return the short name code of the file */ QString name() const; /** * @since 4.5 * * Return the name of a given Holiday Region * * @param regionCode The code for the Holiday Region. * @return the name of the Holiday Region */ static QString name(const QString ®ionCode); /** * @since 4.5 * * Return the description of the Holiday Region if available * * @return the description of the Holiday Region */ QString description() const; /** * @since 4.5 * * Return the description of a given Holiday Region if available * * @return the description of the Holiday Region */ static QString description(const QString ®ionCode); /** * @since 4.6 * * Returns the list of holidays that occur between @p startDate and @p endDate. */ Holiday::List holidays(const QDate &startDate, const QDate &endDate) const; /** * @since 4.6 * * Returns the list of holidays that occur on a @p date. */ Holiday::List holidays(const QDate &date) const; /** * @since 4.6 * * Returns the list of holidays that occur in a Gregorian calendar year @p calendarYear. */ Holiday::List holidays(int calendarYear) const; /** * Checks whether there is any holiday defined for a @p date. */ bool isHoliday(const QDate &date) const; /** * Returns whether the instance contains any holiday data. */ bool isValid() const; /** * @since 4.5 * * Returns whether the Region Code is valid. */ static bool isValid(const QString ®ionCode); private: Q_DISABLE_COPY(HolidayRegion) class HolidayRegionPrivate; HolidayRegionPrivate *const d; }; } #endif // KHOLIDAYS_HOLIDAYREGION_H diff --git a/src/lunarphase.h b/src/lunarphase.h index 2c4ff6d..411349f 100644 --- a/src/lunarphase.h +++ b/src/lunarphase.h @@ -1,99 +1,99 @@ /* This file is part of the kholidays library. Copyright (c) 2004,2007,2009 Allen Winter 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. */ #ifndef KHOLIDAYS_LUNARPHASE_H #define KHOLIDAYS_LUNARPHASE_H #include "kholidays_export.h" class QDate; class QString; namespace KHolidays { /** Represents and manages a Lunar Phase A Lunar Phase can be one of the following: + "new": the moon is not visible; or traditionally: first visible crescent of the Moon. For religious purposes, the new month begins when the first crescent moon can be seen. Thus, it is impossible to be certain in advance of when months will begin; in particular, the exact date on which Ramadan will begin is not known in advance. In Saudi Arabia, observers are sent up in airplanes if the weather is cloudy when the new moon is expected. + "first quarter": the right 50% of the moon is visible. + "full": the moon is fully visible. + "last quarter": the left 50% of the moon is visible. A very good description of the lunar phases can be read at the Wikipedia, - http://en.wikipedia.org/wiki/Lunar_phase + https://en.wikipedia.org/wiki/Lunar_phase Note that crescent and gibbous phases are not currently supported. */ class KHOLIDAYS_EXPORT LunarPhase //krazy:exclude=dpointer { public: /** Phases of the moon, in traditional English notation. The phase @c None is used only as an error indicator, for instance in phase(). */ enum Phase { NewMoon, ///< New moon phase FirstQuarter, ///< First quarter of moon phase LastQuarter, ///< Last quarter of moon phase FullMoon, ///< Full moon phase None ///< Indication for error }; /** Return the lunar phase for the specified Gregorian date. The enum 'None' is returned if one of the supported phases does not occur on the date. @param date compute the lunar phase for the specified Gregorian date. */ static Phase phaseAtDate(const QDate &date); /** Return the lunar phase as a text string for the specified date. A null string is returned if one of the supported phases does not occur on the date. @param date compute the lunar phase for the specified Gregorian date. */ static QString phaseNameAtDate(const QDate &date); /** Return the string representation of phase. @param phase the lunar phase. */ static QString phaseName(Phase phase); }; } #endif diff --git a/src/parsers/qcalendarsystem.cpp b/src/parsers/qcalendarsystem.cpp index 09d9d5d..2f044bc 100644 --- a/src/parsers/qcalendarsystem.cpp +++ b/src/parsers/qcalendarsystem.cpp @@ -1,1271 +1,1271 @@ /* This file is part of the kholidays library. Copyright 2014 John Layt 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 "qcalendarsystem_p.h" #include #include #include "qdebug.h" class QCalendarSystemPrivate : public QSharedData { public: explicit QCalendarSystemPrivate(QCalendarSystem::CalendarSystem calendar); QCalendarSystem::CalendarSystem calendarSystem() const; qint64 epoch() const; qint64 earliestValidDate() const; int earliestValidYear() const; qint64 latestValidDate() const; int latestValidYear() const; int yearOffset() const; int maxMonthsInYear() const; int monthsInYear(int year) const; int maxDaysInYear() const; int daysInYear(int year) const; int maxDaysInMonth() const; int daysInMonth(int year, int month) const; bool hasYearZero() const; bool hasLeapMonths() const; int quarter(int month) const; bool isLeapYear(int year) const; void julianDayToDate(qint64 jd, int *year, int *month, int *day) const; qint64 julianDayFromDate(int year, int month, int day) const; bool isValidYear(int year) const; bool isValidMonth(int year, int month) const; int addYears(int y1, int years) const; int diffYears(int y1, int y2) const; QCalendarSystem::CalendarSystem m_calendarSystem; }; static const char julianMonths[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; QCalendarSystemPrivate::QCalendarSystemPrivate(QCalendarSystem::CalendarSystem calendar) : QSharedData(), m_calendarSystem(calendar) { } QCalendarSystem::CalendarSystem QCalendarSystemPrivate::calendarSystem() const { if (m_calendarSystem == QCalendarSystem::DefaultCalendar) { return QCalendarSystem::GregorianCalendar; } else { return m_calendarSystem; } } qint64 QCalendarSystemPrivate::epoch() const { switch (calendarSystem()) { case QCalendarSystem::GregorianCalendar: return 1721426; // 0001-01-01 Gregorian case QCalendarSystem::CopticCalendar: return 1825030; // 0001-01-01 == 0284-08-29 Gregorian case QCalendarSystem::EthiopicCalendar: return 1724221; // 0001-01-01 == 0008-08-29 Gregorian case QCalendarSystem::EthiopicAmeteAlemCalendar: return -284655; // 0001-01-01 == -5492-08-29 Gregorian case QCalendarSystem::IndianNationalCalendar: return 1749994; // 0000-01-01 == 0078-03-22 Gregorian case QCalendarSystem::IslamicCivilCalendar: return 1948440; // 0001-01-01 == 0622-07-19 Gregorian case QCalendarSystem::ISO8601Calendar: return 1721060; // 0000-01-01 Gregorian case QCalendarSystem::JapaneseCalendar: return 1721426; // 0001-01-01 Gregorian case QCalendarSystem::JulianCalendar: return 1721424; // 0001-01-01 == Gregorian case QCalendarSystem::ROCCalendar: return 2419403; // 0001-01-01 == 1912-01-01 Gregorian case QCalendarSystem::ThaiCalendar: return 1522734; // 0000-01-01 == -0544-01-01 Gregorian default: return 0; } } qint64 QCalendarSystemPrivate::earliestValidDate() const { switch (calendarSystem()) { case QCalendarSystem::GregorianCalendar: return -31738; // -4800-01-01 Gregorian case QCalendarSystem::CopticCalendar: return 1825030; // 0001-01-01 == 0284-08-29 Gregorian case QCalendarSystem::EthiopicCalendar: return 1724221; // 0001-01-01 == 0008-08-29 Gregorian case QCalendarSystem::EthiopicAmeteAlemCalendar: return -284655; // 0001-01-01 == -5492-08-29 Gregorian case QCalendarSystem::IndianNationalCalendar: return 1749994; // 0000-01-01 == 0078-03-22 Gregorian case QCalendarSystem::IslamicCivilCalendar: return 1948440; // 0001-01-01 == 0622-07-19 Gregorian case QCalendarSystem::ISO8601Calendar: return 1721060; // 0000-01-01 Gregorian case QCalendarSystem::JapaneseCalendar: return -31738; // -4800-01-01 Gregorian case QCalendarSystem::JulianCalendar: return -31776; // -4800-01-01 Julian case QCalendarSystem::ROCCalendar: return 2419403; // 0001-01-01 == 1912-01-01 Gregorian case QCalendarSystem::ThaiCalendar: return 1522734; // 0000-01-01 == -0544-01-01 Gregorian default: return 0; } } int QCalendarSystemPrivate::earliestValidYear() const { switch (calendarSystem()) { case QCalendarSystem::GregorianCalendar: case QCalendarSystem::JapaneseCalendar: case QCalendarSystem::JulianCalendar: return -4800; case QCalendarSystem::IndianNationalCalendar: case QCalendarSystem::ISO8601Calendar: case QCalendarSystem::ThaiCalendar: return 0; default: return 1; } } qint64 QCalendarSystemPrivate::latestValidDate() const { switch (calendarSystem()) { case QCalendarSystem::GregorianCalendar: return 5373484; // 9999-12-31 Gregorian case QCalendarSystem::CopticCalendar: return 5477164; // 9999-13-05 == 10283-11-12 Gregorian case QCalendarSystem::EthiopicCalendar: return 5376721; // 9999-13-05 == 10008-11-10 Gregorian case QCalendarSystem::EthiopicAmeteAlemCalendar: return 3367114; // 9999-13-05 == 4506-09-29 Gregorian case QCalendarSystem::IndianNationalCalendar: return 5402054; // 9999-12-30 == 10078-03-21 Gregorian case QCalendarSystem::IslamicCivilCalendar: return 5491751; // 9999-12-29 == 10323-10-21 Gregorian case QCalendarSystem::ISO8601Calendar: return 5373484; // 9999-12-31 Gregorian case QCalendarSystem::JapaneseCalendar: return 5373484; // 9999-12-31 Gregorian case QCalendarSystem::JulianCalendar: return 5373557; // 9999-12-31 == 10000-03-13 Gregorian case QCalendarSystem::ROCCalendar: return 6071462; // 9999-12-31 == 11910-12-31 Gregorian case QCalendarSystem::ThaiCalendar: return 5175158; // 9999-12-31 == 9456-12-31 Gregorian default: return 0; } } int QCalendarSystemPrivate::latestValidYear() const { switch (calendarSystem()) { default: return 9999; } } int QCalendarSystemPrivate::yearOffset() const { switch (calendarSystem()) { case QCalendarSystem::ROCCalendar: return 1911; // 0001-01-01 == 1912-01-01 Gregorian case QCalendarSystem::ThaiCalendar: return -543; // 0000-01-01 == -544-01-01 Gregorian default: return 0; } } int QCalendarSystemPrivate::maxMonthsInYear() const { switch (calendarSystem()) { case QCalendarSystem::CopticCalendar: case QCalendarSystem::EthiopicCalendar: case QCalendarSystem::EthiopicAmeteAlemCalendar: return 13; default: return 12; } } int QCalendarSystemPrivate::monthsInYear(int year) const { //year = year + yearOffset(); Q_UNUSED(year); switch (calendarSystem()) { case QCalendarSystem::CopticCalendar: case QCalendarSystem::EthiopicCalendar: case QCalendarSystem::EthiopicAmeteAlemCalendar: return 13; default: return 12; } } int QCalendarSystemPrivate::maxDaysInYear() const { switch (calendarSystem()) { case QCalendarSystem::IslamicCivilCalendar: return 355; default: return 366; } } int QCalendarSystemPrivate::daysInYear(int year) const { switch (calendarSystem()) { case QCalendarSystem::IslamicCivilCalendar: return isLeapYear(year) ? 355 : 354; default: return isLeapYear(year) ? 366 : 365; } } int QCalendarSystemPrivate::maxDaysInMonth() const { switch (calendarSystem()) { case QCalendarSystem::CopticCalendar: case QCalendarSystem::EthiopicCalendar: case QCalendarSystem::EthiopicAmeteAlemCalendar: case QCalendarSystem::IslamicCivilCalendar: return 30; default: return 31; } } int QCalendarSystemPrivate::daysInMonth(int year, int month) const { if (month < 1 || month > monthsInYear(year)) { return 0; } switch (calendarSystem()) { case QCalendarSystem::GregorianCalendar: case QCalendarSystem::ISO8601Calendar: case QCalendarSystem::JapaneseCalendar: case QCalendarSystem::ROCCalendar: case QCalendarSystem::ThaiCalendar: case QCalendarSystem::JulianCalendar: { if (month == 2 && isLeapYear(year)) { return 29; } else { return julianMonths[month]; } } case QCalendarSystem::CopticCalendar: case QCalendarSystem::EthiopicCalendar: case QCalendarSystem::EthiopicAmeteAlemCalendar: { if (month == 13) { return isLeapYear(year) ? 6 : 5; } else { return 30; } } case QCalendarSystem::IndianNationalCalendar: { if (month >= 7) { return 30; } else if (month >= 2) { return 31; } else if (isLeapYear(year)) { return 31; } else { return 30; } } case QCalendarSystem::IslamicCivilCalendar: { if (month == 12 && isLeapYear(year)) { return 30; } else if (month % 2 == 0) { return 29; } else { return 30; } } default: return 0; } } bool QCalendarSystemPrivate::hasYearZero() const { switch (calendarSystem()) { case QCalendarSystem::IndianNationalCalendar: case QCalendarSystem::ISO8601Calendar: case QCalendarSystem::ThaiCalendar: return true; default: return false; } } bool QCalendarSystemPrivate::hasLeapMonths() const { switch (calendarSystem()) { default: return false; } } int QCalendarSystemPrivate::quarter(int month) const { switch (calendarSystem()) { case QCalendarSystem::CopticCalendar: case QCalendarSystem::EthiopicCalendar: case QCalendarSystem::EthiopicAmeteAlemCalendar: if (month == 13) { // Consider the short epagomenal month as part of the 4th quarter return 4; } Q_FALLTHROUGH(); default: return (((month - 1) / 3) + 1); } } bool QCalendarSystemPrivate::isLeapYear(int year) const { year = year + yearOffset(); // Uses same rule as Gregorian and in same years as Gregorian to keep in sync // Can't use yearOffset() as this offset only applies for isLeapYear() if (calendarSystem() == QCalendarSystem::IndianNationalCalendar) { year = year + 78; } if (year < 1 && !hasYearZero()) { ++year; } switch (calendarSystem()) { case QCalendarSystem::GregorianCalendar: case QCalendarSystem::IndianNationalCalendar: case QCalendarSystem::ISO8601Calendar: case QCalendarSystem::JapaneseCalendar: case QCalendarSystem::ROCCalendar: case QCalendarSystem::ThaiCalendar: return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0); case QCalendarSystem::CopticCalendar: case QCalendarSystem::EthiopicCalendar: case QCalendarSystem::EthiopicAmeteAlemCalendar: return (year % 4 == 3); case QCalendarSystem::JulianCalendar: return (year % 4 == 0); case QCalendarSystem::IslamicCivilCalendar: return ((((11 * year) + 14) % 30) < 11); default: return false; } } void QCalendarSystemPrivate::julianDayToDate(qint64 jd, int *year, int *month, int *day) const { int yy = 0, mm = 0, dd = 0; switch (calendarSystem()) { case QCalendarSystem::GregorianCalendar: case QCalendarSystem::ISO8601Calendar: case QCalendarSystem::JapaneseCalendar: case QCalendarSystem::ROCCalendar: case QCalendarSystem::ThaiCalendar: { // Formula from The Calendar FAQ by Claus Tondering - // http://www.tondering.dk/claus/cal/node3.html#SECTION003161000000000000000 + // https://www.tondering.dk/claus/calendar.html qint64 a = jd + 32044; qint64 b = ((4 * a) + 3) / 146097; qint64 c = a - ((146097 * b) / 4); qint64 d = ((4 * c) + 3) / 1461; qint64 e = c - ((1461 * d) / 4); qint64 m = ((5 * e) + 2) / 153; dd = e - (((153 * m) + 2) / 5) + 1; mm = m + 3 - (12 * (m / 10)); yy = (100 * b) + d - 4800 + (m / 10); break; } case QCalendarSystem::CopticCalendar: case QCalendarSystem::EthiopicCalendar: case QCalendarSystem::EthiopicAmeteAlemCalendar: { // Formula derived from first principles by John Layt qint64 s = jd - (epoch() - 365); qint64 l = s / 1461; yy = (l * 4) + qMin(static_cast(3), (s % 1461) / 365); qint64 diy = s - (yy * 365) + (yy / 4); mm = (diy / 30) + 1; dd = (diy % 30) + 1; break; } case QCalendarSystem::IndianNationalCalendar: { // Formula from the "Explanatory Supplement to the Astronomical Almanac" // Revised Edition 2006 section 12.94 pp 605-606, US Naval Observatory // Originally from the "Report of the Calendar Reform Committee" 1955, Indian Government qint64 l = jd + 68518; qint64 n = (4 * l) / 146097; l = l - (146097 * n + 3) / 4; qint64 i = (4000 * (l + 1)) / 1461001; l = l - (1461 * i) / 4 + 1; qint64 j = ((l - 1) / 31) * (1 - l / 185) + (l / 185) * ((l - 156) / 30 + 5) - l / 366; dd = l - 31 * j + ((j + 2) / 8) * (j - 5); l = j / 11; mm = j + 2 - 12 * l; yy = 100 * (n - 49) + l + i - 78; break; } case QCalendarSystem::IslamicCivilCalendar: { // Formula from the "Explanatory Supplement to the Astronomical Almanac" // Revised Edition 2006 section ??? pp ???, US Naval Observatory // Derived from Fliegel & Van Flandern 1968 qint64 l = jd - epoch() + 10632; qint64 n = (l - 1) / 10631; l = l - 10631 * n + 354; int j = ((10985 - l) / 5316) * ((50 * l) / 17719) + (l / 5670) * ((43 * l) / 15238); l = l - ((30 - j) / 15) * ((17719 * j) / 50) - (j / 16) * ((15238 * j) / 43) + 29; yy = (30 * n) + j - 30; mm = (24 * l) / 709; dd = l - ((709 * mm) / 24); break; } case QCalendarSystem::JulianCalendar: { // Formula from The Calendar FAQ by Claus Tondering - // http://www.tondering.dk/claus/cal/node3.html#SECTION003161000000000000000 + // https://www.tondering.dk/claus/calendar.html qint64 b = 0; qint64 c = jd + 32082; qint64 d = ((4 * c) + 3) / 1461; qint64 e = c - ((1461 * d) / 4); qint64 m = ((5 * e) + 2) / 153; dd = e - (((153 * m) + 2) / 5) + 1; mm = m + 3 - (12 * (m / 10)); yy = (100 * b) + d - 4800 + (m / 10); break; } default: break; } if (!hasYearZero() && yy < 1) { yy -= 1; } yy = yy - yearOffset(); if (year) { *year = yy; } if (month) { *month = mm; } if (day) { *day = dd; } } qint64 QCalendarSystemPrivate::julianDayFromDate(int year, int month, int day) const { qint64 jd = 0; year = year + yearOffset(); if (year < 1 && !hasYearZero()) { year = year + 1; } switch (calendarSystem()) { case QCalendarSystem::GregorianCalendar: case QCalendarSystem::ISO8601Calendar: case QCalendarSystem::JapaneseCalendar: case QCalendarSystem::ROCCalendar: case QCalendarSystem::ThaiCalendar: { // Formula from The Calendar FAQ by Claus Tondering - // http://www.tondering.dk/claus/cal/node3.html#SECTION003161000000000000000 + // https://www.tondering.dk/claus/calendar.html int a = (14 - month) / 12; year = year + 4800 - a; int m = month + (12 * a) - 3; jd = day + (((153 * m) + 2) / 5) + (365 * year) + (year / 4) - (year / 100) + (year / 400) - 32045; break; } case QCalendarSystem::CopticCalendar: case QCalendarSystem::EthiopicCalendar: case QCalendarSystem::EthiopicAmeteAlemCalendar: { // Formula derived from first principles by John Layt jd = epoch() - 1 + ((year - 1) * 365) + (year / 4) + ((month - 1) * 30) + day; break; } case QCalendarSystem::IndianNationalCalendar: { // Formula from the "Explanatory Supplement to the Astronomical Almanac" // Revised Edition 2006 section 12.94 pp 605-606, US Naval Observatory // Originally from the "Report of the Calendar Reform Committee" 1955, Indian Government jd = 365 * year + (year + 78 - 1 / month) / 4 + 31 * month - (month + 9) / 11 - (month / 7) * (month - 7) - (3 * ((year + 78 - 1 / month) / 100 + 1)) / 4 + day + 1749579; break; } case QCalendarSystem::IslamicCivilCalendar: { // Formula from the "Explanatory Supplement to the Astronomical Almanac" // Revised Edition 2006 section ??? pp ???, US Naval Observatory // Derived from Fliegel & Van Flandern 1968 jd = (3 + (11 * year)) / 30 + 354 * year + 30 * month - (month - 1) / 2 + day + epoch() - 385; break; } case QCalendarSystem::JulianCalendar: { // Formula from The Calendar FAQ by Claus Tondering - // http://www.tondering.dk/claus/cal/node3.html#SECTION003161000000000000000 + // https://www.tondering.dk/claus/calendar.html int a = (14 - month) / 12; year = year + 4800 - a; int m = month + (12 * a) - 3; jd = day + (((153 * m) + 2) / 5) + (365 * year) + (year / 4) - 32083; break; } default: break; } return jd; } // Some private utility rules bool QCalendarSystemPrivate::isValidYear(int year) const { return year >= earliestValidYear() && year <= latestValidYear() && (year == 0 ? hasYearZero() : true); } bool QCalendarSystemPrivate::isValidMonth(int year, int month) const { return isValidYear(year) && month >= 1 && month <= monthsInYear(year); } int QCalendarSystemPrivate::addYears(int y1, int years) const { int y2 = y1 + years; if (!hasYearZero()) { if (y1 > 0 && y2 <= 0) { --y2; } else if (y1 < 0 && y2 >= 0) { ++y2; } } return y2; } int QCalendarSystemPrivate::diffYears(int y1, int y2) const { int dy = y2 - y1; if (!hasYearZero()) { if (y2 > 0 && y1 < 0) { dy -= 1; } else if (y2 < 0 && y1 > 0) { dy += 1; } } return dy; } // QCalendarSystem public api QCalendarSystem::QCalendarSystem(QCalendarSystem::CalendarSystem calendar) : d(new QCalendarSystemPrivate(calendar)) { } QCalendarSystem::~QCalendarSystem() { } QCalendarSystem &QCalendarSystem::operator=(const QCalendarSystem &other) { d = other.d; return *this; } QCalendarSystem::CalendarSystem QCalendarSystem::calendarSystem() const { return d->calendarSystem(); } QDate QCalendarSystem::epoch() const { return QDate::fromJulianDay(d->epoch()); } QDate QCalendarSystem::earliestValidDate() const { return QDate::fromJulianDay(d->earliestValidDate()); } QDate QCalendarSystem::latestValidDate() const { return QDate::fromJulianDay(d->latestValidDate()); } int QCalendarSystem::maximumMonthsInYear() const { return d->maxMonthsInYear(); } int QCalendarSystem::maximumDaysInYear() const { return d->maxDaysInYear(); } int QCalendarSystem::maximumDaysInMonth() const { return d->maxDaysInMonth(); } bool QCalendarSystem::isValid(const QDate &date) const { return date.isValid() && date >= earliestValidDate() && date <= latestValidDate(); } bool QCalendarSystem::isValid(int year, int month, int day) const { return d->isValidMonth(year, month) && day >= 1 && day <= d->daysInMonth(year, month); } bool QCalendarSystem::isValid(int year, int dayOfYear) const { return d->isValidYear(year) && dayOfYear > 0 && dayOfYear <= d->daysInYear(year); } QDate QCalendarSystem::date(int year, int month, int day) const { if (isValid(year, month, day)) { return QDate::fromJulianDay(d->julianDayFromDate(year, month, day)); } else { return QDate(); } } QDate QCalendarSystem::date(int year, int dayOfYear) const { if (isValid(year, dayOfYear)) { return QDate::fromJulianDay(d->julianDayFromDate(year, 1, 1) + dayOfYear - 1); } else { return QDate(); } } void QCalendarSystem::getDate(const QDate &date, int *year, int *month, int *day) const { int yy = 0; int mm = 0; int dd = 0; if (isValid(date)) { d->julianDayToDate(date.toJulianDay(), &yy, &mm, &dd); } if (year) { *year = yy; } if (month) { *month = mm; } if (day) { *day = dd; } } int QCalendarSystem::year(const QDate &date) const { int y = 0; if (isValid(date)) { d->julianDayToDate(date.toJulianDay(), &y, nullptr, nullptr); } return y; } int QCalendarSystem::month(const QDate &date) const { int m = 0; if (isValid(date)) { d->julianDayToDate(date.toJulianDay(), nullptr, &m, nullptr); } return m; } int QCalendarSystem::day(const QDate &date) const { int dd = 0; if (isValid(date)) { d->julianDayToDate(date.toJulianDay(), nullptr, nullptr, &dd); } return dd; } int QCalendarSystem::quarter(const QDate &date) const { if (isValid(date)) { int month; d->julianDayToDate(date.toJulianDay(), nullptr, &month, nullptr); return d->quarter(month); } else { return 0; } } int QCalendarSystem::quarter(int year, int month, int day) const { if (isValid(year, month, day)) { return d->quarter(month); } else { return 0; } } int QCalendarSystem::dayOfYear(const QDate &date) const { if (isValid(date)) { return date.toJulianDay() - firstDayOfYear(date).toJulianDay() + 1; } else { return 0; } } int QCalendarSystem::dayOfYear(int year, int month, int day) const { return dayOfYear(date(year, month, day)); } int QCalendarSystem::dayOfWeek(const QDate &date) const { //jd 0 = Monday = weekday 1. We've never skipped weekdays. if (isValid(date)) { if (date.toJulianDay() >= 0) { return (date.toJulianDay() % daysInWeek()) + 1; } else { return ((date.toJulianDay() + 1) % daysInWeek()) + daysInWeek(); } } else { return 0; } } int QCalendarSystem::dayOfWeek(int year, int month, int day) const { return dayOfWeek(date(year, month, day)); } //TODO These are ISO weeks, may need to localise int QCalendarSystem::weekNumber(const QDate &date, int *yearNum) const { if (isValid(date)) { int year, month, day; d->julianDayToDate(date.toJulianDay(), &year, &month, &day); return weekNumber(year, month, day, yearNum); } else { return 0; } } /* \legalese Copyright (c) 1989 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms are permitted provided that the above copyright notice and this paragraph are duplicated in all such forms and that any documentation, advertising materials, and other materials related to such distribution and use acknowledge that the software was developed by the University of California, Berkeley. The name of the University may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ //TODO These are ISO weeks, may need to localise //TODO Replace with cleanly licensed routine int QCalendarSystem::weekNumber(int year, int month, int day, int *yearNum) const { if (!isValid(year, month, day)) { if (yearNum) { *yearNum = 0; } return 0; } int yday = dayOfYear(year, month, day) - 1; int wday = dayOfWeek(year, month, day); if (wday == 7) { wday = 0; } int w; for (;;) { int len, bot, top; len = d->daysInYear(year); /* ** What yday (-3 ... 3) does ** the ISO year begin on? */ bot = ((yday + 11 - wday) % 7) - 3; /* ** What yday does the NEXT ** ISO year begin on? */ top = bot - (len % 7); if (top < -3) { top += 7; } top += len; if (yday >= top) { ++year; w = 1; break; } if (yday >= bot) { w = 1 + ((yday - bot) / 7); break; } --year; yday += d->daysInYear(year); } if (yearNum) { *yearNum = year; } return w; } int QCalendarSystem::monthsInYear(const QDate &date) const { if (isValid(date)) { return d->monthsInYear(year(date)); } else { return 0; } } int QCalendarSystem::monthsInYear(int year) const { if (d->isValidYear(year)) { return d->monthsInYear(year); } else { return 0; } } int QCalendarSystem::weeksInYear(const QDate &date) const { if (isValid(date)) { return weeksInYear(year(date)); } else { return 0; } } //TODO This is ISO weeks, may need to localise int QCalendarSystem::weeksInYear(int year) const { if (d->isValidYear(year)) { int weekYear = year; int lastWeek = weekNumber(lastDayOfYear(year), &weekYear); if (lastWeek < 1 || weekYear != year) { lastWeek = weekNumber(addDays(lastDayOfYear(year), -7), &weekYear); } return lastWeek; } else { return 0; } } int QCalendarSystem::daysInYear(const QDate &date) const { if (isValid(date)) { return d->daysInYear(year(date)); } else { return 0; } } int QCalendarSystem::daysInYear(int year) const { if (d->isValidYear(year)) { return d->daysInYear(year); } else { return 0; } } int QCalendarSystem::daysInMonth(const QDate &date) const { if (isValid(date)) { int year, month; d->julianDayToDate(date.toJulianDay(), &year, &month, nullptr); return d->daysInMonth(year, month); } else { return 0; } } int QCalendarSystem::daysInMonth(int year, int month) const { if (d->isValidMonth(year, month)) { return d->daysInMonth(year, month); } else { return 0; } } int QCalendarSystem::daysInWeek() const { return 7; } bool QCalendarSystem::isLeapYear(const QDate &date) const { if (isValid(date)) { return d->isLeapYear(year(date)); } else { return false; } } bool QCalendarSystem::isLeapYear(int year) const { if (d->isValidYear(year)) { return d->isLeapYear(year); } else { return false; } } QDate QCalendarSystem::addYears(const QDate &dt, int years) const { if (isValid(dt)) { int year, month, day; d->julianDayToDate(dt.toJulianDay(), &year, &month, &day); year = d->addYears(year, years); month = qMin(month, d->monthsInYear(year)); return date(year, month, qMin(day, d->daysInMonth(year, month))); } else { return QDate(); } } QDate QCalendarSystem::addMonths(const QDate &dt, int months) const { if (isValid(dt)) { int year, month, day; d->julianDayToDate(dt.toJulianDay(), &year, &month, &day); while (months != 0) { if (months < 0) { if (month + months >= 1) { month += months; months = 0; } else if (months < 0) { year = d->addYears(year, -1); months += d->monthsInYear(year); } } else { int miy = d->monthsInYear(year); if (month + months <= miy) { month += months; months = 0; } else { year = d->addYears(year, 1); months -= miy; } } } return date(year, month, qMin(day, d->daysInMonth(year, month))); } else { return QDate(); } } QDate QCalendarSystem::addDays(const QDate &date, int days) const { return date.addDays(days); } //Caters for Leap Months, but possibly not for Hebrew int QCalendarSystem::yearsDifference(const QDate &fromDate, const QDate &toDate) const { if (!isValid(fromDate) || !isValid(toDate) || toDate == fromDate) { return 0; } if (toDate < fromDate) { return - yearsDifference(toDate, fromDate); } int y1, m1, d1, y2, m2, d2; d->julianDayToDate(fromDate.toJulianDay(), &y1, &m1, &d1); d->julianDayToDate(toDate.toJulianDay(), &y2, &m2, &d2); if (y2 == y1) { return 0; } if (m2 > m1) { return d->diffYears(y1, y2); } if (m2 < m1) { return d->diffYears(y1, y2) - 1; } // m2 == m1 // Allow for last day of month to last day of month and leap days // e.g. 2000-02-29 to 2001-02-28 is 1 year not 0 years if ((d2 >= d1) || (d1 == d->daysInMonth(y1, m1) && d2 == d->daysInMonth(y2, m2))) { return d->diffYears(y1, y2); } else { return d->diffYears(y1, y2) - 1; } } //Caters for Leap Months, but possibly not for Hebrew int QCalendarSystem::monthsDifference(const QDate &fromDate, const QDate &toDate) const { if (!isValid(fromDate) || !isValid(toDate) || toDate == fromDate) { return 0; } if (toDate < fromDate) { return - monthsDifference(toDate, fromDate); } int y1, m1, d1, y2, m2, d2, my; d->julianDayToDate(fromDate.toJulianDay(), &y1, &m1, &d1); d->julianDayToDate(toDate.toJulianDay(), &y2, &m2, &d2); // Calculate number of months in full years preceding y2 if (y2 == y1) { my = 0; } else if (d->hasLeapMonths()) { my = 0; for (int y = y1; y < y2; y = d->addYears(y, 1)) { my = my + monthsInYear(y); } } else { my = d->diffYears(y1, y2) * monthsInYear(y2); } // Allow for last day of month to last day of month and leap days // e.g. 2010-03-31 to 2010-04-30 is 1 month not 0 months // also 2000-02-29 to 2001-02-28 is 12 months not 11 months if ((d2 >= d1) || (d1 == d->daysInMonth(y1, m1) && d2 == d->daysInMonth(y2, m2))) { return my + m2 - m1; } else { return my + m2 - m1 - 1; } } qint64 QCalendarSystem::daysDifference(const QDate &fromDate, const QDate &toDate) const { if (isValid(fromDate) && isValid(toDate)) { return toDate.toJulianDay() - fromDate.toJulianDay(); } else { return 0; } } //Caters for Leap Months, but possibly not for Hebrew void QCalendarSystem::dateDifference(const QDate &fromDate, const QDate &toDate, int *years, int *months, int *days, int *direction) const { int dy = 0; int dm = 0; int dd = 0; int dir = 1; if (isValid(fromDate) && isValid(toDate) && fromDate != toDate) { if (toDate < fromDate) { dateDifference(toDate, fromDate, &dy, &dm, &dd, nullptr); dir = -1; } else { int y1, m1, d1, y2, m2, d2; d->julianDayToDate(fromDate.toJulianDay(), &y1, &m1, &d1); d->julianDayToDate(toDate.toJulianDay(), &y2, &m2, &d2); dy = yearsDifference(fromDate, toDate); // Calculate months and days difference int miy0 = d->monthsInYear(d->addYears(y2, -1)); if (d2 >= d1) { dm = (miy0 + m2 - m1) % miy0; dd = d2 - d1; } else { // d2 < d1 // Allow for last day of month to last day of month and leap days // e.g. 2010-03-31 to 2010-04-30 is 1 month // 2000-02-29 to 2001-02-28 is 1 year // 2000-02-29 to 2001-03-01 is 1 year 1 day int dim0 = daysInMonth(addMonths(toDate, -1)); int dim1 = d->daysInMonth(y1, m1); if (d1 == dim1 && d2 == d->daysInMonth(y2, m2)) { dm = (miy0 + m2 - m1) % miy0; dd = 0; } else if (month(addMonths(toDate, -1)) == m1 && dim0 < dim1) { // Special case where fromDate = leap day and toDate in month following but non-leap year // e.g. 2000-02-29 to 2001-03-01 needs to use 29 to calculate day number not 28 dm = (miy0 + m2 - m1 - 1) % miy0; dd = (dim1 + d2 - d1) % dim1; } else { dm = (miy0 + m2 - m1 - 1) % miy0; dd = (dim0 + d2 - d1) % dim0; } } } } if (years) { *years = dy; } if (months) { *months = dm; } if (days) { *days = dd; } if (direction) { *direction = dir; } } QDate QCalendarSystem::firstDayOfYear(const QDate &dt) const { if (isValid(dt)) { return date(year(dt), 1, 1); } else { return QDate(); } } QDate QCalendarSystem::firstDayOfYear(int year) const { return date(year, 1, 1); } QDate QCalendarSystem::lastDayOfYear(const QDate &dt) const { if (isValid(dt)) { int y = year(dt); return date(y, d->daysInYear(y)); } else { return QDate(); } } QDate QCalendarSystem::lastDayOfYear(int year) const { if (d->isValidYear(year)) { return date(year, d->daysInYear(year)); } else { return QDate(); } } QDate QCalendarSystem::firstDayOfMonth(const QDate &dt) const { int year, month; getDate(dt, &year, &month, nullptr); return date(year, month, 1); } QDate QCalendarSystem::firstDayOfMonth(int year, int month) const { return date(year, month, 1); } QDate QCalendarSystem::lastDayOfMonth(const QDate &dt) const { int year, month; getDate(dt, &year, &month, nullptr); return date(year, month, daysInMonth(year, month)); } QDate QCalendarSystem::lastDayOfMonth(int year, int month) const { return date(year, month, daysInMonth(year, month)); } diff --git a/src/sunriseset.cpp b/src/sunriseset.cpp index f47e5a9..0b91dce 100644 --- a/src/sunriseset.cpp +++ b/src/sunriseset.cpp @@ -1,209 +1,209 @@ /* This file is part of the kholidays library. - Adapted from the Javascript found at http://www.esrl.noaa.gov/gmd/grad/solcalc + Adapted from the Javascript found at https://www.esrl.noaa.gov/gmd/grad/solcalc which is in the public domain. Copyright (c) 2012 Allen Winter 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 "sunriseset.h" #include static const double PI = 3.14159265358979323846; static const double MaxLat = 89.99; static const double MaxLong = 179.99; using namespace KHolidays; using namespace SunRiseSet; static double degToRad(double degree) { return (degree * PI) / 180.00; } static double radToDeg(double rad) { return (rad * 180.0) / PI; } //convert Julian Day to centuries since J2000.0. static double calcTimeJulianCent(int jday) { return (double(jday) - 2451545.0) / 36525.0; } //calculate the mean obliquity of the ecliptic (in degrees) static double calcMeanObliquityOfEcliptic(double t) { double seconds = 21.448 - t * (46.8150 + t * (0.00059 - t * 0.001813)); double e0 = 23.0 + (26.0 + (seconds / 60.0)) / 60.0; return e0; // in degrees } //calculate the corrected obliquity of the ecliptic (in degrees) static double calcObliquityCorrection(double t) { double e0 = calcMeanObliquityOfEcliptic(t); double omega = 125.04 - 1934.136 * t; double e = e0 + 0.00256 * cos(degToRad(omega)); return e; // in degrees } //calculate the Geometric Mean Longitude of the Sun (in degrees) static double calcGeomMeanLongSun(double t) { double L0 = 280.46646 + t * (36000.76983 + 0.0003032 * t); while (L0 > 360.0) { L0 -= 360.0; } while (L0 < 0.0) { L0 += 360.0; } return L0; // in degrees } //calculate the Geometric Mean Anomaly of the Sun (in degrees) static double calcGeomMeanAnomalySun(double t) { double M = 357.52911 + t * (35999.05029 - 0.0001537 * t); return M; // in degrees } //calculate the equation of center for the sun (in degrees) static double calcSunEqOfCenter(double t) { double m = calcGeomMeanAnomalySun(t); double mrad = degToRad(m); double sinm = sin(mrad); double sin2m = sin(mrad + mrad); double sin3m = sin(mrad + mrad + mrad); double C = sinm * (1.914602 - t * (0.004817 + 0.000014 * t)) + sin2m * (0.019993 - 0.000101 * t) + sin3m * 0.000289; return C; // in degrees } //calculate the true longitude of the sun (in degrees) static double calcSunTrueLong(double t) { double l0 = calcGeomMeanLongSun(t); double c = calcSunEqOfCenter(t); double O = l0 + c; return O; // in degrees } //calculate the apparent longitude of the sun (in degrees) static double calcSunApparentLong(double t) { double o = calcSunTrueLong(t); double omega = 125.04 - 1934.136 * t; double lambda = o - 0.00569 - 0.00478 * sin(degToRad(omega)); return lambda; // in degrees } //calculate the declination of the sun (in degrees) static double calcSunDeclination(double t) { double e = calcObliquityCorrection(t); double lambda = calcSunApparentLong(t); double sint = sin(degToRad(e)) * sin(degToRad(lambda)); double theta = radToDeg(asin(sint)); return theta; // in degrees } //calculate the eccentricity of earth's orbit (unitless) static double calcEccentricityEarthOrbit(double t) { double e = 0.016708634 - t * (0.000042037 + 0.0000001267 * t); return e; // unitless } //calculate the difference between true solar time and mean solar time //(output: equation of time in minutes of time) static double calcEquationOfTime(double t) { double epsilon = calcObliquityCorrection(t); double l0 = calcGeomMeanLongSun(t); double e = calcEccentricityEarthOrbit(t); double m = calcGeomMeanAnomalySun(t); double y = tan(degToRad(epsilon) / 2.0); y *= y; double sin2l0 = sin(2.0 * degToRad(l0)); double sinm = sin(degToRad(m)); double cos2l0 = cos(2.0 * degToRad(l0)); double sin4l0 = sin(4.0 * degToRad(l0)); double sin2m = sin(2.0 * degToRad(m)); double Etime = y * sin2l0 - 2.0 * e * sinm + 4.0 * e * y * sinm * cos2l0 - 0.5 * y * y * sin4l0 - 1.25 * e * e * sin2m; return radToDeg(Etime) * 4.0; // in minutes of time } //calculate the hour angle of the sun at sunrise for the latitude (in radians) static double calcHourAngleSunrise(double latitude, double solarDec) { double latRad = degToRad(latitude); double sdRad = degToRad(solarDec); double HAarg = (cos(degToRad(90.833)) / (cos(latRad) * cos(sdRad)) - tan(latRad) * tan(sdRad)); double HA = acos(HAarg); return HA; // in radians (for sunset, use -HA) } QTime KHolidays::SunRiseSet::utcSunrise(const QDate &date, double latitude, double longitude) { latitude = qMax(qMin(MaxLat, latitude), -MaxLat); longitude = qMax(qMin(MaxLong, longitude), -MaxLong); double t = calcTimeJulianCent(date.toJulianDay()); double eqTime = calcEquationOfTime(t); double solarDec = calcSunDeclination(t); double hourAngle = calcHourAngleSunrise(latitude, solarDec); double delta = longitude + radToDeg(hourAngle); QTime timeUTC(0, 0); if (std::isnan(delta)) { return timeUTC; } timeUTC = timeUTC.addSecs((720 - (4.0 * delta) - eqTime) * 60); return QTime(timeUTC.hour(), timeUTC.second() > 29 ? timeUTC.minute() + 1 : timeUTC.minute(), 0); } QTime KHolidays::SunRiseSet::utcSunset(const QDate &date, double latitude, double longitude) { latitude = qMax(qMin(MaxLat, latitude), -MaxLat); longitude = qMax(qMin(MaxLong, longitude), -MaxLong); double t = calcTimeJulianCent(date.toJulianDay()); double eqTime = calcEquationOfTime(t); double solarDec = calcSunDeclination(t); double hourAngle = -calcHourAngleSunrise(latitude, solarDec); double delta = longitude + radToDeg(hourAngle); QTime timeUTC(0, 0); if (std::isnan(delta)) { return timeUTC; } timeUTC = timeUTC.addSecs((720 - (4.0 * delta) - eqTime) * 60); return QTime(timeUTC.hour(), timeUTC.second() > 29 ? timeUTC.minute() + 1 : timeUTC.minute(), 0); } diff --git a/src/zodiac.h b/src/zodiac.h index e2ec6bf..28a8b87 100644 --- a/src/zodiac.h +++ b/src/zodiac.h @@ -1,131 +1,131 @@ /* This file is part of the kholidays library. Copyright (c) 2005-2007 Allen Winter 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. */ #ifndef KHOLIDAYS_ZODIAC_H #define KHOLIDAYS_ZODIAC_H #include "kholidays_export.h" #include class QDate; class QString; namespace KHolidays { class ZodiacPrivate; /** Represents and manages the Zodiac calendar. The Tropical and Sidereal Zodiacs are supported. A very good description of the Zodiac calendars can be read at the Wikipedia, - http://en.wikipedia.org/wiki/Zodiac + https://en.wikipedia.org/wiki/Zodiac Disclaimer: I am by no means a Zodiac expert. I put together this software based on some quick scanning of documents I found on the WWW. Feel free to contact me about this code if you have improvements. Sign Symbol Birthdates Tropical Sidereal Aries ram Mar 21 - Apr 19 Apr 14 - May 14 Taurus bull Apr 20 - May 20 May 15 - Jun 14 Gemini twins May 21 - Jun 20 Jun 15 - Jul 16 Cancer crab Jun 21 - Jul 22 Jul 17 - Aug 16 Leo lion Jul 23 - Aug 22 Aug 17 - Sep 16 Virgo virgin Aug 23 - Sep 22 Sep 17 - Oct 17 Libra scale Sep 23 - Oct 22 Oct 18 - Nov 16 Scorpio scorpion Oct 23 - Nov 21 Nov 17 - Dec 15 Sagittarius archer Nov 22 - Dec 21 Dec 16 - Jan 14 Capricorn goat Dec 22 - Jan 19 Jan 15 - Feb 12 Aquarius water Jan 20 - Feb 18 Feb 13 - Mar 14 Pisces fish Feb 19 - Mar 20 Mar 15 - Apr 13 */ class KHOLIDAYS_EXPORT Zodiac { public: enum ZodiacType { Tropical, Sidereal }; enum ZodiacSigns { Aries, Taurus, Gemini, Cancer, Leo, Virgo, Libra, Scorpio, Sagittarius, Capricorn, Aquarius, Pisces, None }; explicit Zodiac(ZodiacType type); Zodiac(const Zodiac &other); ~Zodiac(); Zodiac &operator=(const Zodiac &other); /** Return the Zodiac sign for the specified Gregorian date. The enum 'None' is returned if one of the supported signs does not occur on the date. @param date compute the Zodiac sign for the specified Gregorian date. */ ZodiacSigns signAtDate(const QDate &date) const; /** Return the Zodiac sign as a text string for the specified date. A null string is returned if one of the supported Zodiac signs does not occur on the date. @param date compute the Zodiac sign for the specified Gregorian date. */ QString signNameAtDate(const QDate &date) const; /** Return the string representation of Zodiac sign. @param sign Zodiac sign. */ static QString signName(ZodiacSigns sign); /** Convert the Zodiac sign to a Zodiac symbol. */ static QString signSymbol(ZodiacSigns sign); private: QSharedDataPointer d; }; } #endif