19596a2c1Sopenharmony_ci/* 29596a2c1Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 39596a2c1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 49596a2c1Sopenharmony_ci * you may not use this file except in compliance with the License. 59596a2c1Sopenharmony_ci * You may obtain a copy of the License at 69596a2c1Sopenharmony_ci * 79596a2c1Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 89596a2c1Sopenharmony_ci * 99596a2c1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 109596a2c1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 119596a2c1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 129596a2c1Sopenharmony_ci * See the License for the specific language governing permissions and 139596a2c1Sopenharmony_ci * limitations under the License. 149596a2c1Sopenharmony_ci */ 159596a2c1Sopenharmony_ci#include "holiday_manager.h" 169596a2c1Sopenharmony_ci#include "i18n_hilog.h" 179596a2c1Sopenharmony_ci#include <algorithm> 189596a2c1Sopenharmony_ci#include <climits> 199596a2c1Sopenharmony_ci#include <ctime> 209596a2c1Sopenharmony_ci#include <filesystem> 219596a2c1Sopenharmony_ci#include <format> 229596a2c1Sopenharmony_ci#include <fstream> 239596a2c1Sopenharmony_ci#include <iostream> 249596a2c1Sopenharmony_ci#include <regex> 259596a2c1Sopenharmony_ci#include "map" 269596a2c1Sopenharmony_ci#include "utils.h" 279596a2c1Sopenharmony_ci 289596a2c1Sopenharmony_cinamespace OHOS { 299596a2c1Sopenharmony_cinamespace Global { 309596a2c1Sopenharmony_cinamespace I18n { 319596a2c1Sopenharmony_ciconst char* HolidayManager::ITEM_BEGIN_TAG = "BEGIN:VEVENT"; 329596a2c1Sopenharmony_ciconst char* HolidayManager::ITEM_END_TAG = "END:VEVENT"; 339596a2c1Sopenharmony_ciconst char* HolidayManager::ITEM_DTSTART_TAG = "DTSTART"; 349596a2c1Sopenharmony_ciconst char* HolidayManager::ITEM_DTEND_TAG = "DTEND"; 359596a2c1Sopenharmony_ciconst char* HolidayManager::ITEM_SUMMARY_TAG = "SUMMARY"; 369596a2c1Sopenharmony_ciconst char* HolidayManager::ITEM_RESOURCES_TAG = "RESOURCES"; 379596a2c1Sopenharmony_ci 389596a2c1Sopenharmony_ciHolidayManager::HolidayManager(const char* path) 399596a2c1Sopenharmony_ci{ 409596a2c1Sopenharmony_ci if (path == nullptr) { 419596a2c1Sopenharmony_ci HILOG_ERROR_I18N("Failed: parameter path is NULL."); 429596a2c1Sopenharmony_ci return; 439596a2c1Sopenharmony_ci } 449596a2c1Sopenharmony_ci std::string msg = ValidateHolidayFilePath(path); 459596a2c1Sopenharmony_ci if (msg.length() != 0) { 469596a2c1Sopenharmony_ci HILOG_ERROR_I18N("Failed: %{public}s .", msg.c_str()); 479596a2c1Sopenharmony_ci return; 489596a2c1Sopenharmony_ci } 499596a2c1Sopenharmony_ci std::vector<HolidayInfoItem> items = ReadHolidayFile(path); 509596a2c1Sopenharmony_ci for (size_t i = 0; i < items.size(); i++) { 519596a2c1Sopenharmony_ci struct tm tmObj = {.tm_mday = items[i].day, .tm_mon = items[i].month, .tm_year = items[i].year}; 529596a2c1Sopenharmony_ci char strDate[10]; 539596a2c1Sopenharmony_ci size_t resCode = strftime(strDate, sizeof(strDate), "%Y%m%d", &tmObj); 549596a2c1Sopenharmony_ci if (resCode == 0) { 559596a2c1Sopenharmony_ci HILOG_ERROR_I18N("Failed: strftime error:%{public}zu.", resCode); 569596a2c1Sopenharmony_ci return; 579596a2c1Sopenharmony_ci } 589596a2c1Sopenharmony_ci std::string startDate(strDate); 599596a2c1Sopenharmony_ci items[i].year += YEAR_START; 609596a2c1Sopenharmony_ci items[i].month += MONTH_GREATER_ONE; 619596a2c1Sopenharmony_ci if (holidayItemMap.find(startDate) != holidayItemMap.end()) { 629596a2c1Sopenharmony_ci std::vector<HolidayInfoItem> *vetor = &(holidayItemMap.find(startDate)->second); 639596a2c1Sopenharmony_ci vetor->push_back(items[i]); 649596a2c1Sopenharmony_ci } else { 659596a2c1Sopenharmony_ci std::vector<HolidayInfoItem> vetor; 669596a2c1Sopenharmony_ci vetor.push_back(items[i]); 679596a2c1Sopenharmony_ci holidayItemMap.insert(std::pair<std::string, std::vector<HolidayInfoItem>>(startDate, vetor)); 689596a2c1Sopenharmony_ci } 699596a2c1Sopenharmony_ci } 709596a2c1Sopenharmony_ci} 719596a2c1Sopenharmony_ci 729596a2c1Sopenharmony_ciHolidayManager::~HolidayManager() 739596a2c1Sopenharmony_ci{ 749596a2c1Sopenharmony_ci} 759596a2c1Sopenharmony_ci 769596a2c1Sopenharmony_civoid HolidayManager::SetHolidayData(std::map<std::string, std::vector<HolidayInfoItem>> holidayDataMap) 779596a2c1Sopenharmony_ci{ 789596a2c1Sopenharmony_ci holidayItemMap = holidayDataMap; 799596a2c1Sopenharmony_ci} 809596a2c1Sopenharmony_ci 819596a2c1Sopenharmony_cibool HolidayManager::IsHoliday() 829596a2c1Sopenharmony_ci{ 839596a2c1Sopenharmony_ci time_t timeStamp = time(NULL); 849596a2c1Sopenharmony_ci struct tm* timObj = localtime(&timeStamp); 859596a2c1Sopenharmony_ci if (timObj == nullptr) { 869596a2c1Sopenharmony_ci return false; 879596a2c1Sopenharmony_ci } 889596a2c1Sopenharmony_ci int32_t year = timObj->tm_year + YEAR_START; 899596a2c1Sopenharmony_ci int32_t month = timObj->tm_mon + MONTH_GREATER_ONE; 909596a2c1Sopenharmony_ci return IsHoliday(year, month, timObj->tm_mday); 919596a2c1Sopenharmony_ci} 929596a2c1Sopenharmony_ci 939596a2c1Sopenharmony_cibool HolidayManager::IsHoliday(int32_t year, int32_t month, int32_t day) 949596a2c1Sopenharmony_ci{ 959596a2c1Sopenharmony_ci std::string startDate = Format(year, month, day); 969596a2c1Sopenharmony_ci if (holidayItemMap.find(startDate) != holidayItemMap.end()) { 979596a2c1Sopenharmony_ci std::vector<HolidayInfoItem> list = holidayItemMap.find(startDate)->second; 989596a2c1Sopenharmony_ci return list.size() > 0; 999596a2c1Sopenharmony_ci } 1009596a2c1Sopenharmony_ci return false; 1019596a2c1Sopenharmony_ci} 1029596a2c1Sopenharmony_ci 1039596a2c1Sopenharmony_cistd::string HolidayManager::Format(int32_t year, int32_t month, int32_t day) 1049596a2c1Sopenharmony_ci{ 1059596a2c1Sopenharmony_ci std::string formated; 1069596a2c1Sopenharmony_ci formated += std::to_string(year); 1079596a2c1Sopenharmony_ci // Numbers less than 10 are one digit 1089596a2c1Sopenharmony_ci formated += month < 10 ? ("0" + std::to_string(month)) : std::to_string(month); 1099596a2c1Sopenharmony_ci // Numbers less than 10 are one digit 1109596a2c1Sopenharmony_ci formated += day < 10 ? ("0" + std::to_string(day)) : std::to_string(day); 1119596a2c1Sopenharmony_ci return formated; 1129596a2c1Sopenharmony_ci} 1139596a2c1Sopenharmony_ci 1149596a2c1Sopenharmony_cistd::vector<HolidayInfoItem> HolidayManager::GetHolidayInfoItemArray() 1159596a2c1Sopenharmony_ci{ 1169596a2c1Sopenharmony_ci time_t timeStamp = time(NULL); 1179596a2c1Sopenharmony_ci struct tm* timObj = localtime(&timeStamp); 1189596a2c1Sopenharmony_ci if (timObj == nullptr) { 1199596a2c1Sopenharmony_ci std::vector<HolidayInfoItem> emptyList; 1209596a2c1Sopenharmony_ci return emptyList; 1219596a2c1Sopenharmony_ci } 1229596a2c1Sopenharmony_ci int32_t realYear = timObj->tm_year + YEAR_START; 1239596a2c1Sopenharmony_ci return GetHolidayInfoItemArray(realYear); 1249596a2c1Sopenharmony_ci} 1259596a2c1Sopenharmony_ci 1269596a2c1Sopenharmony_cistd::vector<HolidayInfoItem> HolidayManager::GetHolidayInfoItemArray(int32_t year) 1279596a2c1Sopenharmony_ci{ 1289596a2c1Sopenharmony_ci std::vector<HolidayInfoItem> vetor; 1299596a2c1Sopenharmony_ci std::string formatedYear = std::to_string(year); 1309596a2c1Sopenharmony_ci std::map<std::string, std::vector<HolidayInfoItem>>::iterator iter; 1319596a2c1Sopenharmony_ci for (iter = holidayItemMap.begin(); iter != holidayItemMap.end(); ++iter) { 1329596a2c1Sopenharmony_ci std::string key = iter->first; 1339596a2c1Sopenharmony_ci if (formatedYear == key.substr(0, 4)) { // 4 is the length of full year 1349596a2c1Sopenharmony_ci std::vector<HolidayInfoItem> temp = iter->second; 1359596a2c1Sopenharmony_ci for (size_t i = 0; i < temp.size(); i++) { 1369596a2c1Sopenharmony_ci vetor.push_back(temp[i]); 1379596a2c1Sopenharmony_ci } 1389596a2c1Sopenharmony_ci } 1399596a2c1Sopenharmony_ci } 1409596a2c1Sopenharmony_ci return vetor; 1419596a2c1Sopenharmony_ci} 1429596a2c1Sopenharmony_ci 1439596a2c1Sopenharmony_cistd::string HolidayManager::ValidateHolidayFilePath(const char* path) 1449596a2c1Sopenharmony_ci{ 1459596a2c1Sopenharmony_ci char *realpathRes = realpath(path, nullptr); 1469596a2c1Sopenharmony_ci if (realpathRes == NULL) { 1479596a2c1Sopenharmony_ci free(realpathRes); 1489596a2c1Sopenharmony_ci return "the holiday resource file not exists."; 1499596a2c1Sopenharmony_ci } 1509596a2c1Sopenharmony_ci std::ifstream file(path); 1519596a2c1Sopenharmony_ci if (!file.good()) { 1529596a2c1Sopenharmony_ci free(realpathRes); 1539596a2c1Sopenharmony_ci file.close(); 1549596a2c1Sopenharmony_ci return "the holiday resource file can't read."; 1559596a2c1Sopenharmony_ci } 1569596a2c1Sopenharmony_ci file.close(); 1579596a2c1Sopenharmony_ci free(realpathRes); 1589596a2c1Sopenharmony_ci realpathRes = NULL; 1599596a2c1Sopenharmony_ci return ""; 1609596a2c1Sopenharmony_ci} 1619596a2c1Sopenharmony_ci 1629596a2c1Sopenharmony_cistd::vector<HolidayInfoItem> HolidayManager::ReadHolidayFile(const char* path) 1639596a2c1Sopenharmony_ci{ 1649596a2c1Sopenharmony_ci std::vector<HolidayInfoItem> items; 1659596a2c1Sopenharmony_ci if (path == nullptr) { 1669596a2c1Sopenharmony_ci return items; 1679596a2c1Sopenharmony_ci } 1689596a2c1Sopenharmony_ci std::ifstream fin; 1699596a2c1Sopenharmony_ci fin.open(path, std::ios::in); 1709596a2c1Sopenharmony_ci std::string line; 1719596a2c1Sopenharmony_ci while (getline(fin, line)) { 1729596a2c1Sopenharmony_ci line = Trim(line); 1739596a2c1Sopenharmony_ci if (line.compare(ITEM_BEGIN_TAG) != 0) { 1749596a2c1Sopenharmony_ci continue; 1759596a2c1Sopenharmony_ci } 1769596a2c1Sopenharmony_ci struct HolidayInfoItem holidayItem; 1779596a2c1Sopenharmony_ci while (getline(fin, line)) { 1789596a2c1Sopenharmony_ci line = Trim(line); 1799596a2c1Sopenharmony_ci ParseFileLine(line, &(holidayItem)); 1809596a2c1Sopenharmony_ci if (line.compare(ITEM_END_TAG) == 0) { 1819596a2c1Sopenharmony_ci items.push_back(holidayItem); 1829596a2c1Sopenharmony_ci break; 1839596a2c1Sopenharmony_ci } 1849596a2c1Sopenharmony_ci } 1859596a2c1Sopenharmony_ci } 1869596a2c1Sopenharmony_ci fin.close(); 1879596a2c1Sopenharmony_ci return items; 1889596a2c1Sopenharmony_ci} 1899596a2c1Sopenharmony_ci 1909596a2c1Sopenharmony_civoid HolidayManager::ParseFileLine(const std::string &line, HolidayInfoItem *holidayItem) 1919596a2c1Sopenharmony_ci{ 1929596a2c1Sopenharmony_ci if (holidayItem == nullptr) { 1939596a2c1Sopenharmony_ci return; 1949596a2c1Sopenharmony_ci } 1959596a2c1Sopenharmony_ci std::regex reg("([A-Z]+)[:;](.+)"); 1969596a2c1Sopenharmony_ci std::smatch match; 1979596a2c1Sopenharmony_ci bool found = RegexSearchNoExcept(line, match, reg); 1989596a2c1Sopenharmony_ci if (found) { 1999596a2c1Sopenharmony_ci std::string tag = match[1].str(); 2009596a2c1Sopenharmony_ci std::string value = line.substr(line.find_last_of(":") + 1, line.length()); 2019596a2c1Sopenharmony_ci if (tag.compare(ITEM_DTSTART_TAG) == 0) { 2029596a2c1Sopenharmony_ci std::string startDate = value.size() >= 8 ? value.substr(0, 8) : ""; // 8 is date formarted string length 2039596a2c1Sopenharmony_ci if (startDate.size() == 8) { 2049596a2c1Sopenharmony_ci struct tm timeObj; 2059596a2c1Sopenharmony_ci strptime(startDate.c_str(), "%Y%m%d", &timeObj); 2069596a2c1Sopenharmony_ci holidayItem->year = timeObj.tm_year; 2079596a2c1Sopenharmony_ci holidayItem->month = timeObj.tm_mon; 2089596a2c1Sopenharmony_ci holidayItem->day = timeObj.tm_mday; 2099596a2c1Sopenharmony_ci } 2109596a2c1Sopenharmony_ci } else if (tag.compare(ITEM_SUMMARY_TAG) == 0) { 2119596a2c1Sopenharmony_ci holidayItem->baseName = value; 2129596a2c1Sopenharmony_ci } else if (tag.compare(ITEM_RESOURCES_TAG) == 0) { 2139596a2c1Sopenharmony_ci std::string displayName = line.substr(line.find_last_of("=") + 1, line.length()); 2149596a2c1Sopenharmony_ci std::string language = displayName.substr(0, displayName.find_first_of(":")); 2159596a2c1Sopenharmony_ci std::string localName = displayName.substr(displayName.find_first_of(":") + 1, displayName.length()); 2169596a2c1Sopenharmony_ci transform(language.begin(), language.end(), language.begin(), ::tolower); 2179596a2c1Sopenharmony_ci HolidayLocalName localeName = {language, PseudoLocalizationProcessor(localName)}; 2189596a2c1Sopenharmony_ci holidayItem->localNames.push_back(localeName); 2199596a2c1Sopenharmony_ci } 2209596a2c1Sopenharmony_ci } 2219596a2c1Sopenharmony_ci} 2229596a2c1Sopenharmony_ci 2239596a2c1Sopenharmony_cistd::string& HolidayManager::Trim(std::string &str) 2249596a2c1Sopenharmony_ci{ 2259596a2c1Sopenharmony_ci if (str.empty()) { 2269596a2c1Sopenharmony_ci return str; 2279596a2c1Sopenharmony_ci } 2289596a2c1Sopenharmony_ci str.erase(0, str.find_first_not_of(" \t")); 2299596a2c1Sopenharmony_ci str.erase(str.find_last_not_of("\r\n\t") + 1); 2309596a2c1Sopenharmony_ci return str; 2319596a2c1Sopenharmony_ci} 2329596a2c1Sopenharmony_ci} // namespace I18n 2339596a2c1Sopenharmony_ci} // namespace Global 2349596a2c1Sopenharmony_ci} // namespace OHOS 235