1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qglobal.h"
5#include "qislamiccivilcalendar_p.h"
6#include "qcalendarmath_p.h"
7
8QT_BEGIN_NAMESPACE
9
10using namespace QRoundingDown;
11
12/*!
13 \since 5.14
14 \internal
15
16 \class QIslamicCivilCalendar
17 \inmodule QtCore
18 \brief Implements a commonly-used computed version of the Islamic calendar.
19
20 \section1 Civil Islamic Calendar
21
22 QIslamicCivilCalendar implements a tabular version of the Hijri calendar
23 which is known as the Islamic Civil Calendar. It has the same numbering of
24 years and months, but the months are determined by arithmetical rules rather
25 than by observation or astronomical calculations.
26
27 \section2 Calendar Organization
28
29 The civil calendar follows the usual tabular scheme of odd-numbered months
30 and the last month of each leap year being 30 days long, the rest being 29
31 days long. Its determination of leap years follows a 30-year cycle, in each
32 of which the years 2, 5, 7, 10, 13, 16, 18, 21, 24, 26 and 29 are leap
33 years.
34
35 \sa QHijriCalendar, QCalendar
36*/
37
38QString QIslamicCivilCalendar::name() const
39{
40 return QStringLiteral("Islamic Civil");
41}
42
43QStringList QIslamicCivilCalendar::nameList()
44{
45 return {
46 QStringLiteral("Islamic Civil"),
47 QStringLiteral("islamic-civil"), // CLDR name
48 QStringLiteral("islamicc"), // old CLDR name, still (2018) used by Mozilla
49 // Until we have a concrete implementation that knows all the needed ephemerides:
50 QStringLiteral("Islamic"),
51 };
52}
53
54bool QIslamicCivilCalendar::isLeapYear(int year) const
55{
56 if (year == QCalendar::Unspecified)
57 return false;
58 if (year < 0)
59 ++year;
60 return qMod<30>(a: year * 11 + 14) < 11;
61}
62
63// First day of first year (Gregorian 622 CE July 19th) is the base date here:
64constexpr qint64 EpochJd = 1948440;
65// Each 30 years has 11 leap years of 355 days and 19 ordinary years of 354:
66constexpr unsigned ThirtyYears = 11 * 355 + 19 * 354;
67// The first eleven months of the year alternate 30, 29, ..., 29, 30 days in length.
68constexpr unsigned ElevenMonths = 6 * 30 + 5 * 29;
69
70bool QIslamicCivilCalendar::dateToJulianDay(int year, int month, int day, qint64 *jd) const
71{
72 Q_ASSERT(jd);
73 if (!isDateValid(year, month, day))
74 return false;
75
76 *jd = qDiv<30>(a: qint64(ThirtyYears) * (year > 0 ? year - 1 : year) + 14)
77 + qDiv<11>(a: ElevenMonths * (month - 1) + 5)
78 + day + EpochJd - 1;
79 return true;
80}
81
82QCalendar::YearMonthDay QIslamicCivilCalendar::julianDayToDate(qint64 jd) const
83{
84 const auto year30Day = qDivMod<ThirtyYears>(a: 30 * (jd - EpochJd) + 15);
85 // Its remainder changes by 30 per day, except roughly yearly.
86 const auto month11Day = qDivMod<ElevenMonths>(a: 11 * qDiv<30>(a: year30Day.remainder) + 5);
87 // Its remainder changes by 11 per day except roughly monthly.
88 const int month = month11Day.quotient + 1;
89 const int day = qDiv<11>(a: month11Day.remainder) + 1;
90 const int y = year30Day.quotient + 1;
91 return QCalendar::YearMonthDay(y > 0 ? y : y - 1, month, day);
92}
93
94QT_END_NAMESPACE
95

source code of qtbase/src/corelib/time/qislamiccivilcalendar.cpp