1 /*
2  * DQt - D bindings for the Qt Toolkit
3  *
4  * GNU Lesser General Public License Usage
5  * This file may be used under the terms of the GNU Lesser
6  * General Public License version 3 as published by the Free Software
7  * Foundation and appearing in the file LICENSE.LGPL3 included in the
8  * packaging of this file. Please review the following information to
9  * ensure the GNU Lesser General Public License version 3 requirements
10  * will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
11  */
12 module qt.core.calendar;
13 extern(C++):
14 
15 import qt.config;
16 import qt.core.datetime;
17 import qt.core.locale;
18 import qt.core.metamacros;
19 import qt.core.string;
20 import qt.core.stringlist;
21 import qt.core.stringview;
22 import qt.helpers;
23 
24 /* Suggested enum names for other calendars known to CLDR (v33.1)
25 
26    Not yet implemented - see QCalendar::System - contributions welcome:
27 
28    * Buddhist -- Thai Buddhist, to be specific
29    * Chinese
30    * Coptic
31    * Dangi -- Korean
32    * Ethiopic (Amete Mihret - epoch approx. 8 C.E.)
33    * EthiopicAmeteAlem (Amete Alem - epoch approx. 5493 B.C.E; data from
34      type="ethiopic-amete-alem", an alias for type="ethioaa")
35    * Hebrew
36    * Indian -- National
37    * Islamic -- Based on astronomical observations, not predictions, so hard to
38      implement. CLDR's data for type="islamic" apply, unless overridden, to the
39      other Islamic calendar variants, i.e. IslamicCivil, above, and the three
40      following. See QHijriCalendar, a common base to provide that data.
41    * IslamicTabular -- tabular, astronomical epoch (same as IslamicCivil, except
42      for epoch), CLDR type="islamic-tbla"
43    * Saudi -- Saudi Arabia, sighting; CLDR type="islamic-rgsa"
44    * UmmAlQura -- Umm al-Qura, Saudi Arabia, calculated; CLDR type="islamic-umalqura"
45    * Iso8601 -- as Gregorian, but treating ISO 8601 weeks as "months"
46    * Japanese -- Imperial calendar
47    * Minguo -- Republic of China, Taiwan; CLDR type="roc"
48 
49    See:
50    http://www.unicode.org/repos/cldr/tags/latest/common/bcp47/calendar.xml
51 
52    These can potentially be supported, as features, using CLDR's data; any
53    others shall need hand-crafted localization data; it would probably be best
54    to do that by contributing data for them to CLDR.
55 */
56 
57 
58 extern(C++, class) struct QCalendarBackend;
59 
60 /// Binding for C++ class [QCalendar](https://doc.qt.io/qt-6/qcalendar.html).
61 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QCalendar
62 {
63     mixin(Q_GADGET);
64 public:
65     // (Extra parentheses to suppress bogus reading of min() as a macro.)
66     enum int Unspecified = int.min;
67     // Workaround for https://issues.dlang.org/show_bug.cgi?id=20701
68     extern(C++, struct) struct YearMonthDay
69     {
70         /+ YearMonthDay() = default; +/
71         this(int y, int m = 1, int d = 1)
72         {
73             this.year = y;
74             this.month = m;
75             this.day = d;
76         }
77 
78         bool isValid() const
79         { return month != Unspecified && day != Unspecified; }
80         // (The first year supported by QDate has year == Unspecified.)
81 
82         int year = Unspecified;
83         int month = Unspecified;
84         int day = Unspecified;
85     }
86     // Feature (\w+)calendar uses CLDR type="\1" data, except as noted in type="..." comments below
87     enum /+ class +/ System
88     {
89         Gregorian, // CLDR: type = "gregory", alias = "gregorian"
90 /+ #ifndef QT_BOOTSTRAPPED +/
91         Julian = 8,
92         Milankovic = 9,
93 /+ #endif // These are Roman-based, so share Gregorian's CLDR data
94 
95         // Feature-controlled calendars:
96 #if QT_CONFIG(jalalicalendar) +/ // type="persian"
97         Jalali = 10,
98 /+ #endif
99 #if QT_CONFIG(islamiccivilcalendar) +/ // type="islamic-civil", uses data from type="islamic"
100         IslamicCivil = 11,
101         // tabular, civil epoch
102         // 30 year cycle, leap on 2, 5, 7, 10, 13, 16, 18, 21, 24, 26 and 29
103         // (Other variants: 2, 5, 8, (10|11), 13, 16, 19, 21, 24, 27 and 29.)
104 /+ #endif +/
105 
106         Last = 11, // Highest number of any above
107         User = -1
108     }
109     // New entries must be added to the \enum doc in qcalendar.cpp and
110     // handled in QCalendarBackend::fromEnum()
111     /+ Q_ENUM(System) +/
112     extern(C++, class) struct SystemId
113     {
114     private:
115         size_t id = ~size_t(0);
116         /+ friend class QCalendarBackend; +/
117         bool isInEnum() const { return id <= size_t(QCalendar.System.Last); }
118         /+ explicit +/this(QCalendar.System e)
119         {
120             this.id = size_t(e);
121         }
122         /+ explicit +/this(size_t i)
123         {
124             this.id = i;
125         }
126 
127     public:
128         @disable this();
129         /+this()
130         {
131             this.id = UnresolvedMergeConflict!(q{~size_t(0)},q{~size_t(0)});
132         }+/
133         size_t index() const/+ noexcept+/ { return id; }
134         bool isValid() const/+ noexcept+/ { return (~id) != 0; }
135     }
136 
137     @disable this();
138     /+ explicit +/pragma(mangle, defaultConstructorMangling(__traits(identifier, typeof(this))))
139     ref typeof(this) rawConstructor();
140     static typeof(this) create()
141     {
142         typeof(this) r = typeof(this).init;
143         r.rawConstructor();
144         return r;
145     }
146  // Gregorian, optimised
147     /+ explicit +/this(System system);
148     // ### Qt 7: remove
149     /+ explicit +/this(QLatin1String name);
150     // ### Qt 7: use QAnyStringView
151     /+ explicit +/this(QStringView name);
152     /+ explicit +/this(SystemId id);
153 
154     // QCalendar is a trivially copyable value type.
155     bool isValid() const { return d_ptr !is null; }
156 
157     // Date queries:
158     int daysInMonth(int month, int year = Unspecified) const;
159     int daysInYear(int year) const;
160     int monthsInYear(int year) const;
161     bool isDateValid(int year, int month, int day) const;
162 
163     // Leap years:
164     bool isLeapYear(int year) const;
165 
166     // Properties of the calendar:
167     bool isGregorian() const;
168     bool isLunar() const;
169     bool isLuniSolar() const;
170     bool isSolar() const;
171     bool isProleptic() const;
172     bool hasYearZero() const;
173     int maximumDaysInMonth() const;
174     int minimumDaysInMonth() const;
175     int maximumMonthsInYear() const;
176     QString name() const;
177 
178     // QDate conversions:
179     QDate dateFromParts(int year, int month, int day) const;
180     QDate dateFromParts(ref const(YearMonthDay) parts) const;
181     YearMonthDay partsFromDate(QDate date) const;
182     int dayOfWeek(QDate date) const;
183 
184     // Month and week-day names (as in QLocale):
185     QString monthName(ref const(QLocale) locale, int month, int year = Unspecified,
186                           QLocale.FormatType format=QLocale.FormatType.LongFormat) const;
187     QString standaloneMonthName(ref const(QLocale) locale, int month, int year = Unspecified,
188                                     QLocale.FormatType format = QLocale.FormatType.LongFormat) const;
189     QString weekDayName(ref const(QLocale) locale, int day,
190                             QLocale.FormatType format = QLocale.FormatType.LongFormat) const;
191     QString standaloneWeekDayName(ref const(QLocale) locale, int day,
192                                       QLocale.FormatType format=QLocale.FormatType.LongFormat) const;
193 
194     // Formatting of date-times:
195     QString dateTimeToString(QStringView format, ref const(QDateTime) datetime,
196                                  QDate dateOnly, QTime timeOnly,
197                                  ref const(QLocale) locale) const;
198 
199     // What's available ?
200     static QStringList availableCalendars();
201 private:
202     // Always supplied by QCalendarBackend and expected to be a singleton
203     // Note that the calendar registry destroys all backends when it is itself
204     // destroyed. The code should check if the registry is destroyed before
205     // dereferencing this pointer.
206     const(QCalendarBackend)* d_ptr;
207     mixin(CREATE_CONVENIENCE_WRAPPERS);
208 }
209