• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "holiday_manager.h"
16 #include "i18n_hilog.h"
17 #include <algorithm>
18 #include <climits>
19 #include <ctime>
20 #include <filesystem>
21 #include <format>
22 #include <fstream>
23 #include <iostream>
24 #include <regex>
25 #include "map"
26 #include "utils.h"
27 
28 namespace OHOS {
29 namespace Global {
30 namespace I18n {
31 const char* HolidayManager::ITEM_BEGIN_TAG = "BEGIN:VEVENT";
32 const char* HolidayManager::ITEM_END_TAG = "END:VEVENT";
33 const char* HolidayManager::ITEM_DTSTART_TAG = "DTSTART";
34 const char* HolidayManager::ITEM_DTEND_TAG = "DTEND";
35 const char* HolidayManager::ITEM_SUMMARY_TAG = "SUMMARY";
36 const char* HolidayManager::ITEM_RESOURCES_TAG = "RESOURCES";
37 
HolidayManager(const char * path)38 HolidayManager::HolidayManager(const char* path)
39 {
40     if (path == nullptr) {
41         HILOG_ERROR_I18N("HolidayManager::HolidayManager: parameter path is NULL.");
42         return;
43     }
44     std::string absolutePath = GetAbsoluteFilePath(path);
45     if (absolutePath.empty()) {
46         HILOG_ERROR_I18N("HolidayManager::HolidayManager: holiday file path invalid.");
47         return;
48     }
49     std::vector<HolidayInfoItem> items = ReadHolidayFile(absolutePath);
50     for (size_t i = 0; i < items.size(); i++) {
51         struct tm tmObj = {.tm_mday = items[i].day, .tm_mon = items[i].month, .tm_year = items[i].year};
52         char strDate[10];
53         size_t resCode = strftime(strDate, sizeof(strDate), "%Y%m%d", &tmObj);
54         if (resCode == 0) {
55             HILOG_ERROR_I18N("HolidayManager::HolidayManager: strftime error:%{public}zu.", resCode);
56             return;
57         }
58         std::string startDate(strDate);
59         items[i].year += YEAR_START;
60         items[i].month += MONTH_GREATER_ONE;
61         if (holidayItemMap.find(startDate) != holidayItemMap.end()) {
62             std::vector<HolidayInfoItem> *vetor = &(holidayItemMap.find(startDate)->second);
63             vetor->push_back(items[i]);
64         } else {
65             std::vector<HolidayInfoItem> vetor;
66             vetor.push_back(items[i]);
67             holidayItemMap.insert(std::pair<std::string, std::vector<HolidayInfoItem>>(startDate, vetor));
68         }
69     }
70 }
71 
~HolidayManager()72 HolidayManager::~HolidayManager()
73 {
74 }
75 
SetHolidayData(std::map<std::string,std::vector<HolidayInfoItem>> holidayDataMap)76 void HolidayManager::SetHolidayData(std::map<std::string, std::vector<HolidayInfoItem>> holidayDataMap)
77 {
78     holidayItemMap = holidayDataMap;
79 }
80 
IsHoliday()81 bool HolidayManager::IsHoliday()
82 {
83     time_t timeStamp = time(NULL);
84     struct tm* timObj = localtime(&timeStamp);
85     if (timObj == nullptr) {
86         return false;
87     }
88     int32_t year = timObj->tm_year + YEAR_START;
89     int32_t month = timObj->tm_mon + MONTH_GREATER_ONE;
90     return IsHoliday(year, month, timObj->tm_mday);
91 }
92 
IsHoliday(int32_t year,int32_t month,int32_t day)93 bool HolidayManager::IsHoliday(int32_t year, int32_t month, int32_t day)
94 {
95     std::string startDate = Format(year, month, day);
96     if (holidayItemMap.find(startDate) != holidayItemMap.end()) {
97         std::vector<HolidayInfoItem> list = holidayItemMap.find(startDate)->second;
98         return list.size() > 0;
99     }
100     return false;
101 }
102 
Format(int32_t year,int32_t month,int32_t day)103 std::string HolidayManager::Format(int32_t year, int32_t month, int32_t day)
104 {
105     std::string formated;
106     formated += std::to_string(year);
107     // Numbers less than 10 are one digit
108     formated += month < 10 ? ("0" + std::to_string(month)) : std::to_string(month);
109     // Numbers less than 10 are one digit
110     formated += day < 10 ? ("0" + std::to_string(day)) : std::to_string(day);
111     return formated;
112 }
113 
GetHolidayInfoItemArray()114 std::vector<HolidayInfoItem> HolidayManager::GetHolidayInfoItemArray()
115 {
116     time_t timeStamp = time(NULL);
117     struct tm* timObj = localtime(&timeStamp);
118     if (timObj == nullptr) {
119         std::vector<HolidayInfoItem> emptyList;
120         return emptyList;
121     }
122     int32_t realYear = timObj->tm_year + YEAR_START;
123     return GetHolidayInfoItemArray(realYear);
124 }
125 
GetHolidayInfoItemArray(int32_t year)126 std::vector<HolidayInfoItem> HolidayManager::GetHolidayInfoItemArray(int32_t year)
127 {
128     std::vector<HolidayInfoItem> vetor;
129     std::string formatedYear = std::to_string(year);
130     std::map<std::string, std::vector<HolidayInfoItem>>::iterator iter;
131     for (iter = holidayItemMap.begin(); iter != holidayItemMap.end(); ++iter) {
132         std::string key = iter->first;
133         if (formatedYear == key.substr(0, 4)) { // 4 is the length of full year
134             std::vector<HolidayInfoItem> temp = iter->second;
135             for (size_t i = 0; i < temp.size(); i++) {
136                 vetor.push_back(temp[i]);
137             }
138         }
139     }
140     return vetor;
141 }
142 
ReadHolidayFile(const std::string & path)143 std::vector<HolidayInfoItem> HolidayManager::ReadHolidayFile(const std::string &path)
144 {
145     std::vector<HolidayInfoItem> items;
146     std::ifstream fin;
147     fin.open(path.c_str(), std::ios::in);
148     std::string line;
149     while (getline(fin, line)) {
150         line = Trim(line);
151         if (line.compare(ITEM_BEGIN_TAG) != 0) {
152             continue;
153         }
154         struct HolidayInfoItem holidayItem;
155         while (getline(fin, line)) {
156             line = Trim(line);
157             ParseFileLine(line, &(holidayItem));
158             if (line.compare(ITEM_END_TAG) == 0) {
159                 items.push_back(holidayItem);
160                 break;
161             }
162         }
163     }
164     fin.close();
165     return items;
166 }
167 
ParseFileLine(const std::string & line,HolidayInfoItem * holidayItem)168 void HolidayManager::ParseFileLine(const std::string &line, HolidayInfoItem *holidayItem)
169 {
170     if (holidayItem == nullptr) {
171         return;
172     }
173     std::regex reg("([A-Z]+)[:;](.+)");
174     std::smatch match;
175     bool found = RegexSearchNoExcept(line, match, reg);
176     if (!found) {
177         return;
178     }
179     std::string tag = match[1].str();
180     size_t valuePos = line.find_last_of(":");
181     if (valuePos == std::string::npos || valuePos + 1 >= line.length()) {
182         return;
183     }
184     std::string value = line.substr(valuePos + 1, line.length());
185     if (tag.compare(ITEM_DTSTART_TAG) == 0) {
186         std::string startDate = value.size() >= 8 ? value.substr(0, 8) : ""; // 8 is date formarted string length
187         if (startDate.size() == 8) {
188             struct tm timeObj;
189             strptime(startDate.c_str(), "%Y%m%d", &timeObj);
190             holidayItem->year = timeObj.tm_year;
191             holidayItem->month = timeObj.tm_mon;
192             holidayItem->day = timeObj.tm_mday;
193         }
194     } else if (tag.compare(ITEM_SUMMARY_TAG) == 0) {
195         holidayItem->baseName = value;
196     } else if (tag.compare(ITEM_RESOURCES_TAG) == 0) {
197         size_t displayNamesPos = line.find_last_of('=');
198         if (displayNamesPos == std::string::npos || displayNamesPos + 1 >= line.length()) {
199             return;
200         }
201         std::string displayName = line.substr(displayNamesPos + 1, line.length());
202         size_t languagePos = displayName.find_first_of(":");
203         if (languagePos == std::string::npos || languagePos + 1 >= displayName.length()) {
204             return;
205         }
206         std::string language = displayName.substr(0, languagePos);
207         std::string localName = displayName.substr(languagePos + 1, displayName.length());
208         transform(language.begin(), language.end(), language.begin(), ::tolower);
209         HolidayLocalName localeName = {language, PseudoLocalizationProcessor(localName)};
210         holidayItem->localNames.push_back(localeName);
211     }
212 }
213 
Trim(std::string & str)214 std::string& HolidayManager::Trim(std::string &str)
215 {
216     if (str.empty()) {
217         return str;
218     }
219     size_t endPos = str.find_first_not_of(" \t");
220     if (endPos != std::string::npos) {
221         str.erase(0, endPos);
222     }
223     size_t startPos = str.find_last_not_of("\r\n\t");
224     if (startPos != std::string::npos && startPos + 1 < str.length()) {
225         str.erase(startPos + 1);
226     }
227     return str;
228 }
229 } // namespace I18n
230 } // namespace Global
231 } // namespace OHOS
232