Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qjalalicalendar.cpp
Go to the documentation of this file.
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
// Qt-Security score:significant reason:default
4
5
#
include
"qglobal.h"
6
#
include
"qjalalicalendar_p.h"
7
#
include
"qjalalicalendar_data_p.h"
8
#
include
"qcalendarmath_p.h"
9
#
include
<
QtCore
/
qmath
.
h
>
10
11
QT_BEGIN_NAMESPACE
12
13
using
namespace
QRoundingDown;
14
15
// Constants
16
17
constexpr
qint64
cycleDays
= 1029983;
18
constexpr
int
cycleYears
= 2820;
19
constexpr
double
yearLength
= 365.24219858156028368;
// 365 + 683 / 2820.
20
constexpr
qint64
jalaliEpoch
= 2121446;
// 475/01/01 AP, start of 2820 cycle
21
// This appears to be based on Ahmad Birashk's algorithm.
22
23
// Calendar implementation
24
25
static
inline
int
cycle
(qint64 jdn)
26
{
27
return
qDiv<
cycleDays
>(jdn - jalaliEpoch);
28
}
29
30
static
qint64
cycleStart
(
int
cycleNo)
31
{
32
return
jalaliEpoch + cycleNo * qint64(cycleDays);
33
}
34
35
static
qint64
firstDayOfYear
(
int
year,
int
cycleNo)
36
{
37
using
std
::floor;
38
qint64 firstDOYinEra
39
= QtPrivate::qCheckedFPConversionToInteger<qint64>(floor(year * yearLength));
40
return
jalaliEpoch + cycleNo * qint64(cycleDays) + firstDOYinEra;
41
}
42
43
// Promoted to qint64 to avoid overflows and handle julianDayToDate()'s qint64.
44
static
bool
isLeap
(qint64 year)
45
{
46
// This handles a year < 0 ? year + 1 : year adjusted year, or a value due
47
// to be subjected to the reverse of that to deliver a year.
48
return
qMod<2820>((year + 2346) * 683) < 683;
49
}
50
51
/*!
52
\since 5.14
53
\internal
54
55
\class QJalaliCalendar
56
\inmodule QtCore
57
\brief The QJalaliCalendar class provides Jalali (Hijri Shamsi) calendar
58
system implementation.
59
60
\section1 Solar Hijri Calendar System
61
62
The Solar Hijri calendar, also called the Solar Hejri calendar, Shamsi
63
Hijri calendar or Jalali calendar, is the official calendar of Iran and
64
Afghanistan. It begins on the vernal equinox (Nowruz) as determined by
65
astronomical calculation for the Iran Standard Time meridian
66
(52.5°E or GMT+3.5h). This determination of starting moment is more accurate
67
than the Gregorian calendar for predicting the date of the vernal equinox,
68
because it uses astronomical observations rather than mathematical rules.
69
70
\section2 Calendar Organization
71
72
Each of the twelve months corresponds with a zodiac sign. The first six
73
months have 31 days, the next five have 30 days, and the last month has 29
74
days in usual years but 30 days in leap years. The New Year's Day always
75
falls on the March equinox.
76
77
\section2 Leap Year Rules
78
79
The Solar Hijri calendar produces a five-year leap year interval after about
80
every seven four-year leap year intervals. It usually follows a 33-year
81
cycle with occasional interruptions by single 29-year or 37-year subcycles.
82
The reason for this behavior is that it tracks the observed vernal equinox.
83
By contrast, some less accurate predictive algorithms are in use based
84
on confusion between the average tropical year (365.2422 days, approximated
85
with near 128-year cycles or 2820-year great cycles) and the mean interval
86
between spring equinoxes (365.2424 days, approximated with a near 33-year
87
cycle).
88
89
Source: \l {https://en.wikipedia.org/wiki/Solar_Hijri_calendar}{Wikipedia
90
page on Solar Hijri Calendar}
91
*/
92
93
QString QJalaliCalendar::name()
const
94
{
95
return
QStringLiteral(
"Jalali"
);
96
}
97
98
QStringList QJalaliCalendar::nameList()
99
{
100
return
{
101
QStringLiteral(
"Jalali"
),
102
QStringLiteral(
"Persian"
),
103
};
104
}
105
106
bool
QJalaliCalendar::isLeapYear(
int
year)
const
107
{
108
if
(year == QCalendar::Unspecified)
109
return
false
;
110
if
(year < 0)
111
++year;
112
113
return
isLeap(year);
114
}
115
116
bool
QJalaliCalendar::isLunar()
const
117
{
118
return
false
;
119
}
120
121
bool
QJalaliCalendar::isLuniSolar()
const
122
{
123
return
false
;
124
}
125
126
bool
QJalaliCalendar::isSolar()
const
127
{
128
return
true
;
129
}
130
131
bool
QJalaliCalendar::dateToJulianDay(
int
year,
int
month,
int
day, qint64 *jd)
const
132
{
133
Q_ASSERT(jd);
134
if
(!isDateValid(year, month, day))
135
return
false
;
136
137
const
int
yearOffset = year < 0 ? 474 : 475;
138
auto
yModCycle = qDivMod<cycleYears>(year);
139
if
(yModCycle.remainder < yearOffset) {
140
yModCycle.quotient -= 1;
141
yModCycle.remainder += cycleYears;
142
}
143
yModCycle.remainder -= yearOffset;
144
145
int
dayInYear = day;
146
for
(
int
i = 1; i < month; ++i)
147
dayInYear += daysInMonth(i, year);
148
*jd = firstDayOfYear(yModCycle.remainder, yModCycle.quotient) + dayInYear - 1;
149
return
true
;
150
}
151
152
QCalendar::YearMonthDay QJalaliCalendar::julianDayToDate(qint64 jd)
const
153
{
154
using
Bound = std::numeric_limits<
int
>;
155
constexpr
qint64 maxInt = Bound::max();
156
const
int
c = cycle(jd);
157
int
yearInCycle = qFloor((jd - cycleStart(c)) / yearLength);
158
int
day = jd - firstDayOfYear(yearInCycle, c) + 1;
159
160
// Near the bounds of the supported range this is just outside int's range:
161
qint64 y = yearInCycle + 475 + c * qint64(cycleYears);
162
// Inline daysInYear() to bypass corrections for no year 0 (and its int parameter):
163
if
(day > (isLeap(y) ? 366 : 365)) {
164
++y;
165
day = 1;
166
}
167
// We'll be subtracting 1 if negative, so -maxInt is the lower bound, not Bound::min().
168
if
(y > maxInt || y < -maxInt)
169
return
{};
170
171
int
year =
static_cast
<
int
>(y);
172
if
(year <= 0)
173
year--;
174
int
month;
175
for
(month = 1; month < 12; ++month) {
176
const
int
last = daysInMonth(month, year);
177
if
(day <= last)
178
break
;
179
day -= last;
180
}
181
return
{year, month, day};
182
}
183
184
int
QJalaliCalendar::daysInMonth(
int
month,
int
year)
const
185
{
186
if
(!year || month < 1 || month > 12)
187
return
0;
188
189
if
(month < 7)
190
return
31;
191
192
if
(month < 12 || year == QCalendar::Unspecified || isLeapYear(year))
193
return
30;
194
195
return
29;
196
}
197
198
const
QCalendarLocale *QJalaliCalendar::localeMonthIndexData()
const
199
{
200
return
QtPrivate::Jalali::locale_data;
201
}
202
203
const
char16_t
*QJalaliCalendar::localeMonthData()
const
204
{
205
return
QtPrivate::Jalali::months_data;
206
}
207
208
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
isLeap
static bool isLeap(qint64 year)
Definition
qjalalicalendar.cpp:44
cycleYears
constexpr int cycleYears
Definition
qjalalicalendar.cpp:18
jalaliEpoch
constexpr qint64 jalaliEpoch
Definition
qjalalicalendar.cpp:20
cycle
static int cycle(qint64 jdn)
Definition
qjalalicalendar.cpp:25
yearLength
constexpr double yearLength
Definition
qjalalicalendar.cpp:19
firstDayOfYear
static qint64 firstDayOfYear(int year, int cycleNo)
Definition
qjalalicalendar.cpp:35
cycleStart
static qint64 cycleStart(int cycleNo)
Definition
qjalalicalendar.cpp:30
cycleDays
constexpr qint64 cycleDays
Definition
qjalalicalendar.cpp:17
qtbase
src
corelib
time
qjalalicalendar.cpp
Generated on
for Qt by
1.18.0