File indexing completed on 2024-06-16 05:03:55
0001 /* 0002 SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "islamiccalendar.h" 0008 0009 #include "icucalendar_p.h" 0010 0011 class IslamicCalendarProviderPrivate : public ICUCalendarPrivate 0012 { 0013 public: 0014 explicit IslamicCalendarProviderPrivate(CalendarSystem::System calendarSystem); 0015 0016 /** 0017 * For formatting, see the documentation of SimpleDateFormat: 0018 * https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1SimpleDateFormat.html#details 0019 */ 0020 QString formattedDateString(const icu::UnicodeString &str) const; 0021 QString formattedDateStringInNativeLanguage(const icu::UnicodeString &str) const; 0022 0023 QCalendar::YearMonthDay fromGregorian(const QDate &_date); 0024 CalendarEvents::CalendarEventsPlugin::SubLabel subLabel(const QDate &date); 0025 0026 private: 0027 // See https://unicode-org.github.io/icu/userguide/locale/#keywords for available keywords 0028 icu::Locale m_arabicLocale; 0029 icu::Locale m_nativeLocale; 0030 }; 0031 0032 IslamicCalendarProviderPrivate::IslamicCalendarProviderPrivate(CalendarSystem::System calendarSystem) 0033 : ICUCalendarPrivate() 0034 { 0035 if (U_FAILURE(m_errorCode)) { 0036 return; // Failed to create m_GregorianCalendar 0037 } 0038 0039 // See https://github.com/unicode-org/cldr/blob/main/common/bcp47/number.xml for available number systems 0040 // See https://cldr.unicode.org/development/development-process/design-proposals/islamic-calendar-types for available Islamic caneldar types 0041 switch (calendarSystem) { 0042 case CalendarSystem::Jalali: { 0043 m_arabicLocale = icu::Locale("ar_IR", 0, 0, "calendar=persian;numbers=arab"); 0044 m_nativeLocale = icu::Locale(QLocale::system().name().toLatin1(), 0, 0, "calendar=persian;"); 0045 break; 0046 } 0047 case CalendarSystem::Islamic: { 0048 m_arabicLocale = icu::Locale("ar_SA", 0, 0, "calendar=islamic;numbers=arab"); 0049 m_nativeLocale = icu::Locale(QLocale::system().name().toLatin1(), 0, 0, "calendar=islamic;"); 0050 break; 0051 } 0052 case CalendarSystem::IslamicCivil: { 0053 m_arabicLocale = icu::Locale("ar_SA", 0, 0, "calendar=islamic-civil;numbers=arab"); 0054 m_nativeLocale = icu::Locale(QLocale::system().name().toLatin1(), 0, 0, "calendar=islamic-civil;"); 0055 break; 0056 } 0057 case CalendarSystem::IslamicUmalqura: { 0058 m_arabicLocale = icu::Locale("ar_SA", 0, 0, "calendar=islamic-umalqura;numbers=arab"); 0059 m_nativeLocale = icu::Locale(QLocale::system().name().toLatin1(), 0, 0, "calendar=islamic-umalqura;"); 0060 break; 0061 } 0062 default: 0063 Q_UNREACHABLE(); 0064 } 0065 0066 m_calendar.reset(icu::Calendar::createInstance(m_arabicLocale, m_errorCode)); 0067 } 0068 0069 QString IslamicCalendarProviderPrivate::formattedDateString(const icu::UnicodeString &str) const 0070 { 0071 UErrorCode errorCode = U_ZERO_ERROR; 0072 icu::UnicodeString dateString; 0073 icu::SimpleDateFormat formatter(str, m_arabicLocale, errorCode); 0074 formatter.setCalendar(*m_calendar); 0075 formatter.format(m_calendar->getTime(errorCode), dateString); 0076 0077 return QString::fromUtf16(dateString.getBuffer(), dateString.length()); 0078 } 0079 0080 QString IslamicCalendarProviderPrivate::formattedDateStringInNativeLanguage(const icu::UnicodeString &str) const 0081 { 0082 UErrorCode errorCode = U_ZERO_ERROR; 0083 icu::UnicodeString dateString; 0084 icu::SimpleDateFormat formatter(str, m_nativeLocale, errorCode); 0085 formatter.setCalendar(*m_calendar); 0086 formatter.format(m_calendar->getTime(errorCode), dateString); 0087 0088 return QString::fromUtf16(dateString.getBuffer(), dateString.length()); 0089 } 0090 0091 QCalendar::YearMonthDay IslamicCalendarProviderPrivate::fromGregorian(const QDate &_date) 0092 { 0093 if (U_FAILURE(m_errorCode) || !_date.isValid() || !setDate(_date)) { 0094 return {}; 0095 } 0096 0097 return date(); 0098 } 0099 0100 CalendarEvents::CalendarEventsPlugin::SubLabel IslamicCalendarProviderPrivate::subLabel(const QDate &date) 0101 { 0102 auto sublabel = CalendarEvents::CalendarEventsPlugin::SubLabel{}; 0103 0104 if (U_FAILURE(m_errorCode) || !date.isValid() || !setDate(date)) { 0105 return sublabel; 0106 } 0107 0108 const bool isLocaleArabicOrPersian = QLocale::system().language() == QLocale::Arabic || QLocale::system().language() == QLocale::Persian; 0109 0110 sublabel.dayLabel = isLocaleArabicOrPersian ? formattedDateString("d") : QString::number(day()); 0111 // From QLocale(QLocale::Arabic).dateFormat() and QLocale(QLocale::Persian).dateFormat() 0112 const QString arabicDateString = formattedDateString("d MMMM yyyy"); 0113 // Translated month names are available in https://github.com/unicode-org/icu/tree/main/icu4c/source/data/locales 0114 sublabel.label = isLocaleArabicOrPersian 0115 ? arabicDateString 0116 : i18ndc("plasma_calendar_alternatecalendar", 0117 "@label %1 Day number %2 Month name in Islamic Calendar %3 Year number %4 Islamic calendar date in Arabic", 0118 "%1 %2, %3 (%4)", 0119 QString::number(day()), 0120 formattedDateStringInNativeLanguage("MMMM"), 0121 QString::number(year()), 0122 arabicDateString); 0123 sublabel.priority = CalendarEvents::CalendarEventsPlugin::SubLabelPriority::Low; 0124 0125 return sublabel; 0126 } 0127 0128 IslamicCalendarProvider::IslamicCalendarProvider(QObject *parent, 0129 CalendarSystem::System calendarSystem, 0130 const QDate &startDate, 0131 const QDate &endDate, 0132 int dateOffset) 0133 : AbstractCalendarProvider(parent, calendarSystem, startDate, endDate, dateOffset) 0134 , d(std::make_unique<IslamicCalendarProviderPrivate>(calendarSystem)) 0135 { 0136 Q_ASSERT(m_calendarSystem == CalendarSystem::Jalali || m_calendarSystem == CalendarSystem::Islamic || m_calendarSystem == CalendarSystem::IslamicCivil 0137 || m_calendarSystem == CalendarSystem::IslamicUmalqura); 0138 } 0139 0140 IslamicCalendarProvider::~IslamicCalendarProvider() 0141 { 0142 } 0143 0144 QCalendar::YearMonthDay IslamicCalendarProvider::fromGregorian(const QDate &date) const 0145 { 0146 return d->fromGregorian(date); 0147 } 0148 0149 CalendarEvents::CalendarEventsPlugin::SubLabel IslamicCalendarProvider::subLabel(const QDate &date) const 0150 { 0151 return d->subLabel(date); 0152 }