• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "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     valuesBucket.Put("channel_id", channelId);
388 
389     BuildEventLocation(valuesBucket, event);
390     BuildEventService(valuesBucket, event);
391     BuildEventRecurrenceRule(valuesBucket, event);
392 
393     LOG_DEBUG("description %{private}s", event.description.value_or("").c_str());
394 
395     if (event.description.has_value()) {
396         valuesBucket.Put("description", event.description.value());
397     }
398     if (event.timeZone.has_value()) {
399         valuesBucket.Put("eventTimezone", event.timeZone.value());
400     }
401     if (event.isAllDay.has_value()) {
402         valuesBucket.Put("allDay", event.isAllDay.value());
403     }
404     if (event.identifier.has_value()) {
405         valuesBucket.Put("identifier", event.identifier.value());
406     }
407     if (event.isLunar.has_value()) {
408         valuesBucket.Put("event_calendar_type", event.isLunar.value());
409     }
410     return valuesBucket;
411 }
412 
413 DataShare::DataShareValuesBucket BuildAttendeeValue(const Attendee &attendee, int eventId)
414 {
415     DataShare::DataShareValuesBucket valuesBucket;
416     valuesBucket.Put("event_id", eventId);
417     valuesBucket.Put("attendeeName", attendee.name);
418     LOG_DEBUG("attendeeName %{private}s", attendee.name.c_str());
419     valuesBucket.Put("attendeeEmail", attendee.email);
420     LOG_DEBUG("attendeeEmail %{private}s", attendee.email.c_str());
421     if (attendee.role.has_value()) {
422         valuesBucket.Put("attendeeRelationship", attendee.role.value());
423     }
424     if (attendee.status.has_value()) {
425         valuesBucket.Put("attendeeStatus", attendee.status.value());
426     }
427     if (attendee.type.has_value()) {
428         valuesBucket.Put("attendeeType", attendee.type.value());
429     }
430 
431     return valuesBucket;
432 }
433 
434 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, int& out)
435 {
436     int index = 0;
437     auto ret = resultSet->GetColumnIndex(string(fieldName), index);
438     if (ret != DataShare::E_OK) {
439         return ret;
440     }
441     return resultSet->GetInt(index, out);
442 }
443 
444 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, std::string& out)
445 {
446     return resultSet->GetString(index, out);
447 }
448 
449 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int& out)
450 {
451     return resultSet->GetInt(index, out);
452 }
453 
454 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int64_t& out)
455 {
456     return resultSet->GetLong(index, out);
457 }
458 
459 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, std::string& out)
460 {
461     int index = 0;
462     auto fieldNameStr = string(fieldName);
463     auto ret = resultSet->GetColumnIndex(fieldNameStr, index);
464     if (ret != DataShare::E_OK) {
465         LOG_WARN("GetValue [%{private}s] failed [%{private}d]", fieldNameStr.c_str(), ret);
466         return ret;
467     }
468     return resultSet->GetString(index, out);
469 }
470 
471 std::vector<std::shared_ptr<Calendar>> ResultSetToCalendars(DataShareResultSetPtr &resultSet)
472 {
473     std::vector<std::shared_ptr<Calendar>> result;
474     int rowCount = 0;
475     resultSet->GetRowCount(rowCount);
476     LOG_INFO("GetRowCount is %{public}d", rowCount);
477     if (rowCount == 0) {
478         return result;
479     }
480     auto err = resultSet->GoToFirstRow();
481     if (err != DataShare::E_OK) {
482         LOG_INFO("Failed GoToFirstRow %{public}d", err);
483         return result;
484     }
485     do {
486         int idValue = -1;
487         if (GetValue(resultSet, "_id", idValue) != DataShare::E_OK) {
488             break;
489         }
490         LOG_DEBUG("id: %{private}d", idValue);
491         std::string nameValue;
492         if (GetValue(resultSet, "account_name", nameValue) != DataShare::E_OK) {
493             break;
494         }
495         LOG_DEBUG("account_name: %{private}s", nameValue.c_str());
496         std::string typeValue;
497         if (GetValue(resultSet, "account_type", typeValue) != DataShare::E_OK) {
498             break;
499         }
500         LOG_DEBUG("account_type: %{private}s", typeValue.c_str());
501 
502         std::string displayNameValue;
503         GetValue(resultSet, "calendar_displayName", displayNameValue);
504         LOG_DEBUG("calendar_displayName: %{private}s", displayNameValue.c_str());
505 
506         int canReminder = -1;
507         GetValue(resultSet, "canReminder", canReminder);
508         LOG_DEBUG("canReminder: %{private}d", canReminder);
509 
510         int colorValue = 0;
511         GetValue(resultSet, "calendar_color", colorValue);
512         CalendarAccount curAccount {nameValue, typeValue, displayNameValue};
513         result.emplace_back(std::make_shared<Calendar>(curAccount, idValue));
514     } while (resultSet->GoToNextRow() == DataShare::E_OK);
515     return result;
516 }
517 
518 std::optional<Location> ResultSetToLocation(DataShareResultSetPtr &resultSet)
519 {
520     Location out;
521     string value;
522     double maxLon = 180;
523     double maxLat = 90;
524     auto ret = GetValue(resultSet, "eventLocation", value);
525     out.location = std::make_optional<string>(value);
526     ret = GetValue(resultSet, "location_longitude", value);
527     std::stringstream str2digit;
528     double longitudeValue = 0;
529     if (!value.empty()) {
530         str2digit << value;
531         str2digit >> longitudeValue;
532         if (fabs(longitudeValue) <= maxLon) {
533             out.longitude = std::make_optional<double>(longitudeValue);
534         }
535     }
536 
537     ret = GetValue(resultSet, "location_latitude", value);
538     double latitudeValue = 0;
539     str2digit.clear();
540     if (!value.empty()) {
541         str2digit << value;
542         str2digit >> latitudeValue;
543         if (fabs(latitudeValue) <= maxLat) {
544             out.latitude = std::make_optional<double>(latitudeValue);
545         }
546     }
547 
548     if (ret != DataShare::E_OK) {
549         return std::nullopt;
550     }
551     return std::make_optional<Location>(out);
552 }
553 
554 std::optional<EventService> ResultSetToEventService(DataShareResultSetPtr &resultSet)
555 {
556     EventService out;
557     string value;
558     auto ret = GetValue(resultSet, "service_type", value);
559     if (ret != DataShare::E_OK) {
560         return std::nullopt;
561     }
562     const std::set<std::string> serviceType = {"Meeting", "Watching", "Repayment", "Live", "Shopping",
563                                                "Trip", "Class", "SportsEvents", "SportsExercise"};
564     if (serviceType.count(value)) {
565         out.type = value;
566     } else {
567         return std::nullopt;
568     }
569     ret = GetValue(resultSet, "service_cp_bz_uri", value);
570     if (ret != DataShare::E_OK) {
571         return std::nullopt;
572     }
573     out.uri = value;
574     ret = GetValue(resultSet, "service_description", value);
575     if (ret == DataShare::E_OK) {
576         out.description = std::make_optional<string>(value);
577     }
578     return std::make_optional<EventService>(out);
579 }
580 
581 int StringToInt(const std::string &str)
582 {
583     try {
584         return std::stoi(str);
585     } catch (std::exception &ex) {
586         LOG_ERROR("StringToInt conversion fail, str: %{public}s", str.c_str());
587         return 0;
588     }
589 }
590 
591 std::time_t TimeToUTC(const std::string &strTime)
592 {
593     const int baseYear = 1900;
594     const int offset = 2;
595     const int yearOffset = 4;
596     const int monBase = 4;
597     const int dayBase = 6;
598     const int hourBase = 9;
599     const int minBase = 11;
600     const int secBase = 13;
601     const int monCount = 12;
602     const int monRectify = 11;
603     const int micSecond = 1000;
604     const int timeStrLenMin = 8;
605     const int timeStrLen = 15;
606 
607     std::tm expireTime = {0};
608     if (strTime.size() < timeStrLenMin) {
609         LOG_DEBUG("strTime length error");
610         return 0;
611     }
612     expireTime.tm_year = StringToInt(strTime.substr(0, yearOffset)) - baseYear;
613     expireTime.tm_mon = (StringToInt(strTime.substr(monBase, offset)) + monRectify) % monCount;
614     expireTime.tm_mday = StringToInt(strTime.substr(dayBase, offset));
615     if (strTime.find("T") != std::string::npos && strTime.length() >= timeStrLen) {
616         expireTime.tm_hour = StringToInt(strTime.substr(hourBase, offset));
617         expireTime.tm_min = StringToInt(strTime.substr(minBase, offset));
618         expireTime.tm_sec = StringToInt(strTime.substr(secBase,  offset));
619     } else {
620         expireTime.tm_hour = 0;
621         expireTime.tm_min = 0;
622         expireTime.tm_sec = 0;
623     }
624 
625     std::time_t utcTime = mktime(&expireTime) * micSecond; //精确到微秒
626 
627     return utcTime;
628 }
629 
630 std::vector<std::string> SplitString(const std::string &str, const std::string &flag)
631 {
632     std::vector<std::string> result;
633     std::string::size_type pos1 = 0;
634     std::string::size_type pos2 = str.find(flag);
635     while (pos2 != std::string::npos) {
636         result.push_back(str.substr(pos1, pos2 - pos1));
637         pos1 = pos2 + flag.size();
638         pos2 = str.find(flag, pos1);
639     }
640     if (pos1 != str.length()) {
641         result.push_back(str.substr(pos1));
642     }
643 
644     return result;
645 }
646 
647 std::optional<vector<int64_t>> ResultSetToExcludedDates(DataShareResultSetPtr &resultSet)
648 {
649     std::string value;
650     auto ret = GetValue(resultSet, "exdate", value);
651     if (ret != DataShare::E_OK) {
652         return std::nullopt;
653     }
654     std::vector<string> strListExDate = SplitString(value, ",");
655 
656     std::vector<int64_t> excludedDates;
657     for (const auto &str : strListExDate) {
658         auto exDate = TimeToUTC(str);
659         excludedDates.emplace_back(exDate);
660     }
661 
662     return std::make_optional<vector<int64_t>>(excludedDates);
663 }
664 
665 void ConvertRecurrenceFrequency(const std::string &frequency, RecurrenceRule &rule)
666 {
667     if (frequency == "YEARLY") {
668         rule.recurrenceFrequency = YEARLY;
669         return;
670     }
671     if (frequency == "MONTHLY") {
672         rule.recurrenceFrequency = MONTHLY;
673         return;
674     }
675     if (frequency == "WEEKLY") {
676         rule.recurrenceFrequency = WEEKLY;
677         return;
678     }
679     if (frequency == "DAILY") {
680         rule.recurrenceFrequency = DAILY;
681     }
682 }
683 
684 std::optional<RecurrenceRule> ResultSetToRecurrenceRule(DataShareResultSetPtr &resultSet)
685 {
686     const int strListSize = 2;
687     RecurrenceRule out;
688     out.recurrenceFrequency = NORULE;
689     std::string value;
690     auto ret = GetValue(resultSet, "rrule", value);
691     if (ret != DataShare::E_OK) {
692         return std::nullopt;
693     }
694     std::map<std::string, std::string> ruleMap;
695     std::vector<std::string> strListRule = SplitString(value, ";");
696     for (const auto &str : strListRule) {
697         std::vector<std::string> keyAndValue = SplitString(str, "=");
698         if (keyAndValue.size() == strListSize) {
699             ruleMap.insert(std::pair<std::string, std::string>(keyAndValue[0], keyAndValue[1]));
700         }
701     }
702     SetRRuleValue(ruleMap, out);
703     out.excludedDates = ResultSetToExcludedDates(resultSet);
704 
705     return std::make_optional<RecurrenceRule>(out);
706 }
707 
708 void SetVecNum(std::optional<std::vector<int64_t>> &ruleVec, const std::string &ruleStr)
709 {
710     std::vector<std::string> weekNumList = SplitString(ruleStr, ",");
711     for (const auto &weekNum : weekNumList) {
712         ruleVec->push_back(StringToInt(weekNum));
713     }
714 }
715 
716 void SetRRuleValue(const std::map<std::string, std::string> &ruleMap, RecurrenceRule &out)
717 {
718     std::map<std::string, std::string>::const_iterator iter;
719     for (iter = ruleMap.begin(); iter != ruleMap.end(); iter++) {
720         if (iter->first == "FREQ") {
721             ConvertRecurrenceFrequency(iter->second, out);
722             continue;
723         }
724         if (iter->first == "COUNT") {
725             out.count = std::make_optional<int64_t>(StringToInt(iter->second));
726             continue;
727         }
728         if (iter->first == "INTERVAL") {
729             out.interval = std::make_optional<int64_t>(StringToInt(iter->second));
730             continue;
731         }
732         if (iter->first == "UNTIL") {
733             out.expire = std::make_optional<int64_t>(TimeToUTC(iter->second));
734         }
735         if (iter->first == "BYDAY") {
736             std::vector<std::string> weekDayList = SplitString(iter->second, ",");
737             SetByDayOfRRule(weekDayList, out);
738         }
739         if (iter->first == "BYWEEKNO") {
740             out.weeksOfYear = std::make_optional<std::vector<int64_t>>();
741             SetVecNum(out.weeksOfYear, iter->second);
742         }
743         if (iter->first == "BYMONTHDAY") {
744             out.daysOfMonth = std::make_optional<std::vector<int64_t>>();
745             SetVecNum(out.daysOfMonth, iter->second);
746         }
747         if (iter->first == "BYYEARDAY") {
748             out.daysOfYear = std::make_optional<std::vector<int64_t>>();
749             SetVecNum(out.daysOfYear, iter->second);
750         }
751         if (iter->first == "BYMONTH") {
752             out.monthsOfYear = std::make_optional<std::vector<int64_t>>();
753             SetVecNum(out.monthsOfYear, iter->second);
754         }
755     }
756 }
757 
758 void SetByDayOfRRule(const std::vector<std::string> &weekDayList, RecurrenceRule &out)
759 {
760     const int weekStrLen = 2;
761     const std::vector<string> dayOfWeekList = {"MO", "TU", "WE", "TH", "FR", "SA", "SU"};
762     out.daysOfWeek = std::make_optional<vector<int64_t>>();
763     out.weeksOfMonth = std::make_optional<vector<int64_t>>();
764     for (const auto &weekday : weekDayList) {
765         if (weekday.length() > weekStrLen) {
766             std::string weekDayStr = weekday.substr(weekday.length() - weekStrLen, weekStrLen);
767             std::string WeekNumStr = weekday.substr(0, weekday.length() - weekStrLen);
768             auto it = std::find(dayOfWeekList.begin(), dayOfWeekList.end(), weekDayStr);
769             if (it != dayOfWeekList.end()) {
770                 int dayNum = it - dayOfWeekList.begin();
771                 out.daysOfWeek->push_back(dayNum + 1);
772                 out.weeksOfMonth->push_back(StringToInt(WeekNumStr));
773             }
774         } else if (weekday.length() == weekStrLen) {
775             auto it = std::find(dayOfWeekList.begin(), dayOfWeekList.end(), weekday);
776             if (it != dayOfWeekList.end()) {
777                 int dayNum = it - dayOfWeekList.begin();
778                 out.daysOfWeek->push_back(dayNum + 1);
779             }
780         }
781     }
782 }
783 
784 void ResultSetToInstanceTime(Event &event, DataShareResultSetPtr &resultSet, const std::set<std::string>& columns)
785 {
786     if (columns.count("instanceStartTime")) {
787         GetValueOptional(resultSet, "begin", event.instanceStartTime);
788     }
789 
790     if (columns.count("instanceEndTime")) {
791         GetValueOptional(resultSet, "end", event.instanceEndTime);
792     }
793 }
794 
795 void ResultSetToEvent(Event &event, DataShareResultSetPtr &resultSet, const std::set<std::string>& columns)
796 {
797     GetValueOptional(resultSet, "_id", event.id);
798     if (columns.count("type")) {
799         int type = 0;
800         GetValue(resultSet, "important_event_type", type);
801         event.type = static_cast<EventType>(type);
802     }
803     if (columns.count("title")) {
804         GetValueOptional(resultSet, "title", event.title);
805     }
806     if (columns.count("startTime")) {
807         LOG_DEBUG("TLQ get startTime");
808         GetValue(resultSet, "dtstart", event.startTime);
809     }
810     if (columns.count("endTime")) {
811         LOG_DEBUG("TLQ get endTime");
812         GetValue(resultSet, "dtend", event.endTime);
813     }
814     if (columns.count("isAllDay")) {
815         int isAllDay = 0;
816         GetValue(resultSet, "allDay", isAllDay);
817         event.isAllDay = static_cast<bool>(isAllDay);
818     }
819     if (columns.count("description")) {
820         GetValueOptional(resultSet, "description", event.description);
821     }
822     if (columns.count("timeZone")) {
823         GetValueOptional(resultSet, "eventTimezone", event.timeZone);
824     }
825     if (columns.count("location")) {
826         event.location = ResultSetToLocation(resultSet);
827     }
828     if (columns.count("service")) {
829         event.service = ResultSetToEventService(resultSet);
830     }
831     if (columns.count("recurrenceRule")) {
832         event.recurrenceRule = ResultSetToRecurrenceRule(resultSet);
833     }
834 
835     if (columns.count("identifier")) {
836         GetValueOptional(resultSet, "identifier", event.identifier);
837     }
838     if (columns.count("isLunar")) {
839         int isLunar = 0;
840         GetValue(resultSet, "event_calendar_type", isLunar);
841         event.isLunar = static_cast<bool>(isLunar);
842     }
843     ResultSetToInstanceTime(event, resultSet, columns);
844 }
845 
846 int ResultSetToEvents(std::vector<std::string> &eventIds, std::vector<Event> &events,
847     DataShareResultSetPtr &resultSet, const std::set<std::string>& columns)
848 {
849     int rowCount = 0;
850     resultSet->GetRowCount(rowCount);
851     LOG_INFO("GetRowCount is %{public}d", rowCount);
852     if (rowCount <= 0) {
853         return -1;
854     }
855     auto err = resultSet->GoToFirstRow();
856     if (err != DataShare::E_OK) {
857         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
858         return -1;
859     }
860     do {
861         Event event;
862         ResultSetToEvent(event, resultSet, columns);
863         if (!event.id.has_value()) {
864             continue;
865         }
866         eventIds.emplace_back(std::to_string(event.id.value()));
867         events.emplace_back(event);
868     } while (resultSet->GoToNextRow() == DataShare::E_OK);
869     return 0;
870 }
871 
872 void ResultSetToAttendeeStatus(Attendee &attendee, DataShareResultSetPtr &resultSet)
873 {
874     int statusValue = 0;
875     GetValue(resultSet, "attendeeStatus", statusValue);
876     if (statusValue == UNKNOWN) {
877         attendee.status = std::make_optional<AttendeeStatus>(UNKNOWN);
878     } else if (statusValue == TENTATIVE) {
879         attendee.status = std::make_optional<AttendeeStatus>(TENTATIVE);
880     } else if (statusValue == ACCEPTED) {
881         attendee.status = std::make_optional<AttendeeStatus>(ACCEPTED);
882     } else if (statusValue == DECLINED) {
883         attendee.status = std::make_optional<AttendeeStatus>(DECLINED);
884     } else {
885         attendee.status = std::make_optional<AttendeeStatus>(UNRESPONSIVE);
886     }
887 }
888 
889 void ResultSetToAttendeeType(Attendee &attendee, DataShareResultSetPtr &resultSet)
890 {
891     int typeValue = 0;
892     GetValue(resultSet, "attendeeType", typeValue);
893     if (typeValue == REQUIRED) {
894         attendee.type = std::make_optional<AttendeeType>(REQUIRED);
895     } else if (typeValue == OPTIONAL) {
896         attendee.type = std::make_optional<AttendeeType>(OPTIONAL);
897     } else {
898         attendee.type = std::make_optional<AttendeeType>(RESOURCE);
899     }
900 }
901 
902 int ResultSetToMultiAttendees(std::vector<Event> &events, DataShareResultSetPtr &resultSet)
903 {
904     if (!resultSet) {
905         LOG_ERROR("resultSet is null");
906         return -1;
907     }
908     int rowCount = 0;
909     resultSet->GetRowCount(rowCount);
910     LOG_INFO("GetRowCount is %{public}d", rowCount);
911     if (rowCount <= 0) {
912         return -1;
913     }
914     auto err = resultSet->GoToFirstRow();
915     if (err != DataShare::E_OK) {
916         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
917         return -1;
918     }
919     std::map<int, std::vector<Attendee>> attendeesMap;
920     int roleValue = 0;
921     do {
922         Attendee attendee;
923         int eventId;
924         GetValue(resultSet, "event_id", eventId);
925         GetValue(resultSet, "attendeeName", attendee.name);
926         GetValue(resultSet, "attendeeEmail", attendee.email);
927         GetValue(resultSet, "attendeeRelationship",  roleValue);
928         if (roleValue == PARTICIPANT) {
929             attendee.role = std::make_optional<RoleType>(PARTICIPANT);
930         } else if (roleValue == ORGANIZER) {
931             attendee.role = std::make_optional<RoleType>(ORGANIZER);
932         }
933 
934         ResultSetToAttendeeStatus(attendee, resultSet);
935         ResultSetToAttendeeType(attendee, resultSet);
936 
937         auto attendeeFindId = attendeesMap.find(eventId);
938         if (attendeeFindId == attendeesMap.end()) {
939             attendeesMap.insert(std::pair<int, std::vector<Attendee>>(eventId, {attendee}));
940         } else {
941             attendeeFindId->second.emplace_back(attendee);
942         }
943     } while (resultSet->GoToNextRow() == DataShare::E_OK);
944     GetEventAttendeesValue(events, attendeesMap);
945     return 0;
946 }
947 
948 void GetEventAttendeesValue(std::vector<Event> &events, const std::map<int, std::vector<Attendee>> &attendeesMap) {
949     if (attendeesMap.size() == 0) {
950         LOG_ERROR("attendees has no value");
951         return;
952     }
953     for (auto &event : events) {
954         const auto id =  event.id;
955         if (!id) {
956             LOG_ERROR("event id is null");
957             continue;
958         }
959         auto attendeeFindId = attendeesMap.find(id.value());
960         if (attendeeFindId != attendeesMap.end()) {
961             event.attendees = attendeeFindId->second;
962         }
963     }
964 }
965 
966 std::string EventIdsToString(const std::vector<int> &ids) {
967     if (ids.empty()) {
968         return "";
969     }
970     return std::accumulate(std::next(ids.begin()), ids.end(), std::to_string(ids[0]),
971         [](const std::string& a, int b) {
972             std::stringstream ss;
973             ss << a << ", " << b;
974             return ss.str();
975         }
976     );
977 }
978 
979 int ResultSetToMultiReminders(std::vector<Event> &events, DataShareResultSetPtr &resultSet)
980 {
981     if (!resultSet) {
982         LOG_ERROR("resultSet is null");
983         return -1;
984     }
985     int rowCount = 0;
986     resultSet->GetRowCount(rowCount);
987     LOG_INFO("GetRowCount is %{public}d", rowCount);
988     if (rowCount <= 0) {
989         return -1;
990     }
991     auto err = resultSet->GoToFirstRow();
992     if (err != DataShare::E_OK) {
993         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
994         return -1;
995     }
996     std::map<int, std::vector<int>> remindersMap;
997     do {
998         int minutes = 0;
999         int eventId = 0;
1000         GetValue(resultSet, "minutes", minutes);
1001         GetValue(resultSet, "event_id", eventId);
1002         auto eventFindId = remindersMap.find(eventId);
1003         if (eventFindId == remindersMap.end()) {
1004             remindersMap.insert(std::pair<int, std::vector<int>>(eventId, {minutes}));
1005         } else {
1006             eventFindId->second.emplace_back(minutes);
1007         }
1008     } while (resultSet->GoToNextRow() == DataShare::E_OK);
1009     if (remindersMap.size() == 0) {
1010         LOG_ERROR("reminders has no value");
1011         return -1;
1012     }
1013     for (auto &event : events) {
1014         const auto id = event.id;
1015         if (!id) {
1016             LOG_ERROR("event id is null");
1017             continue;
1018         }
1019         auto eventFindId = remindersMap.find(id.value());
1020         if (eventFindId != remindersMap.end()) {
1021             event.reminderTime = eventFindId->second;
1022         }
1023     }
1024     return 0;
1025 }
1026 
1027 void ResultSetToConfig(CalendarConfig &config, DataShareResultSetPtr &resultSet)
1028 {
1029     int rowCount = 0;
1030     resultSet->GetRowCount(rowCount);
1031     LOG_INFO("GetRowCount is %{public}d", rowCount);
1032     auto err = resultSet->GoToFirstRow();
1033     if (err != DataShare::E_OK) {
1034         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
1035     }
1036     do {
1037         int enableReminder = 0;
1038         std::int64_t color = 0;
1039         GetValue(resultSet, "canReminder", enableReminder);
1040         GetValue(resultSet, "calendar_color", color);
1041         config.enableReminder = static_cast<bool>(enableReminder);
1042         LOG_INFO("enableReminder is %{public}d", enableReminder);
1043         config.color = color;
1044     } while (resultSet->GoToNextRow() == DataShare::E_OK);
1045 }
1046 
1047 bool IsValidHexString(const std::string& colorStr)
1048 {
1049     if (colorStr.empty()) {
1050         return false;
1051     }
1052     for (char ch : colorStr) {
1053         if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
1054             continue;
1055         }
1056         return false;
1057     }
1058     return true;
1059 }
1060 
1061 bool ColorParse(const std::string& colorStr, variant<string, int64_t>& colorValue)
1062 {
1063     if (colorStr.empty()) {
1064         LOG_ERROR("color string is empty");
1065         return false;
1066     }
1067 
1068     if (colorStr[0] != '#') { // start with '#'
1069         LOG_ERROR("color string not start with #");
1070         return false;
1071     }
1072 
1073     const int rgbLen = 7;
1074     const int argbLen = 9;
1075     if (colorStr.size() != rgbLen && colorStr.size() != argbLen) {
1076         LOG_ERROR("color string length is not 7 or 9");
1077         return false;
1078     }
1079 
1080     std::string colorStrSub = colorStr.substr(1);
1081     if (!IsValidHexString(colorStrSub)) {
1082         LOG_DEBUG("color string is not valid hex string");
1083         return false;
1084     }
1085 
1086     LOG_DEBUG("color string size is 7 or 9");
1087     try {
1088         colorValue.emplace<1>(std::stoll(colorStrSub, NULL, 16));  // 16 is convert hex string to number
1089     } catch (std::exception &ex) {
1090         LOG_ERROR("stoll fail %{public}s", ex.what());
1091         return false;
1092     }
1093     if (std::get_if<1>(&colorValue)) {
1094         LOG_DEBUG("colorStrSub -> colorValue colorValue:%{public}s", std::to_string(std::get<1>(colorValue)).c_str());
1095         return true;
1096     }
1097     LOG_DEBUG("color is null");
1098     return false;
1099 }
1100 
1101 void SetLocationFieldInfo(std::vector<string>& queryField)
1102 {
1103     queryField.emplace_back("eventLocation");
1104     queryField.emplace_back("location_longitude");
1105     queryField.emplace_back("location_latitude");
1106 }
1107 
1108 void SetServiceFieldInfo(std::vector<string>& queryField)
1109 {
1110     queryField.emplace_back("service_type");
1111     queryField.emplace_back("service_cp_bz_uri");
1112     queryField.emplace_back("service_description");
1113 }
1114 
1115 void FillFieldInfo(const std::string field, std::vector<string>& queryField, std::set<string>& resultSetField,
1116     const std::map<string, string> eventField)
1117 {
1118     if (field == "location") {
1119             SetLocationFieldInfo(queryField);
1120             resultSetField.insert(field);
1121             return;
1122         }
1123         if (field == "service") {
1124             SetServiceFieldInfo(queryField);
1125             resultSetField.insert(field);
1126             return;
1127         }
1128         if (field == "attendee") {
1129             resultSetField.insert(field);
1130             return;
1131         }
1132         if (field == "reminderTime") {
1133             resultSetField.insert(field);
1134             return;
1135         }
1136         if (field == "identifier") {
1137             queryField.emplace_back("identifier");
1138             resultSetField.insert(field);
1139             return;
1140         }
1141         if (field == "recurrenceRule") {
1142             queryField.emplace_back("rrule");
1143             queryField.emplace_back("exdate");
1144             resultSetField.insert(field);
1145             return;
1146         }
1147         if (field == "isLunar") {
1148             queryField.emplace_back("event_calendar_type");
1149             resultSetField.insert(field);
1150             return;
1151         }
1152         if (field == "instanceStartTime") {
1153             queryField.emplace_back("begin");
1154             resultSetField.insert(field);
1155             return;
1156         }
1157         if (field == "instanceEndTime") {
1158             queryField.emplace_back("end");
1159             resultSetField.insert(field);
1160             return;
1161         }
1162         queryField.emplace_back(eventField.at(field));
1163         resultSetField.insert(field);
1164 }
1165 
1166 void SetFieldInfo(const std::vector<string>& eventKey, std::vector<string>& queryField,
1167     std::set<string>& resultSetField, const std::map<string, string> eventField)
1168 {
1169     for (const auto& field : eventKey) {
1170         if (field == "id") {
1171             continue;
1172         }
1173         FillFieldInfo(field, queryField, resultSetField, eventField);
1174     }
1175 }
1176 
1177 void SetField(const std::vector<string>& eventKey, std::vector<string>& queryField, std::set<string>& resultSetField)
1178 {
1179     const std::map<string, string> eventField = { { "id", "_id" },
1180                                                   { "type", "important_event_type" },
1181                                                   { "title", "title" },
1182                                                   { "startTime", "dtstart" },
1183                                                   { "endTime", "dtend" },
1184                                                   { "isAllDay", "allDay" },
1185                                                   { "timeZone", "eventTimezone" },
1186                                                   { "description", "description" }};
1187     SetFieldInfo(eventKey, queryField, resultSetField, eventField);
1188 }
1189 }