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