diff --git a/CMakeLists.txt b/CMakeLists.txt index 75a88b30..6a5cafe8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,166 +1,167 @@ cmake_minimum_required(VERSION 3.5) set(PIM_VERSION "5.10.40") project(kdepim-addons VERSION ${PIM_VERSION}) if(POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif() set(KF5_VERSION "5.51.0") find_package(ECM ${KF5_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/ ${ECM_MODULE_PATH}) # Do NOT add quote set(KDEPIM_DEV_VERSION alpha) # add an extra space if(DEFINED KDEPIM_DEV_VERSION) set(KDEPIM_DEV_VERSION " ${KDEPIM_DEV_VERSION}") endif() set(KDEPIMADDONS_VERSION_NUMBER ${PIM_VERSION}) set(KDEPIMADDONS_VERSION "${KDEPIMADDONS_VERSION_NUMBER}${KDEPIM_DEV_VERSION}") set(KDEPIMADDONS_LIB_VERSION "${KDEPIMADDONS_VERSION_NUMBER}") set(KDEPIMADDONS_LIB_SOVERSION "5") set(AKONADINOTES_LIB_VERSION "5.10.40") set(QT_REQUIRED_VERSION "5.9.0") include(ECMInstallIcons) include(ECMSetupVersion) include(ECMAddTests) include(GenerateExportHeader) include(ECMGenerateHeaders) include(FeatureSummary) include(CheckFunctionExists) include(ECMGeneratePriFile) include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMAddAppIcon) include(ECMQtDeclareLoggingCategory) option(KDEPIMADDONS_BUILD_EXAMPLES "Build the kdepim-addons example applications." TRUE) option(KDEPIM_ENTERPRISE_BUILD "Enable features specific to the enterprise branch, which are normally disabled. Also, it disables many components not needed for Kontact such as the Kolab client." FALSE) option(KMAIL_EDITORCONVERTERPLUGIN_TEMPLATE_BUILD "Build the kmail editor converter plugin." FALSE) find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED WebEngine WebEngineWidgets Widgets Test) find_package(KF5I18n ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Config ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5DBusAddons ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiNotes ${AKONADINOTES_LIB_VERSION} CONFIG REQUIRED) find_package(KF5XmlGui ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Declarative ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5SyntaxHighlighting ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5IconThemes ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Parts ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Prison ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Holidays ${KF5_VERSION} CONFIG REQUIRED) +find_package(KF5KDELibs4Support ${KF5_VERSION} CONFIG REQUIRED) #for the korganizer hebrew plugin set(MAILCOMMON_LIB_VERSION "5.10.40") set(GRAVATAR_LIB_VERSION "5.10.40") set(PIMCOMMON_LIB_VERSION "5.10.41") set(GRANTLEETHEME_LIB_VERSION "5.10.40") set(CALENDARSUPPORT_LIB_VERSION "5.10.40") set(EVENTVIEW_LIB_VERSION "5.10.40") set(LIBKDEPIM_LIB_VERSION "5.10.40") set(KDEPIM_APPS_LIB_VERSION "5.10.40") set(LIBKLEO_LIB_VERSION "5.10.40") set(AKONADI_LIB_VERSION "5.10.40") set(INCIDENCEEDITOR_LIB_VERSION "5.10.40") set(KTNEF_LIB_VERSION "5.10.40") set(MESSAGELIB_LIB_VERSION "5.10.43") set(AKONADICALENDAR_LIB_VERSION "5.10.40") set(CALENDAR_UTILS_VERSION "5.10.40") set(KPIMTEXTEDIT_LIB_VERSION "5.10.40") set(KIMAP_LIB_VERSION "5.10.40") set(LIBKSIEVE_LIB_VERSION "5.10.40") set(KMAILTRANSPORT_LIB_VERSION "5.10.40") set(AKONADICONTACT_LIB_VERSION "5.10.40") set(IMPORTWIZARD_LIB_VERSION "5.10.40") set(MAILIMPORTER_LIB_VERSION "5.10.40") set(KPIMPKPASS_LIB_VERSION "5.10.40") set(KPIMITINERARY_LIB_VERSION "5.10.40") find_package(KF5CalendarUtils ${CALENDAR_UTILS_VERSION} CONFIG REQUIRED) find_package(KF5WebEngineViewer ${MESSAGELIB_LIB_VERSION} CONFIG REQUIRED) find_package(KF5TemplateParser ${MESSAGELIB_LIB_VERSION} CONFIG REQUIRED) find_package(KF5MailCommon ${MAILCOMMON_LIB_VERSION} CONFIG REQUIRED) find_package(KF5KaddressbookGrantlee ${KDEPIM_APPS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5MessageViewer ${MESSAGELIB_LIB_VERSION} CONFIG REQUIRED) find_package(KF5KaddressbookImportExport ${KDEPIM_APPS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Libkleo ${LIBKLEO_LIB_VERSION} CONFIG REQUIRED) find_package(KF5GrantleeTheme ${GRANTLEETHEME_LIB_VERSION} CONFIG REQUIRED) find_package(KF5PimCommonAkonadi ${PIMCOMMON_LIB_VERSION} CONFIG REQUIRED) find_package(KF5LibkdepimAkonadi ${LIBKDEPIM_LIB_VERSION} CONFIG REQUIRED) find_package(KF5IncidenceEditor ${INCIDENCEEDITOR_LIB_VERSION} CONFIG REQUIRED) find_package(KF5MessageCore ${MESSAGELIB_LIB_VERSION} CONFIG REQUIRED) find_package(KF5MessageComposer ${MESSAGELIB_LIB_VERSION} CONFIG REQUIRED) find_package(KF5MessageList ${MESSAGELIB_LIB_VERSION} CONFIG REQUIRED) find_package(KF5CalendarSupport ${CALENDARSUPPORT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5EventViews ${EVENTVIEW_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Akonadi ${AKONADI_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiCalendar ${AKONADICALENDAR_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Gravatar ${GRAVATAR_LIB_VERSION} CONFIG REQUIRED) find_package(KF5PimTextEdit ${KPIMTEXTEDIT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5IdentityManagement ${KIDENTITYMANAGEMENT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5IMAP ${KIMAP_LIB_VERSION} CONFIG REQUIRED) find_package(KF5LibKSieve ${LIBKSIEVE_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Tnef ${KTNEF_LIB_VERSION} CONFIG REQUIRED) find_package(KF5MailTransportAkonadi ${KMAILTRANSPORT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiContact ${AKONADICONTACT_LIB_VERSION} CONFIG REQUIRED) find_package(KPimImportWizard ${IMPORTWIZARD_LIB_VERSION} CONFIG) find_package(KF5MailImporterAkonadi ${MAILIMPORTER_LIB_VERSION} CONFIG REQUIRED) find_package(KPimPkPass ${KPIMPKPASS_LIB_VERSION} CONFIG REQUIRED) find_package(KPimItinerary ${KPIMITINERARY_LIB_VERSION} CONFIG REQUIRED) if(KDEPIM_ENTERPRISE_BUILD) set(KDEPIM_ENTERPRISE_BUILD true) else() set(KDEPIM_ENTERPRISE_BUILD false) endif() # Extra package find_package(Gpgmepp 1.8.0 CONFIG) set_package_properties(Gpgmepp PROPERTIES DESCRIPTION "GpgME library" URL "http://www.gnupg.org" TYPE REQUIRED) if(KDEPIMADDONS_BUILD_EXAMPLES) add_subdirectory(examples) endif() include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set(QTCREATOR_TEMPLATE_INSTALL_DIR ${KDE_INSTALL_DATADIR}/qtcreator/templates CACHE PATH "Define qtcreator template install path (default is /usr/share/qtcreator/templates)") find_package(Discount "2") set_package_properties("discount" PROPERTIES DESCRIPTION "A library that gives you formatting functions suitable for marking down entire documents or lines of text" URL "http://www.pell.portland.or.us/~orc/Code/discount/" TYPE RECOMMENDED PURPOSE "Generate Markdown file.") add_subdirectory(plugins) add_subdirectory(korganizer) add_subdirectory(kmail) add_subdirectory(kaddressbook) add_subdirectory(sieveeditor) add_subdirectory(kmailtransport) if(KPimImportWizard_FOUND) add_subdirectory(akonadi-import-wizard) endif() install(FILES kdepim-addons.categories kdepim-addons.renamecategories DESTINATION ${KDE_INSTALL_CONFDIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/korganizer/plugins/CMakeLists.txt b/korganizer/plugins/CMakeLists.txt index 9c9a1cc3..36da9066 100644 --- a/korganizer/plugins/CMakeLists.txt +++ b/korganizer/plugins/CMakeLists.txt @@ -1,8 +1,7 @@ add_definitions(-DTRANSLATION_DOMAIN=\"korganizer_plugins\") add_subdirectory(datenums) -#Comment it it depends against kdelibs4support -#add_subdirectory(hebrew) +add_subdirectory(hebrew) #Comment it is just too ugly --Allen #add_subdirectory(lunarphases) add_subdirectory(picoftheday) add_subdirectory(thisdayinhistory) diff --git a/korganizer/plugins/hebrew/CMakeLists.txt b/korganizer/plugins/hebrew/CMakeLists.txt index 67117191..a5b68451 100644 --- a/korganizer/plugins/hebrew/CMakeLists.txt +++ b/korganizer/plugins/hebrew/CMakeLists.txt @@ -1,31 +1,33 @@ ########### next target ############### set(korg_hebrew_PART_SRCS + qcalendarsystem.cpp configdialog.cpp converter.cpp hebrew.cpp holiday.cpp parsha.cpp ) ecm_qt_declare_logging_category(korg_hebrew_PART_SRCS HEADER korganizer_hebrew_debug.h IDENTIFIER KORGANIZER_HEBREWPLUGIN_LOG CATEGORY_NAME org.kde.pim.korganizer_hebrew_plugin) + add_library(korg_hebrew MODULE ${korg_hebrew_PART_SRCS}) target_link_libraries(korg_hebrew KF5::EventViews KF5::I18n KF5::KDELibs4Support ) install(TARGETS korg_hebrew DESTINATION ${KDE_INSTALL_PLUGINDIR} ) ########### install files ############### install(FILES hebrew.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}/korganizer ) diff --git a/korganizer/plugins/hebrew/qcalendarsystem.cpp b/korganizer/plugins/hebrew/qcalendarsystem.cpp new file mode 100644 index 00000000..09d9d5da --- /dev/null +++ b/korganizer/plugins/hebrew/qcalendarsystem.cpp @@ -0,0 +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 + 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 + 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 + 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 + 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/korganizer/plugins/hebrew/qcalendarsystem_p.h b/korganizer/plugins/hebrew/qcalendarsystem_p.h new file mode 100644 index 00000000..450b8e47 --- /dev/null +++ b/korganizer/plugins/hebrew/qcalendarsystem_p.h @@ -0,0 +1,134 @@ +/* + 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. +*/ + +#ifndef QCALENDARSYSTEM_H +#define QCALENDARSYSTEM_H + +#include +#include + +class QCalendarSystemPrivate; + +class QCalendarSystem +{ +public: + enum CalendarSystem { + DefaultCalendar = 0, + GregorianCalendar = 1, + ChineseCalendar = 2, + CopticCalendar = 3, + EthiopicCalendar = 4, + EthiopicAmeteAlemCalendar = 5, + HebrewCalendar = 6, + IndianNationalCalendar = 7, + IslamicCalendar = 8, + IslamicCivilCalendar = 9, + ISO8601Calendar = 10, + JapaneseCalendar = 11, + JulianCalendar = 12, + PersianCalendar = 13, + ROCCalendar = 14, + ThaiCalendar = 15, + LastCalendar = ThaiCalendar + }; + + explicit QCalendarSystem(QCalendarSystem::CalendarSystem calendar = QCalendarSystem::DefaultCalendar); + ~QCalendarSystem(); + + QCalendarSystem &operator=(const QCalendarSystem &other); + + QCalendarSystem::CalendarSystem calendarSystem() const; + + QDate epoch() const; + QDate earliestValidDate() const; + QDate latestValidDate() const; + int maximumMonthsInYear() const; + int maximumDaysInYear() const; + int maximumDaysInMonth() const; + + bool isValid(const QDate &date) const; + bool isValid(int year, int month, int day) const; + bool isValid(int year, int dayOfYear) const; + + QDate date(int year, int month, int day) const; + QDate date(int year, int dayOfYear) const; + + void getDate(const QDate &date, int *year, int *month, int *day) const; + + int year(const QDate &date) const; + int month(const QDate &date) const; + int day(const QDate &date) const; + + int quarter(const QDate &date) const; + int quarter(int year, int month, int day) const; + + int dayOfYear(const QDate &date) const; + int dayOfYear(int year, int month, int day) const; + + int dayOfWeek(const QDate &date) const; + int dayOfWeek(int year, int month, int day) const; + + int weekNumber(const QDate &date, int *yearNum = nullptr) const; + int weekNumber(int year, int month, int day, int *yearNum = nullptr) const; + + int monthsInYear(const QDate &date) const; + int monthsInYear(int year) const; + + int weeksInYear(const QDate &date) const; + int weeksInYear(int year) const; + + int daysInYear(const QDate &date) const; + int daysInYear(int year) const; + + int daysInMonth(const QDate &date) const; + int daysInMonth(int year, int month) const; + + int daysInWeek() const; + + bool isLeapYear(const QDate &date) const; + bool isLeapYear(int year) const; + + QDate addYears(const QDate &date, int years) const; + QDate addMonths(const QDate &date, int months) const; + QDate addDays(const QDate &date, int days) const; + + int yearsDifference(const QDate &fromDate, const QDate &toDate) const; + int monthsDifference(const QDate &fromDate, const QDate &toDate) const; + qint64 daysDifference(const QDate &fromDate, const QDate &toDate) const; + + void dateDifference(const QDate &fromDate, const QDate &toDate, + int *years, int *months, int *days, int *direction) const; + + QDate firstDayOfYear(const QDate &date) const; + QDate firstDayOfYear(int year) const; + QDate lastDayOfYear(const QDate &date) const; + QDate lastDayOfYear(int year) const; + + QDate firstDayOfMonth(const QDate &date) const; + QDate firstDayOfMonth(int year, int month) const; + QDate lastDayOfMonth(const QDate &date) const; + QDate lastDayOfMonth(int year, int month) const; + +private: + QSharedDataPointer d; +}; + +#endif // QCALENDARSYSTEM_H