1  /*
2   * Copyright (C) 2023-2025 Huawei Device Co., Ltd.
3   * Licensed under the Apache License, Version 2.0 (the "License");
4   * you may not use this file except in compliance with the License.
5   * You may obtain a copy of the License at
6   *
7   *     http://www.apache.org/licenses/LICENSE-2.0
8   *
9   * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  
16  #include "time_format_utils.h"
17  
18  #include <chrono>
19  #include <ctime>
20  #include <iomanip>
21  #include <iostream>
22  #include <regex>
23  #include <sstream>
24  #include <string>
25  
26  #include "media_log.h"
27  
28  namespace {
29  constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "TimeFormatUtils"};
30  }
31  
32  namespace OHOS {
33  namespace Media {
FormatDateTimeByTimeZone(const std::string & iso8601Str)34  std::string TimeFormatUtils::FormatDateTimeByTimeZone(const std::string &iso8601Str)
35  {
36      std::regex pattern(R"((\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(.\d{1,6})?(((\+|-)\d{4})|Z)?)");
37      std::smatch match;
38      if (!std::regex_match(iso8601Str, match, pattern)) {
39          return iso8601Str;  // not standard ISO8601 type string
40      }
41  
42      std::istringstream iss(iso8601Str);
43      std::tm tm;
44      if (!(iss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S"))) {
45          return iso8601Str;  // cant prase time
46      }
47  
48      // time zone
49      time_t tt = mktime(&tm);
50      if (tt == -1) {
51          return iso8601Str;
52      }
53      uint32_t length = iso8601Str.length();
54      long diffTime = 0;
55      if (iso8601Str.substr(length - 1, 1).compare("Z") != 0) {
56          char symbol = iso8601Str.at(length - 5);
57          if (symbol != '+' && symbol != '-') {
58              std::ostringstream oss;
59              oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
60              return oss.str();
61          }
62          int mins = std::stoi(iso8601Str.substr(length - 2, 2));
63          int hours = std::stoi(iso8601Str.substr(length - 4, 2));
64          long seconds = (hours * 60 + mins) * 60;
65          diffTime = symbol == '+' ? seconds : -seconds;
66      }
67  
68      // convert time to localtime
69      long timezone = 0;
70      std::tm *timeWithOffsetPtr = localtime(&tt);
71      if (timeWithOffsetPtr == nullptr) {
72          return "";
73      }
74      std::tm timeWithOffset = *timeWithOffsetPtr;
75      if (timeWithOffset.tm_gmtoff != 0) {
76          timezone = timeWithOffset.tm_gmtoff;
77      }
78      auto localTime =
79          std::chrono::system_clock::from_time_t(std::mktime(&tm)) + std::chrono::seconds(timezone - diffTime);
80      std::time_t localTimeT = std::chrono::system_clock::to_time_t(localTime);
81      std::tm *localTmPtr = std::localtime(&localTimeT);
82      if (localTmPtr == nullptr) {
83          return "";
84      }
85      std::tm localTm = *localTmPtr;
86      std::ostringstream oss;
87      oss << std::put_time(&localTm, "%Y-%m-%d %H:%M:%S");
88      return oss.str();
89  }
90  
FormatDataTimeByString(const std::string & dataTime)91  std::string TimeFormatUtils::FormatDataTimeByString(const std::string &dataTime)
92  {
93      if (dataTime.compare("") == 0) {
94          return dataTime;
95      }
96      std::string::size_type position = dataTime.find(" ");
97      std::string data = "";
98      std::string time = "";
99      if (position == dataTime.npos) {
100          data = dataTime;
101          if (data.find("-") == data.npos) {
102              data += "-01-01";
103          } else if (data.find_first_of("-") == data.find_last_of("-")) {
104              data += "-01";
105          }
106          time += " 00:00:00";
107      } else {
108          data = dataTime.substr(0, position);
109          time = dataTime.substr(position);
110          if (data.find("-") == data.npos) {
111              data += "-01-01";
112          } else if (data.find_first_of("-") == data.find_last_of("-")) {
113              data += "-01";
114          }
115          if (time.find(":") == data.npos) {
116              time += ":00:00";
117          } else if (time.find_first_of(":") == time.find_last_of(":")) {
118              time += ":00";
119          } else {
120              time = time.substr(0, time.find("."));
121          }
122      }
123      MEDIA_LOGD("FormatDataTimeByString is: %{public}s%{public}s", data.c_str(), time.c_str());
124      return data + time;
125  }
126  
ConvertTimestampToDatetime(const std::string & timestamp)127  std::string TimeFormatUtils::ConvertTimestampToDatetime(const std::string &timestamp)
128  {
129      if (timestamp.empty()) {
130          MEDIA_LOGE("datetime is empty, format failed");
131          return "";
132      }
133  
134      time_t ts = stoi(timestamp);
135      tm *pTime;
136      char date[maxDateTimeSize];
137      char time[maxDateTimeSize];
138      pTime = localtime(&ts);
139      if (pTime == nullptr) {
140          return "";
141      }
142      size_t sizeDateStr = strftime(date, maxDateTimeSize, "%Y-%m-%d", pTime);
143      size_t sizeTimeStr = strftime(time, maxDateTimeSize, "%H:%M:%S", pTime);
144      if (sizeDateStr != standardDateStrSize || sizeTimeStr != standardTimeStrSize) {
145          MEDIA_LOGE("datetime is invalid, format failed");
146          return "";
147      }
148  
149      return std::string(date) + " " + std::string(time);
150  }
151  }  // namespace Media
152  }  // namespace OHOS