File indexing completed on 2024-04-28 08:32:04

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "holidaycache_p.h"
0008 
0009 #include <kholidays_version.h>
0010 #include <KHolidays/HolidayRegion>
0011 
0012 #include <QDate>
0013 #include <QHash>
0014 
0015 using namespace KOpeningHours;
0016 
0017 KHolidays::HolidayRegion HolidayCache::resolveRegion(QStringView region)
0018 {
0019     static QHash<QString, QString> s_holidayRegionCache;
0020 
0021     const auto idx = region.indexOf(QLatin1Char('_')); // compatibility with KHolidays region codes
0022     if (idx > 0) {
0023         region = region.left(idx);
0024     }
0025 
0026     const auto loc = region.toString();
0027 
0028     const auto it = s_holidayRegionCache.constFind(loc);
0029     if (it != s_holidayRegionCache.constEnd()) {
0030         return KHolidays::HolidayRegion(it.value());
0031     }
0032 
0033     const auto code = KHolidays::HolidayRegion::defaultRegionCode(loc);
0034     s_holidayRegionCache.insert(loc, code);
0035     return KHolidays::HolidayRegion(code);
0036 }
0037 
0038 struct HolidayCacheEntry {
0039     QDate begin;
0040     QDate end;
0041     KHolidays::Holiday::List holidays;
0042 };
0043 
0044 static KHolidays::Holiday nextHoliday(const KHolidays::Holiday::List &holidays, QDate date)
0045 {
0046     for (const auto &h : holidays) {
0047         if (h.observedStartDate() >= date)
0048             return h;
0049     }
0050     return {};
0051 }
0052 
0053 KHolidays::Holiday HolidayCache::nextHoliday(const KHolidays::HolidayRegion &region, QDate date)
0054 {
0055     static QHash<QString, HolidayCacheEntry> s_holidayCache;
0056 
0057     if (!region.isValid()) {
0058         return {};
0059     }
0060 
0061     const auto it = s_holidayCache.constFind(region.regionCode());
0062     if (it != s_holidayCache.constEnd() && date >= it.value().begin && date.addYears(1) < it.value().end) {
0063         return nextHoliday(it.value().holidays, date);
0064     }
0065 
0066     HolidayCacheEntry entry;
0067     entry.begin = date.addDays(-7);
0068     entry.end = date.addYears(2).addDays(7);
0069     if (it != s_holidayCache.constEnd()) {
0070         entry.begin = std::min(it.value().begin, entry.begin);
0071         entry.end = std::max(it.value().end, entry.end);
0072     }
0073 #if KHOLIDAYS_VERSION >= QT_VERSION_CHECK(5, 95, 0)
0074     entry.holidays = region.rawHolidays(entry.begin, entry.end);
0075 #else
0076     entry.holidays = region.holidays(entry.begin, entry.end);
0077 #endif
0078     entry.holidays.erase(std::remove_if(entry.holidays.begin(), entry.holidays.end(), [](const auto &h) {
0079         return h.dayType() != KHolidays::Holiday::NonWorkday;
0080     }), entry.holidays.end());
0081     std::sort(entry.holidays.begin(), entry.holidays.end(), [](const auto &lhs, const auto &rhs) {
0082         return lhs.observedStartDate() < rhs.observedStartDate();
0083     });
0084     s_holidayCache.insert(region.regionCode(), entry);
0085     return nextHoliday(entry.holidays, date);
0086 }