1 /*
2 * Copyright (c) 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 #include "zone_rules.h"
16
17 #include "i18n_hilog.h"
18 #include "unicode/tzrule.h"
19 #include "unicode/tztrans.h"
20 #include "unicode/gregocal.h"
21
22 namespace OHOS {
23 namespace Global {
24 namespace I18n {
ZoneRules(const std::string & tzid)25 ZoneRules::ZoneRules(const std::string &tzid)
26 {
27 this->tzId = tzid;
28 InitBasicTimeZone();
29 }
30
~ZoneRules()31 ZoneRules::~ZoneRules()
32 {
33 }
34
InitBasicTimeZone()35 void ZoneRules::InitBasicTimeZone()
36 {
37 if (tzId.empty()) {
38 HILOG_ERROR_I18N("ZoneRules::InitBasicTimeZone: param tzid is empty.");
39 return;
40 }
41 icu::UnicodeString unicodeZoneId(tzId.data(), tzId.length());
42 icu::TimeZone* icuTz = icu::TimeZone::createTimeZone(unicodeZoneId);
43 if (icuTz == nullptr) {
44 HILOG_ERROR_I18N("ZoneRules::InitBasicTimeZone: param tzid: %{public}s invalid.", tzId.c_str());
45 return;
46 }
47 icu::BasicTimeZone* btzPtr = static_cast<icu::BasicTimeZone*>(icuTz);
48 if (btzPtr == nullptr) {
49 HILOG_ERROR_I18N("ZoneRules::InitBasicTimeZone: static_cast icu::TimeZone failed.");
50 return;
51 }
52 this->btz = std::unique_ptr<icu::BasicTimeZone>(btzPtr);
53 if (btz == nullptr) {
54 HILOG_ERROR_I18N("ZoneRules::InitBasicTimeZone: btz is nullptr.");
55 }
56 }
57
NextTransition()58 std::unique_ptr<ZoneOffsetTransition> ZoneRules::NextTransition()
59 {
60 auto time = std::chrono::system_clock::now();
61 auto since_epoch = time.time_since_epoch();
62 auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(since_epoch);
63 UDate currentTime = static_cast<double>(millis.count());
64 return NextTransition(currentTime);
65 }
66
NextTransition(double date)67 std::unique_ptr<ZoneOffsetTransition> ZoneRules::NextTransition(double date)
68 {
69 if (btz == nullptr) {
70 HILOG_ERROR_I18N("ZoneRules::NextTransition: btz is nullptr.");
71 return std::make_unique<ZoneOffsetTransition>();
72 }
73 icu::TimeZoneTransition trans;
74 if (!btz->getNextTransition(date, false, trans)) {
75 HILOG_ERROR_I18N("ZoneRules::nextTransition: get next transition after %{public}s failed.",
76 std::to_string(date).c_str());
77 return std::make_unique<ZoneOffsetTransition>();
78 }
79 const icu::TimeZoneRule* from = trans.getFrom();
80 const icu::TimeZoneRule* to = trans.getTo();
81 if (from == nullptr || to == nullptr) {
82 return std::make_unique<ZoneOffsetTransition>();
83 }
84 double time = trans.getTime();
85 int32_t offsetBefore = from->getRawOffset() + from->getDSTSavings();
86 int32_t offsetAfter = to->getRawOffset() + to->getDSTSavings();
87 return std::make_unique<ZoneOffsetTransition>(time, offsetBefore, offsetAfter);
88 }
89 } // namespace I18n
90 } // namespace Global
91 } // namespace OHOS
92