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