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