• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 <sstream>
16 #include <iomanip>
17 #include "calendar_log.h"
18 #include "cj_native_util.h"
19 #include <ctime>
20 #include <numeric>
21 
22 namespace OHOS::CalendarApi::Native {
23 const int MIN_DAY_OF_WEEK = 1;
24 const int MAX_DAY_OF_WEEK = 7;
25 const int MIN_MONTH_OF_YEAR = -12;
26 const int MAX_MONTH_OF_YEAR = 12;
27 const int MIN_DAY_OF_MONTH = -31;
28 const int MAX_DAY_OF_MONTH = 31;
29 const int MIN_DAY_OF_YEAR = -366;
30 const int MAX_DAY_OF_YEAR = 366;
31 const int MIN_WEEK_OF_YEAR = -53;
32 const int MAX_WEEK_OF_YEAR = 53;
33 const int MIN_WEEK_OF_MONTH = -5;
34 const int MAX_WEEK_OF_MONTH = 5;
DumpCalendarAccount(const CalendarAccount & account)35 void DumpCalendarAccount(const CalendarAccount &account)
36 {
37     LOG_DEBUG("account.name:%{private}s", account.name.c_str());
38     LOG_DEBUG("account.type:%{private}s", account.type.c_str());
39     LOG_DEBUG("account.displayName:%{private}s", account.displayName.value_or("").c_str());
40 }
41 
DumpEvent(const Event & event)42 void DumpEvent(const Event &event)
43 {
44     LOG_DEBUG("id       :%{private}d", event.id.value_or(-1));
45     LOG_DEBUG("type     :%{private}d", event.type);
46     LOG_DEBUG("title    :%{private}s", event.title.value_or("[null]").c_str());
47     if (event.location) {
48         auto location = event.location.value();
49         LOG_DEBUG("location.location  :%{private}s", location.location.value_or("[null]").c_str());
50         LOG_DEBUG("location.longitude :%{private}lf", location.longitude.value_or(-1));
51         LOG_DEBUG("location.latitude  :%{private}lf", location.latitude.value_or(-1));
52     } else {
53         LOG_DEBUG("location [null]");
54     }
55     if (event.service) {
56         auto service = event.service.value();
57         LOG_DEBUG("service.type  :%{private}s", service.type.c_str());
58         LOG_DEBUG("service.description :%{private}s", service.description.value_or("[null]").c_str());
59         LOG_DEBUG("service.uri  :%{private}s", service.uri.c_str());
60     } else {
61         LOG_DEBUG("service [null]");
62     }
63     if (event.recurrenceRule.has_value()) {
64         LOG_DEBUG("recurrenceRule.recurrenceFrequency: %{private}d", event.recurrenceRule.value().recurrenceFrequency);
65     }
66     LOG_DEBUG("startTime    :%{private}s", std::to_string(event.startTime).c_str());
67     LOG_DEBUG("endTime      :%{private}s", std::to_string(event.endTime).c_str());
68     LOG_DEBUG("isAllDay :%{private}d", event.isAllDay.value_or(0));
69 
70     for (const auto &attendee : event.attendees) {
71         LOG_DEBUG("attendee.name   :%{private}s", attendee.name.c_str());
72         LOG_DEBUG("attendee.email  :%{private}s", attendee.email.c_str());
73     }
74 
75     LOG_DEBUG("timeZone     :%{private}s", event.timeZone.value_or("[null]").c_str());
76     LOG_DEBUG("description  :%{private}s", event.description.value_or("[null]").c_str());
77 }
78 
BuildEventLocation(DataShare::DataShareValuesBucket & valuesBucket,const Event & event)79 void BuildEventLocation(DataShare::DataShareValuesBucket &valuesBucket, const Event &event)
80 {
81     if (!event.location) {
82         return;
83     }
84     auto location = event.location.value();
85     if (location.location) {
86         valuesBucket.Put("eventLocation", location.location.value());
87     } else {
88         valuesBucket.Put("eventLocation", "");
89     }
90     if (location.longitude) {
91         // longitude is string in db
92         valuesBucket.Put("location_longitude", std::to_string(location.longitude.value()));
93     } else {
94         valuesBucket.Put("location_longitude", "");
95     }
96     if (location.latitude) {
97         // latitude is string in db
98         valuesBucket.Put("location_latitude", std::to_string(location.latitude.value()));
99     } else {
100         valuesBucket.Put("location_latitude", "");
101     }
102 }
103 
BuildEventService(DataShare::DataShareValuesBucket & valuesBucket,const Event & event)104 void BuildEventService(DataShare::DataShareValuesBucket &valuesBucket, const Event &event)
105 {
106     if (!event.service.has_value()) {
107         LOG_INFO("BuildEventService event.service has no value ");
108         return;
109     }
110     const auto service = event.service.value();
111     if (service.description) {
112         valuesBucket.Put("service_description", service.description.value());
113     } else {
114         valuesBucket.Put("service_description", "");
115     }
116     valuesBucket.Put("service_type", service.type);
117     valuesBucket.Put("service_cp_bz_uri", service.uri);
118 }
119 
GetUTCTime(const int64_t & timeValue)120 std::string GetUTCTime(const int64_t &timeValue)
121 {
122     const int monOffset = 1;
123     const int strLen = 2;
124     const int baseYear = 1900;
125     time_t expire = timeValue / 1000;
126     std::tm expireTime = {0};
127 #ifdef WINDOWS_PLATFORM
128     if (gmtime_s(&expireTime, &expire)) {
129 #else
130     if (gmtime_r(&expire, &expireTime) == nullptr) {
131 #endif
132         return {};
133     }
134     std::stringstream out;
135     out << (expireTime.tm_year + baseYear);
136     out << std::setfill('0') << std::setw(strLen) << expireTime.tm_mon + monOffset;
137     out << std::setfill('0') << std::setw(strLen) << expireTime.tm_mday;
138     out << "T";
139     out << std::setfill('0') << std::setw(strLen) << expireTime.tm_hour;
140     out << std::setfill('0') << std::setw(strLen) << expireTime.tm_min;
141     out << std::setfill('0') << std::setw(strLen) << expireTime.tm_sec;
142     out << "Z";
143 
144     return out.str();
145 }
146 
147 std::string GetUTCTimes(const std::vector<int64_t> &timeValues)
148 {
149     std::stringstream out;
150     if (timeValues.size() == 0) {
151         return out.str();
152     }
153 
154     const auto timeLen = timeValues.size() - 1;
155     if (timeLen == 0) {
156         out << GetUTCTime(timeValues[0]);
157         return out.str();
158     }
159 
160     for (unsigned int i = 0; i <= timeLen; i++) {
161         out << GetUTCTime(timeValues[i]);
162         if (i != timeLen) {
163             out << ",";
164         }
165     }
166 
167     return out.str();
168 }
169 
170 std::string GetRule(const Event &event)
171 {
172     const time_t now = event.startTime / 1000;
173     const std::tm *time = std::localtime(&now);
174     std::string rrule;
175     RecurrenceType recurrenceFrequency = event.recurrenceRule.value().recurrenceFrequency;
176     if (recurrenceFrequency == DAILY) {
177         rrule = "FREQ=DAILY" + GetEventRRule(event) + ";WKST=SU";
178     } else if (recurrenceFrequency == WEEKLY) {
179         rrule = "FREQ=WEEKLY" + GetEventRRule(event) + ";WKST=SU;BYDAY=";
180         if (time != nullptr) {
181             rrule += GetWeeklyRule(event, *time);
182         }
183     } else if (recurrenceFrequency == MONTHLY) {
184         rrule = "FREQ=MONTHLY" + GetEventRRule(event) + ";WKST=SU";
185         if (time != nullptr) {
186             rrule += GetMonthlyRule(event, *time);
187         }
188     } else if (recurrenceFrequency == YEARLY) {
189         rrule = "FREQ=YEARLY" + GetEventRRule(event) + ";WKST=SU";
190         if (time != nullptr) {
191             rrule += GetYearlyRule(event, *time);
192         }
193     } else if (recurrenceFrequency == NORULE) {
194         LOG_INFO(" recurrenceFrequency == NORULE");
195         rrule = "";
196     }
197 
198     return rrule;
199 }
200 
201 std::string GetEventRRule(const Event &event)
202 {
203     auto recurrenceRule = event.recurrenceRule.value();
204     std::string rrule;
205     if (recurrenceRule.expire.has_value() && recurrenceRule.expire.value() > 0) {
206         rrule += ";UNTIL=" + GetUTCTime(event.recurrenceRule.value().expire.value());
207     }
208     if (recurrenceRule.count.has_value() && recurrenceRule.count.value() > 0) {
209         rrule += ";COUNT=" + std::to_string(recurrenceRule.count.value());
210     }
211     if (recurrenceRule.interval.has_value() && recurrenceRule.interval.value() > 0) {
212         rrule += ";INTERVAL=" + std::to_string(recurrenceRule.interval.value());
213     }
214     return rrule;
215 }
216 
217 std::string GetWeeklyRule(const Event &event, const std::tm &time)
218 {
219     std::string rrule;
220     bool isHasSetData = false;
221     auto rRuleValue = event.recurrenceRule.value();
222     const std::vector<string> weekList = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
223     if (rRuleValue.daysOfWeek.has_value()) {
224         isHasSetData = true;
225         auto daysOfWeekList = rRuleValue.daysOfWeek.value();
226         rrule = GetDaysOfWeekRule(MIN_DAY_OF_WEEK, MAX_DAY_OF_WEEK, daysOfWeekList);
227     }
228     if (isHasSetData == false) {
229         if (time.tm_wday < MAX_DAY_OF_WEEK) {
230             rrule = weekList[time.tm_wday];
231         }
232     }
233     return rrule;
234 }
235 
236 std::string GetMonthlyRule(const Event &event, const std::tm &time)
237 {
238     bool isHasSetData = false;
239     std::string rrule;
240     auto rruleValue = event.recurrenceRule.value();
241     if (rruleValue.daysOfWeek.has_value() && rruleValue.weeksOfMonth.has_value()) {
242         isHasSetData = true;
243         rrule += ";BYDAY=";
244         rrule += GetDaysOfWeekMonthRule(rruleValue.daysOfWeek.value(), rruleValue.weeksOfMonth.value());
245     }
246 
247     if (rruleValue.daysOfMonth.has_value()) {
248         isHasSetData = true;
249         rrule += ";BYMONTHDAY=";
250         auto daysOfMonthList = rruleValue.daysOfMonth.value();
251         rrule += GetRRuleSerial(MIN_DAY_OF_MONTH, MAX_DAY_OF_MONTH, daysOfMonthList);
252     }
253     if (isHasSetData == false) {
254         rrule += ";BYMONTHDAY=";
255         rrule += std::to_string(time.tm_mday);
256     }
257     return rrule;
258 }
259 
260 std::string GetYearlyRule(const Event &event, const std::tm &time)
261 {
262     const int monOffset = 1;
263     bool isHasSetData = false;
264     std::string rrule;
265     auto rruleValue = event.recurrenceRule.value();
266     if (rruleValue.daysOfYear.has_value()) {
267         isHasSetData = true;
268         std::string days = GetRRuleSerial(MIN_DAY_OF_YEAR, MAX_DAY_OF_YEAR, rruleValue.daysOfYear.value());
269         rrule = ";BYYEARDAY=" + days;
270     }
271     if (rruleValue.weeksOfYear.has_value() && rruleValue.daysOfWeek.has_value()) {
272         isHasSetData = true;
273         auto weekOfYearList = rruleValue.weeksOfYear.value();
274         std::string weeks = GetRRuleSerial(MIN_WEEK_OF_YEAR, MAX_WEEK_OF_YEAR, weekOfYearList);
275         auto daysOfWeekList = rruleValue.daysOfWeek.value();
276         std::string weekdays = GetDaysOfWeekRule(MIN_DAY_OF_WEEK, MAX_DAY_OF_WEEK, daysOfWeekList);
277         rrule = ";BYWEEKNO=" + weeks + ";BYDAY=" + weekdays;
278     }
279     if (rruleValue.monthsOfYear.has_value() && rruleValue.daysOfMonth.has_value()) {
280         isHasSetData = true;
281         auto daysOfMonthList = rruleValue.daysOfMonth.value();
282         auto monthsOfYearList = rruleValue.monthsOfYear.value();
283         std::string days = GetRRuleSerial(MIN_DAY_OF_MONTH, MAX_DAY_OF_MONTH, daysOfMonthList);
284         std::string months = GetRRuleSerial(MIN_MONTH_OF_YEAR, MAX_MONTH_OF_YEAR, monthsOfYearList);
285         rrule = ";BYMONTHDAY=" + days + ";BYMONTH=" + months;
286     }
287     if (rruleValue.monthsOfYear.has_value() && rruleValue.weeksOfMonth.has_value() &&
288         rruleValue.daysOfWeek.has_value()) {
289         isHasSetData = true;
290         auto monthsOfYearList = rruleValue.monthsOfYear.value();
291         auto weeksOfMonthList = rruleValue.weeksOfMonth.value();
292         auto daysOfWeekList = rruleValue.daysOfWeek.value();
293         std::string months = GetRRuleSerial(MIN_MONTH_OF_YEAR, MAX_MONTH_OF_YEAR, monthsOfYearList);
294         std::string daysOfWeekMonth = GetDaysOfWeekMonthRule(daysOfWeekList, weeksOfMonthList);
295         rrule = ";BYDAY=" + daysOfWeekMonth + ";BYMONTH=" + months;
296     }
297     if (isHasSetData == false) {
298         rrule += ";BYMONTHDAY=";
299         rrule += std::to_string(time.tm_mday);
300         rrule += ";BYMONTH=";
301         rrule += std::to_string(time.tm_mon + monOffset);
302     }
303     return rrule;
304 }
305 
306 std::string GetDaysOfWeekRule(int minValue, int maxValue, const std::vector<int64_t> &daysOfWeekList)
307 {
308     std::string rrule;
309     const std::vector<string> weekDayList = {"MO", "TU", "WE", "TH", "FR", "SA", "SU"};
310     for (const auto &dayOfWeek : daysOfWeekList) {
311         if (dayOfWeek <= maxValue && dayOfWeek >= minValue) {
312             if (&dayOfWeek == &daysOfWeekList.back()) {
313                 rrule = rrule + weekDayList[dayOfWeek - 1];
314                 break;
315             }
316             rrule = rrule + weekDayList[dayOfWeek - 1] + ",";
317         }
318     }
319     return rrule;
320 }
321 
322 std::string GetDaysOfWeekMonthRule(
323     const std::vector<int64_t> &daysOfWeekList, const std::vector<int64_t> &weeksOfMonthList)
324 {
325     std::string rrule;
326     const std::vector<string> weekDayList = {"MO", "TU", "WE", "TH", "FR", "SA", "SU"};
327     auto daysLen = daysOfWeekList.size();
328     for (size_t i = 0; i < daysLen; i++) {
329         if (daysOfWeekList[i] >= MIN_DAY_OF_WEEK && daysOfWeekList[i] <= MAX_DAY_OF_WEEK &&
330             weeksOfMonthList[i] >= MIN_WEEK_OF_MONTH && weeksOfMonthList[i] <= MAX_WEEK_OF_MONTH) {
331             if (i == daysLen - 1) {
332                 rrule = rrule + std::to_string(weeksOfMonthList[i]) + weekDayList[daysOfWeekList[i] - 1];
333                 break;
334             } else {
335                 rrule = rrule + std::to_string(weeksOfMonthList[i]) + weekDayList[daysOfWeekList[i] - 1] + ",";
336             }
337         }
338     }
339     return rrule;
340 }
341 
342 std::string GetRRuleSerial(int minValue, int maxValue, const std::vector<int64_t> &serialList)
343 {
344     std::string rrule;
345     for (const auto &serial : serialList) {
346         if (serial >= minValue && serial <= maxValue) {
347             if (&serial == &serialList.back()) {
348                 rrule = rrule + std::to_string(serial);
349                 break;
350             }
351             rrule = rrule + std::to_string(serial) + ",";
352         }
353     }
354     return rrule;
355 }
356 
357 void BuildEventRecurrenceRule(DataShare::DataShareValuesBucket &valuesBucket, const Event &event)
358 {
359     if (!event.recurrenceRule.has_value()) {
360         return;
361     }
362 
363     std::string rrule = GetRule(event);
364     valuesBucket.Put("rrule", rrule);
365 
366     if (event.recurrenceRule.value().excludedDates.has_value()) {
367         const auto excludedDateStr = GetUTCTimes(event.recurrenceRule.value().excludedDates.value());
368         valuesBucket.Put("exdate", excludedDateStr);
369     }
370 }
371 
372 DataShare::DataShareValuesBucket BuildValueEvent(const Event &event, int calendarId, int channelId, bool isUpdate)
373 {
374     DataShare::DataShareValuesBucket valuesBucket;
375     valuesBucket.Put("calendar_id", calendarId);
376     if (!isUpdate) {
377         LOG_DEBUG("title %{private}s", event.title.value_or("").c_str());
378         valuesBucket.Put("title", event.title.value_or(""));
379     } else {
380         if (event.title) {
381             valuesBucket.Put("title", event.title.value());
382         }
383     }
384     valuesBucket.Put("important_event_type", event.type);
385     valuesBucket.Put("dtstart", event.startTime);
386     valuesBucket.Put("dtend", event.endTime);
387 
388     BuildEventLocation(valuesBucket, event);
389     BuildEventService(valuesBucket, event);
390     BuildEventRecurrenceRule(valuesBucket, event);
391 
392     LOG_DEBUG("description %{private}s", event.description.value_or("").c_str());
393 
394     if (event.description.has_value()) {
395         valuesBucket.Put("description", event.description.value());
396     }
397     if (event.timeZone.has_value()) {
398         valuesBucket.Put("eventTimezone", event.timeZone.value());
399     }
400     if (event.isAllDay.has_value() && event.isAllDay.value() != false) {
401         valuesBucket.Put("allDay", event.isAllDay.value());
402     }
403     if (event.identifier.has_value()) {
404         valuesBucket.Put("identifier", event.identifier.value());
405     }
406     if (event.isLunar.has_value() && event.isLunar.value()!= false) {
407         valuesBucket.Put("event_calendar_type", event.isLunar.value());
408     }
409     return valuesBucket;
410 }
411 
412 DataShare::DataShareValuesBucket BuildAttendeeValue(const Attendee &attendee, int eventId)
413 {
414     DataShare::DataShareValuesBucket valuesBucket;
415     valuesBucket.Put("event_id", eventId);
416     valuesBucket.Put("attendeeName", attendee.name);
417     LOG_DEBUG("attendeeName %{private}s", attendee.name.c_str());
418     valuesBucket.Put("attendeeEmail", attendee.email);
419     LOG_DEBUG("attendeeEmail %{private}s", attendee.email.c_str());
420     if (attendee.role.has_value()) {
421         valuesBucket.Put("attendeeRelationship", attendee.role.value());
422     }
423     if (attendee.status.has_value()) {
424         valuesBucket.Put("attendeeStatus", attendee.status.value());
425     }
426     if (attendee.type.has_value()) {
427         valuesBucket.Put("attendeeType", attendee.type.value());
428     }
429 
430     return valuesBucket;
431 }
432 
433 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, int& out)
434 {
435     int index = 0;
436     auto ret = resultSet->GetColumnIndex(string(fieldName), index);
437     if (ret != DataShare::E_OK) {
438         return ret;
439     }
440     return resultSet->GetInt(index, out);
441 }
442 
443 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, std::string& out)
444 {
445     return resultSet->GetString(index, out);
446 }
447 
448 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int& out)
449 {
450     return resultSet->GetInt(index, out);
451 }
452 
453 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int64_t& out)
454 {
455     return resultSet->GetLong(index, out);
456 }
457 
458 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, std::string& out)
459 {
460     int index = 0;
461     auto fieldNameStr = string(fieldName);
462     auto ret = resultSet->GetColumnIndex(fieldNameStr, index);
463     if (ret != DataShare::E_OK) {
464         LOG_WARN("GetValue [%{private}s] failed [%{private}d]", fieldNameStr.c_str(), ret);
465         return ret;
466     }
467     return resultSet->GetString(index, out);
468 }
469 
470 std::vector<std::shared_ptr<CJNativeCalendar>> ResultSetToCalendars(DataShareResultSetPtr &resultSet)
471 {
472     std::vector<std::shared_ptr<CJNativeCalendar>> result;
473     int rowCount = 0;
474     resultSet->GetRowCount(rowCount);
475     LOG_INFO("GetRowCount is %{public}d", rowCount);
476     if (rowCount == 0) {
477         return result;
478     }
479     auto err = resultSet->GoToFirstRow();
480     if (err != DataShare::E_OK) {
481         LOG_INFO("Failed GoToFirstRow %{public}d", err);
482         return result;
483     }
484     do {
485         int idValue = -1;
486         if (GetValue(resultSet, "_id", idValue) != DataShare::E_OK) {
487             break;
488         }
489         LOG_DEBUG("id: %{private}d", idValue);
490         std::string nameValue;
491         if (GetValue(resultSet, "account_name", nameValue) != DataShare::E_OK) {
492             break;
493         }
494         LOG_DEBUG("account_name: %{private}s", nameValue.c_str());
495         std::string typeValue;
496         if (GetValue(resultSet, "account_type", typeValue) != DataShare::E_OK) {
497             break;
498         }
499         LOG_DEBUG("account_type: %{private}s", typeValue.c_str());
500 
501         std::string displayNameValue;
502         GetValue(resultSet, "calendar_displayName", displayNameValue);
503         LOG_DEBUG("calendar_displayName: %{private}s", displayNameValue.c_str());
504 
505         int canReminder = -1;
506         GetValue(resultSet, "canReminder", canReminder);
507         LOG_DEBUG("canReminder: %{private}d", canReminder);
508 
509         int colorValue = 0;
510         GetValue(resultSet, "calendar_color", colorValue);
511         CalendarAccount curAccount {nameValue, typeValue, displayNameValue};
512         result.emplace_back(std::make_shared<CJNativeCalendar>(curAccount, idValue));
513     } while (resultSet->GoToNextRow() == DataShare::E_OK);
514     return result;
515 }
516 
517 std::optional<Location> ResultSetToLocation(DataShareResultSetPtr &resultSet)
518 {
519     Location out;
520     string value;
521     auto ret = GetValue(resultSet, "eventLocation", value);
522     out.location = std::make_optional<string>(value);
523     ret = GetValue(resultSet, "location_longitude", value);
524     double longitudeValue = -1;
525     std::stringstream str2digit;
526     str2digit << value;
527     str2digit >> longitudeValue;
528     if (longitudeValue != -1) {
529         out.longitude = std::make_optional<double>(longitudeValue);
530     }
531     ret = GetValue(resultSet, "location_latitude", value);
532     double latitudeValue = -1;
533     str2digit.clear();
534     str2digit << value;
535     str2digit >> latitudeValue;
536     if (latitudeValue != -1) {
537         out.latitude = std::make_optional<double>(latitudeValue);
538     }
539 
540     if (ret != DataShare::E_OK) {
541         return std::nullopt;
542     }
543     return std::make_optional<Location>(out);
544 }
545 
546 std::optional<EventService> ResultSetToEventService(DataShareResultSetPtr &resultSet)
547 {
548     EventService out;
549     string value;
550     auto ret = GetValue(resultSet, "service_type", value);
551     if (ret != DataShare::E_OK) {
552         return std::nullopt;
553     }
554     const std::set<std::string> serviceType = {"Meeting", "Watching", "Repayment", "Live", "Shopping",
555                                                "Trip", "Class", "SportsEvents", "SportsExercise"};
556     if (serviceType.count(value)) {
557         out.type = value;
558     } else {
559         return std::nullopt;
560     }
561     ret = GetValue(resultSet, "service_cp_bz_uri", value);
562     if (ret != DataShare::E_OK) {
563         return std::nullopt;
564     }
565     out.uri = value;
566     ret = GetValue(resultSet, "service_description", value);
567     if (ret == DataShare::E_OK) {
568         out.description = std::make_optional<string>(value);
569     }
570     return std::make_optional<EventService>(out);
571 }
572 
573 int StringToInt(const std::string &str)
574 {
575     try {
576         return std::stoi(str);
577     } catch (std::exception &ex) {
578         LOG_ERROR("StringToInt conversion fail, str: %{public}s", str.c_str());
579         return 0;
580     }
581 }
582 
583 std::time_t TimeToUTC(const std::string &strTime)
584 {
585     const int baseYear = 1900;
586     const int offset = 2;
587     const int yearOffset = 4;
588     const int monBase = 4;
589     const int dayBase = 6;
590     const int hourBase = 9;
591     const int minBase = 11;
592     const int secBase = 13;
593     const int monCount = 12;
594     const int monRectify = 11;
595     const int micSecond = 1000;
596     const int timeStrLenMin = 8;
597     const int timeStrLen = 15;
598 
599     std::tm expireTime = {0};
600     if (strTime.size() < timeStrLenMin) {
601         LOG_DEBUG("strTime length error");
602         return 0;
603     }
604     expireTime.tm_year = StringToInt(strTime.substr(0, yearOffset)) - baseYear;
605     expireTime.tm_mon = (StringToInt(strTime.substr(monBase, offset)) + monRectify) % monCount;
606     expireTime.tm_mday = StringToInt(strTime.substr(dayBase, offset));
607     if (strTime.find("T") != std::string::npos && strTime.length() >= timeStrLen) {
608         expireTime.tm_hour = StringToInt(strTime.substr(hourBase, offset));
609         expireTime.tm_min = StringToInt(strTime.substr(minBase, offset));
610         expireTime.tm_sec = StringToInt(strTime.substr(secBase,  offset));
611     } else {
612         expireTime.tm_hour = 0;
613         expireTime.tm_min = 0;
614         expireTime.tm_sec = 0;
615     }
616 
617     std::time_t utcTime = mktime(&expireTime) * micSecond; //精确到微秒
618 
619     return utcTime;
620 }
621 
622 std::vector<std::string> SplitString(const std::string &str, const std::string &flag)
623 {
624     std::vector<std::string> result;
625     std::string::size_type pos1 = 0;
626     std::string::size_type pos2 = str.find(flag);
627     while (pos2 != std::string::npos) {
628         result.push_back(str.substr(pos1, pos2 - pos1));
629         pos1 = pos2 + flag.size();
630         pos2 = str.find(flag, pos1);
631     }
632     if (pos1 != str.length()) {
633         result.push_back(str.substr(pos1));
634     }
635 
636     return result;
637 }
638 
639 std::optional<vector<int64_t>> ResultSetToExcludedDates(DataShareResultSetPtr &resultSet)
640 {
641     std::string value;
642     auto ret = GetValue(resultSet, "exdate", value);
643     if (ret != DataShare::E_OK) {
644         return std::nullopt;
645     }
646     std::vector<string> strListExDate = SplitString(value, ",");
647 
648     std::vector<int64_t> excludedDates;
649     for (const auto &str : strListExDate) {
650         auto exDate = TimeToUTC(str);
651         excludedDates.emplace_back(exDate);
652     }
653 
654     return std::make_optional<vector<int64_t>>(excludedDates);
655 }
656 
657 void ConvertRecurrenceFrequency(const std::string &frequency, RecurrenceRule &rule)
658 {
659     if (frequency == "YEARLY") {
660         rule.recurrenceFrequency = YEARLY;
661         return;
662     }
663     if (frequency == "MONTHLY") {
664         rule.recurrenceFrequency = MONTHLY;
665         return;
666     }
667     if (frequency == "WEEKLY") {
668         rule.recurrenceFrequency = WEEKLY;
669         return;
670     }
671     if (frequency == "DAILY") {
672         rule.recurrenceFrequency = DAILY;
673     }
674 }
675 
676 std::optional<RecurrenceRule> ResultSetToRecurrenceRule(DataShareResultSetPtr &resultSet)
677 {
678     const int strListSize = 2;
679     RecurrenceRule out;
680     out.recurrenceFrequency = NORULE;
681     std::string value;
682     auto ret = GetValue(resultSet, "rrule", value);
683     if (ret != DataShare::E_OK) {
684         return std::nullopt;
685     }
686     std::map<std::string, std::string> ruleMap;
687     std::vector<std::string> strListRule = SplitString(value, ";");
688     for (const auto &str : strListRule) {
689         std::vector<std::string> keyAndValue = SplitString(str, "=");
690         if (keyAndValue.size() == strListSize) {
691             ruleMap.insert(std::pair<std::string, std::string>(keyAndValue[0], keyAndValue[1]));
692         }
693     }
694     SetRRuleValue(ruleMap, out);
695     out.excludedDates = ResultSetToExcludedDates(resultSet);
696 
697     return std::make_optional<RecurrenceRule>(out);
698 }
699 
700 void SetVecNum(std::optional<std::vector<int64_t>> &ruleVec, const std::string &ruleStr)
701 {
702     std::vector<std::string> weekNumList = SplitString(ruleStr, ",");
703     for (const auto &weekNum : weekNumList) {
704         ruleVec->push_back(StringToInt(weekNum));
705     }
706 }
707 
708 void SetRRuleValue(const std::map<std::string, std::string> &ruleMap, RecurrenceRule &out)
709 {
710     std::map<std::string, std::string>::const_iterator iter;
711     for (iter = ruleMap.begin(); iter != ruleMap.end(); iter++) {
712         if (iter->first == "FREQ") {
713             ConvertRecurrenceFrequency(iter->second, out);
714             continue;
715         }
716         if (iter->first == "COUNT") {
717             out.count = std::make_optional<int64_t>(StringToInt(iter->second));
718             continue;
719         }
720         if (iter->first == "INTERVAL") {
721             out.interval = std::make_optional<int64_t>(StringToInt(iter->second));
722             continue;
723         }
724         if (iter->first == "UNTIL") {
725             out.expire = std::make_optional<int64_t>(TimeToUTC(iter->second));
726         }
727         if (iter->first == "BYDAY") {
728             std::vector<std::string> weekDayList = SplitString(iter->second, ",");
729             SetByDayOfRRule(weekDayList, out);
730         }
731         if (iter->first == "BYWEEKNO") {
732             out.weeksOfYear = std::make_optional<std::vector<int64_t>>();
733             SetVecNum(out.weeksOfYear, iter->second);
734         }
735         if (iter->first == "BYMONTHDAY") {
736             out.daysOfMonth = std::make_optional<std::vector<int64_t>>();
737             SetVecNum(out.daysOfMonth, iter->second);
738         }
739         if (iter->first == "BYYEARDAY") {
740             out.daysOfYear = std::make_optional<std::vector<int64_t>>();
741             SetVecNum(out.daysOfYear, iter->second);
742         }
743         if (iter->first == "BYMONTH") {
744             out.monthsOfYear = std::make_optional<std::vector<int64_t>>();
745             SetVecNum(out.monthsOfYear, iter->second);
746         }
747     }
748 }
749 
750 void SetByDayOfRRule(const std::vector<std::string> &weekDayList, RecurrenceRule &out)
751 {
752     const int weekStrLen = 2;
753     const std::vector<string> dayOfWeekList = {"MO", "TU", "WE", "TH", "FR", "SA", "SU"};
754     out.daysOfWeek = std::make_optional<vector<int64_t>>();
755     out.weeksOfMonth = std::make_optional<vector<int64_t>>();
756     for (const auto &weekday : weekDayList) {
757         if (weekday.length() > weekStrLen) {
758             std::string weekDayStr = weekday.substr(weekday.length() - weekStrLen, weekStrLen);
759             std::string WeekNumStr = weekday.substr(0, weekday.length() - weekStrLen);
760             auto it = std::find(dayOfWeekList.begin(), dayOfWeekList.end(), weekDayStr);
761             if (it != dayOfWeekList.end()) {
762                 int dayNum = it - dayOfWeekList.begin();
763                 out.daysOfWeek->push_back(dayNum + 1);
764                 out.weeksOfMonth->push_back(StringToInt(WeekNumStr));
765             }
766         } else if (weekday.length() == weekStrLen) {
767             auto it = std::find(dayOfWeekList.begin(), dayOfWeekList.end(), weekday);
768             if (it != dayOfWeekList.end()) {
769                 int dayNum = it - dayOfWeekList.begin();
770                 out.daysOfWeek->push_back(dayNum + 1);
771             }
772         }
773     }
774 }
775 
776 void ResultSetToInstanceTime(Event &event, DataShareResultSetPtr &resultSet, const std::set<std::string>& columns)
777 {
778     if (columns.count("instanceStartTime")) {
779         GetValueOptional(resultSet, "begin", event.instanceStartTime);
780     }
781 
782     if (columns.count("instanceEndTime")) {
783         GetValueOptional(resultSet, "end", event.instanceEndTime);
784     }
785 }
786 
787 void ResultSetToEvent(Event &event, DataShareResultSetPtr &resultSet, const std::set<std::string>& columns)
788 {
789     GetValueOptional(resultSet, "_id", event.id);
790     if (columns.count("type")) {
791         int type = 0;
792         GetValue(resultSet, "important_event_type", type);
793         event.type = static_cast<EventType>(type);
794     }
795     if (columns.count("title")) {
796         GetValueOptional(resultSet, "title", event.title);
797     }
798     if (columns.count("startTime")) {
799         LOG_DEBUG("TLQ get startTime");
800         GetValue(resultSet, "dtstart", event.startTime);
801     }
802     if (columns.count("endTime")) {
803         LOG_DEBUG("TLQ get endTime");
804         GetValue(resultSet, "dtend", event.endTime);
805     }
806     if (columns.count("isAllDay")) {
807         int isAllDay = 0;
808         GetValue(resultSet, "allDay", isAllDay);
809         event.isAllDay = static_cast<bool>(isAllDay);
810     }
811     if (columns.count("description")) {
812         GetValueOptional(resultSet, "description", event.description);
813     }
814     if (columns.count("timeZone")) {
815         GetValueOptional(resultSet, "eventTimezone", event.timeZone);
816     }
817     if (columns.count("location")) {
818         event.location = ResultSetToLocation(resultSet);
819     }
820     if (columns.count("service")) {
821         event.service = ResultSetToEventService(resultSet);
822     }
823     if (columns.count("recurrenceRule")) {
824         event.recurrenceRule = ResultSetToRecurrenceRule(resultSet);
825     }
826 
827     if (columns.count("identifier")) {
828         GetValueOptional(resultSet, "identifier", event.identifier);
829     }
830     if (columns.count("isLunar")) {
831         int isLunar = 0;
832         GetValue(resultSet, "event_calendar_type", isLunar);
833         event.isLunar = static_cast<bool>(isLunar);
834     }
835     ResultSetToInstanceTime(event, resultSet, columns);
836 }
837 
838 int ResultSetToEvents(std::vector<Event> &events, DataShareResultSetPtr &resultSet,
839     const std::set<std::string>& columns)
840 {
841     int rowCount = 0;
842     resultSet->GetRowCount(rowCount);
843     LOG_INFO("GetRowCount is %{public}d", rowCount);
844     if (rowCount <= 0) {
845         return -1;
846     }
847     auto err = resultSet->GoToFirstRow();
848     if (err != DataShare::E_OK) {
849         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
850         return -1;
851     }
852     do {
853         Event event;
854         ResultSetToEvent(event, resultSet, columns);
855         events.emplace_back(event);
856     } while (resultSet->GoToNextRow() == DataShare::E_OK);
857     return 0;
858 }
859 
860 void ResultSetToAttendeeStatus(Attendee &attendee, DataShareResultSetPtr &resultSet)
861 {
862     int statusValue = 0;
863     GetValue(resultSet, "attendeeStatus", statusValue);
864     if (statusValue == UNKNOWN) {
865         attendee.status = std::make_optional<AttendeeStatus>(UNKNOWN);
866     } else if (statusValue == TENTATIVE) {
867         attendee.status = std::make_optional<AttendeeStatus>(TENTATIVE);
868     } else if (statusValue == ACCEPTED) {
869         attendee.status = std::make_optional<AttendeeStatus>(ACCEPTED);
870     } else if (statusValue == DECLINED) {
871         attendee.status = std::make_optional<AttendeeStatus>(DECLINED);
872     } else {
873         attendee.status = std::make_optional<AttendeeStatus>(UNRESPONSIVE);
874     }
875 }
876 
877 void ResultSetToAttendeeType(Attendee &attendee, DataShareResultSetPtr &resultSet)
878 {
879     int typeValue = 0;
880     GetValue(resultSet, "attendeeType", typeValue);
881     if (typeValue == REQUIRED) {
882         attendee.type = std::make_optional<AttendeeType>(REQUIRED);
883     } else if (typeValue == OPTIONAL) {
884         attendee.type = std::make_optional<AttendeeType>(OPTIONAL);
885     } else {
886         attendee.type = std::make_optional<AttendeeType>(RESOURCE);
887     }
888 }
889 
890 int ResultSetToAttendees(std::vector<Attendee> &attendees, DataShareResultSetPtr &resultSet)
891 {
892     int rowCount = 0;
893     resultSet->GetRowCount(rowCount);
894     LOG_INFO("GetRowCount is %{public}d", rowCount);
895     if (rowCount <= 0) {
896         return -1;
897     }
898     auto err = resultSet->GoToFirstRow();
899     if (err != DataShare::E_OK) {
900         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
901         return -1;
902     }
903     int roleValue = 0;
904     do {
905         Attendee attendee;
906         GetValue(resultSet, "attendeeName", attendee.name);
907         GetValue(resultSet, "attendeeEmail", attendee.email);
908         GetValue(resultSet, "attendeeRelationship",  roleValue);
909         if (roleValue == PARTICIPANT) {
910             attendee.role = std::make_optional<RoleType>(PARTICIPANT);
911         } else if (roleValue == ORGANIZER) {
912             attendee.role = std::make_optional<RoleType>(ORGANIZER);
913         }
914 
915         ResultSetToAttendeeStatus(attendee, resultSet);
916         ResultSetToAttendeeType(attendee, resultSet);
917         attendees.emplace_back(attendee);
918     } while (resultSet->GoToNextRow() == DataShare::E_OK);
919     return 0;
920 }
921 
922 std::string EventIdsToString(const std::vector<int> &ids) {
923     if (ids.empty()) {
924         return "";
925     }
926     return std::accumulate(std::next(ids.begin()), ids.end(), std::to_string(ids[0]),
927         [](const std::string& a, int b) {
928             std::stringstream ss;
929             ss << a << ", " << b;
930             return ss.str();
931         }
932     );
933 }
934 
935 int ResultSetToReminders(std::vector<int> &reminders, DataShareResultSetPtr &resultSet)
936 {
937     int rowCount = 0;
938     resultSet->GetRowCount(rowCount);
939     LOG_INFO("GetRowCount is %{public}d", rowCount);
940     if (rowCount <= 0) {
941         return -1;
942     }
943     auto err = resultSet->GoToFirstRow();
944     if (err != DataShare::E_OK) {
945         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
946         return -1;
947     }
948     do {
949         int minutes = 0;
950         GetValue(resultSet, "minutes", minutes);
951         reminders.emplace_back(minutes);
952     } while (resultSet->GoToNextRow() == DataShare::E_OK);
953     return 0;
954 }
955 
956 void ResultSetToConfig(CalendarConfig &config, DataShareResultSetPtr &resultSet)
957 {
958     int rowCount = 0;
959     resultSet->GetRowCount(rowCount);
960     LOG_INFO("GetRowCount is %{public}d", rowCount);
961     auto err = resultSet->GoToFirstRow();
962     if (err != DataShare::E_OK) {
963         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
964     }
965     do {
966         int enableReminder = 0;
967         std::int64_t color = 0;
968         GetValue(resultSet, "canReminder", enableReminder);
969         GetValue(resultSet, "calendar_color", color);
970         config.enableReminder = static_cast<bool>(enableReminder);
971         LOG_INFO("enableReminder is %{public}d", enableReminder);
972         config.color = color;
973     } while (resultSet->GoToNextRow() == DataShare::E_OK);
974 }
975 
976 bool IsValidHexString(const std::string& colorStr)
977 {
978     if (colorStr.empty()) {
979         return false;
980     }
981     for (char ch : colorStr) {
982         if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
983             continue;
984         }
985         return false;
986     }
987     return true;
988 }
989 
990 bool ColorParse(const std::string& colorStr, variant<string, int64_t>& colorValue)
991 {
992     if (colorStr.empty()) {
993         LOG_ERROR("color string is empty");
994         return false;
995     }
996 
997     if (colorStr[0] != '#') { // start with '#'
998         LOG_ERROR("color string not start with #");
999         return false;
1000     }
1001 
1002     const int rgbLen = 7;
1003     const int argbLen = 9;
1004     if (colorStr.size() != rgbLen && colorStr.size() != argbLen) {
1005         LOG_ERROR("color string length is not 7 or 9");
1006         return false;
1007     }
1008 
1009     std::string colorStrSub = colorStr.substr(1);
1010     if (!IsValidHexString(colorStrSub)) {
1011         LOG_DEBUG("color string is not valid hex string");
1012         return false;
1013     }
1014 
1015     LOG_DEBUG("color string size is 7 or 9");
1016     try {
1017         colorValue.emplace<1>(std::stoll(colorStrSub, NULL, 16));  // 16 is convert hex string to number
1018     } catch (std::exception &ex) {
1019         LOG_ERROR("stoll fail %{public}s", ex.what());
1020         return false;
1021     }
1022     if (std::get_if<1>(&colorValue)) {
1023         LOG_DEBUG("colorStrSub -> colorValue colorValue:%{public}s", std::to_string(std::get<1>(colorValue)).c_str());
1024         return true;
1025     }
1026     LOG_DEBUG("color is null");
1027     return false;
1028 }
1029 
1030 void SetLocationFieldInfo(std::vector<string>& queryField)
1031 {
1032     queryField.emplace_back("eventLocation");
1033     queryField.emplace_back("location_longitude");
1034     queryField.emplace_back("location_latitude");
1035 }
1036 
1037 void SetServiceFieldInfo(std::vector<string>& queryField)
1038 {
1039     queryField.emplace_back("service_type");
1040     queryField.emplace_back("service_cp_bz_uri");
1041     queryField.emplace_back("service_description");
1042 }
1043 
1044 void FillFieldInfo(const std::string field, std::vector<string>& queryField, std::set<string>& resultSetField,
1045     const std::map<string, string> eventField)
1046 {
1047     if (field == "location") {
1048             SetLocationFieldInfo(queryField);
1049             resultSetField.insert(field);
1050             return;
1051         }
1052         if (field == "service") {
1053             SetServiceFieldInfo(queryField);
1054             resultSetField.insert(field);
1055             return;
1056         }
1057         if (field == "attendee") {
1058             resultSetField.insert(field);
1059             return;
1060         }
1061         if (field == "reminderTime") {
1062             resultSetField.insert(field);
1063             return;
1064         }
1065         if (field == "identifier") {
1066             queryField.emplace_back("identifier");
1067             resultSetField.insert(field);
1068             return;
1069         }
1070         if (field == "recurrenceRule") {
1071             queryField.emplace_back("rrule");
1072             queryField.emplace_back("exdate");
1073             resultSetField.insert(field);
1074             return;
1075         }
1076         if (field == "isLunar") {
1077             queryField.emplace_back("event_calendar_type");
1078             resultSetField.insert(field);
1079             return;
1080         }
1081         if (field == "instanceStartTime") {
1082             queryField.emplace_back("begin");
1083             resultSetField.insert(field);
1084             return;
1085         }
1086         if (field == "instanceEndTime") {
1087             queryField.emplace_back("end");
1088             resultSetField.insert(field);
1089             return;
1090         }
1091         queryField.emplace_back(eventField.at(field));
1092         resultSetField.insert(field);
1093 }
1094 
1095 void SetFieldInfo(const std::vector<string>& eventKey, std::vector<string>& queryField,
1096     std::set<string>& resultSetField, const std::map<string, string> eventField)
1097 {
1098     for (const auto& field : eventKey) {
1099         if (field == "id") {
1100             continue;
1101         }
1102         FillFieldInfo(field, queryField, resultSetField, eventField);
1103     }
1104 }
1105 
1106 void SetField(const std::vector<string>& eventKey, std::vector<string>& queryField, std::set<string>& resultSetField)
1107 {
1108     const std::map<string, string> eventField = { { "id", "_id" },
1109                                                   { "type", "important_event_type" },
1110                                                   { "title", "title" },
1111                                                   { "startTime", "dtstart" },
1112                                                   { "endTime", "dtend" },
1113                                                   { "isAllDay", "allDay" },
1114                                                   { "timeZone", "eventTimezone" },
1115                                                   { "description", "description" }};
1116     SetFieldInfo(eventKey, queryField, resultSetField, eventField);
1117 }
1118 }