M image/user/db/settings_v2_002.sql => image/user/db/settings_v2_002.sql +2 -1
@@ 36,5 36,6 @@ INSERT OR IGNORE INTO settings_tab (path, value) VALUES
('\EventManager\\br_auto_mode', '0'),
('\EventManager\\br_level', '50.0f'),
('keypad_light_state', '0'),
- ('gs_current_timezone', '');
+ ('gs_current_timezone_name', ''),
+ ('gs_current_timezone_rules', '');
M module-apps/application-settings-new/windows/ChangeTimeZone.cpp => module-apps/application-settings-new/windows/ChangeTimeZone.cpp +52 -5
@@ 2,20 2,67 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "ChangeTimeZone.hpp"
+#include "OptionSetting.hpp"
-#include <application-settings-new/ApplicationSettings.hpp>
+#include <time/TimeZone.hpp>
+#include <service-time/service-time/TimeMessage.hpp>
+#include <service-time/Constants.hpp>
+#include <service-time/api/TimeSettingsApi.hpp>
namespace gui
{
-
- ChangeTimeZone::ChangeTimeZone(app::Application *app) : BaseSettingsWindow(app, window::name::change_date_and_time)
+ ChangeTimeZone::ChangeTimeZone(app::Application *app)
+ : BaseSettingsWindow(app, window::name::change_date_and_time),
+ timeZonesList(utils::time::getAvailableTimeZonesWithOffset())
{
setTitle(utils::translate("app_settings_date_and_time_time_zone"));
}
- std::list<Option> ChangeTimeZone::buildOptionsList()
+ void ChangeTimeZone::onBeforeShow(ShowMode mode, SwitchData *data)
+ {
+ selectedTimeZone = stm::api::getCurrentTimezoneName();
+ refreshOptionsList(setTimeZoneIndex());
+ }
+
+ [[nodiscard]] auto ChangeTimeZone::buildOptionsList() -> std::list<gui::Option>
+ {
+ std::list<gui::Option> options;
+
+ for (const auto &zone : timeZonesList) {
+ options.emplace_back(std::make_unique<gui::option::OptionSettings>(
+ zone,
+ [=](const gui::Item &item) {
+ application->bus.sendUnicast(
+ std::make_shared<stm::message::SetTimezoneRequest>(extractTimeZoneName(zone)),
+ service::name::service_time);
+ return true;
+ },
+ nullptr,
+ this,
+ selectedTimeZone == extractTimeZoneName(zone) ? gui::option::SettingRightItem::Checked
+ : gui::option::SettingRightItem::Disabled));
+ }
+
+ return options;
+ }
+
+ [[nodiscard]] auto ChangeTimeZone::setTimeZoneIndex() -> unsigned int
+ {
+ unsigned int zoneIndex = 0;
+ if (selectedTimeZone.empty()) {
+ selectedTimeZone.assign(utils::time::defaultTimeZoneName);
+ }
+ for (zoneIndex = 0; zoneIndex < timeZonesList.size(); ++zoneIndex) {
+ if (selectedTimeZone == extractTimeZoneName(timeZonesList[zoneIndex])) {
+ break;
+ }
+ }
+ return zoneIndex;
+ }
+
+ [[nodiscard]] auto ChangeTimeZone::extractTimeZoneName(const std::string &name) const noexcept -> std::string
{
- return {};
+ return name.substr(utils::time::timeZoneNameOffset);
}
} // namespace gui
M module-apps/application-settings-new/windows/ChangeTimeZone.hpp => module-apps/application-settings-new/windows/ChangeTimeZone.hpp +15 -2
@@ 1,6 1,11 @@
-#pragma once
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
#include "BaseSettingsWindow.hpp"
+#include <application-settings-new/ApplicationSettings.hpp>
+#include <Option.hpp>
namespace gui
{
@@ 9,6 14,14 @@ namespace gui
{
public:
explicit ChangeTimeZone(app::Application *app);
- auto buildOptionsList() -> std::list<Option> override;
+
+ protected:
+ [[nodiscard]] auto buildOptionsList() -> std::list<Option> override;
+ void onBeforeShow(ShowMode mode, SwitchData *data) override;
+ [[nodiscard]] auto setTimeZoneIndex() -> unsigned int;
+ [[nodiscard]] auto extractTimeZoneName(const std::string &name) const noexcept -> std::string;
+
+ const std::vector<std::string> timeZonesList;
+ std::string selectedTimeZone;
};
} // namespace gui
M module-apps/apps-common/widgets/TimeWidget.cpp => module-apps/apps-common/widgets/TimeWidget.cpp +11 -3
@@ 9,6 9,7 @@
#include <time/time_date_validation.hpp>
#include "DateAndTimeStyle.hpp"
#include <module-apps/application-calendar/data/dateCommon.hpp>
+#include <time/TimeZone.hpp>
namespace gui
{
@@ 422,19 423,26 @@ namespace gui
if (!validateHour()) {
return false;
}
- auto hours = std::chrono::hours(LocalizedHoursToUtcHours(std::stoi(hourInput->getText().c_str())));
+ auto hours = std::chrono::hours(std::stoi(hourInput->getText().c_str()));
auto minutes = std::chrono::minutes(std::stoi(minuteInput->getText().c_str()));
+
if (!mode24H) {
hours = date::make24(hours, isPm(mode12hInput->getText()));
}
auto date = (dateItem != nullptr) ? TimePointFromYearMonthDay(dateItem->getChosenDate())
: TimePointFromYearMonthDay(TimePointToYearMonthDay(TimePointNow()));
+
+ TimePoint presetPointTime = date + hours + minutes;
+ auto timeZoneOffset =
+ utils::time::getTimeZoneOffset(stm::api::getCurrentTimezoneName(), TimePointToTimeT(presetPointTime));
+
if (type == Type::Start) {
- fromTillDate->from = date + hours + minutes;
+ fromTillDate->from = presetPointTime - timeZoneOffset;
}
else if (type == Type::End) {
- fromTillDate->till = date + hours + minutes;
+ fromTillDate->till = presetPointTime - timeZoneOffset;
}
+
return true;
}
M module-services/service-db/agents/settings/SystemSettings.hpp => module-services/service-db/agents/settings/SystemSettings.hpp +2 -1
@@ 21,7 21,8 @@ namespace settings
constexpr inline auto eulaAccepted = "gs_eula_accepted";
constexpr inline auto osCurrentVersion = "gs_os_current_version";
constexpr inline auto osUpdateVersion = "gs_os_update_version";
- constexpr inline auto currentTimezone = "gs_current_timezone";
+ constexpr inline auto currentTimezoneName = "gs_current_timezone_name";
+ constexpr inline auto currentTimezoneRules = "gs_current_timezone_rules";
} // namespace SystemProperties
namespace Bluetooth
{
M module-services/service-time/ServiceTime.cpp => module-services/service-time/ServiceTime.cpp +40 -16
@@ 20,6 20,7 @@
#include <service-cellular/ServiceCellular.hpp>
#include <time/time_constants.hpp>
#include <time/time_conversion_factory.hpp>
+#include <time/TimeZone.hpp>
#include <service-evtmgr/Constants.hpp>
#include <service-db/service-db/Settings.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>
@@ 30,6 31,8 @@
namespace stm
{
+ constexpr auto automaticTimezoneName = "";
+
ServiceTime::ServiceTime() : sys::Service(service::name::service_time, "", StackDepth), calendarEvents(this)
{
LOG_INFO("[ServiceTime] Initializing");
@@ 158,6 161,12 @@ namespace stm
connect(typeid(stm::message::SetTimezoneRequest),
[&](sys::Message *request) -> sys::MessagePointer { return handleSetTimezoneRequest(request); });
+
+ connect(typeid(stm::message::TimeChangeRequestMessage), [&](sys::Message *request) -> sys::MessagePointer {
+ auto message = static_cast<stm::message::TimeChangeRequestMessage *>(request);
+ timeManager->handleTimeChangeRequest(message->getTime());
+ return std::make_shared<sys::ResponseMessage>();
+ });
}
auto ServiceTime::handleSetAutomaticDateAndTimeRequest(sys::Message *request)
@@ 217,10 226,16 @@ namespace stm
auto ServiceTime::handleSetTimezoneRequest(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>
{
auto message = static_cast<stm::message::SetTimezoneRequest *>(request);
+ auto timeZoneName = message->getTimezoneName();
+ auto timeZoneRules = utils::time::getTimeZoneRules(timeZoneName);
+
+ timeManager->handleTimezoneChangeRequest(timeZoneRules);
+ settings->setValue(settings::SystemProperties::currentTimezoneName, timeZoneName);
+ stm::internal::StaticData::get().setTimezoneName(timeZoneName);
+
+ settings->setValue(settings::SystemProperties::currentTimezoneRules, timeZoneRules);
+ stm::internal::StaticData::get().setTimezoneRules(timeZoneRules);
- timeManager->handleTimezoneChangeRequest(message->getTimezone());
- settings->setValue(settings::SystemProperties::currentTimezone, message->getTimezone());
- stm::internal::StaticData::get().setTimezone(message->getTimezone());
return std::shared_ptr<sys::ResponseMessage>();
}
@@ 228,18 243,24 @@ namespace stm
-> std::shared_ptr<sys::ResponseMessage>
{
auto message = static_cast<CellularTimeNotificationMessage *>(request);
- auto timezone = TimezoneHandler(std::chrono::duration_cast<std::chrono::minutes>(
- std::chrono::seconds{message->getTimeZoneOffset().value()}))
- .getTimezone();
+ auto timezoneRules = TimezoneHandler(std::chrono::duration_cast<std::chrono::minutes>(
+ std::chrono::seconds{message->getTimeZoneOffset().value()}))
+ .getTimezone();
if (stm::api::isAutomaticDateAndTime()) {
- timeManager->handleCellularTimeUpdate(message->getTime().value(), timezone);
- settings->setValue(settings::SystemProperties::currentTimezone, timezone);
- stm::internal::StaticData::get().setTimezone(timezone);
+ timeManager->handleCellularTimeUpdate(message->getTime().value(), timezoneRules);
+ settings->setValue(settings::SystemProperties::currentTimezoneRules, timezoneRules);
+ stm::internal::StaticData::get().setTimezoneRules(timezoneRules);
+
+ settings->setValue(settings::SystemProperties::currentTimezoneName, automaticTimezoneName);
+ stm::internal::StaticData::get().setTimezoneName(automaticTimezoneName);
}
else if (stm::api::isAutomaticTimezone()) {
- timeManager->handleTimezoneChangeRequest(timezone);
- settings->setValue(settings::SystemProperties::currentTimezone, timezone);
- stm::internal::StaticData::get().setTimezone(timezone);
+ timeManager->handleTimezoneChangeRequest(timezoneRules);
+ settings->setValue(settings::SystemProperties::currentTimezoneRules, timezoneRules);
+ stm::internal::StaticData::get().setTimezoneRules(timezoneRules);
+
+ settings->setValue(settings::SystemProperties::currentTimezoneName, automaticTimezoneName);
+ stm::internal::StaticData::get().setTimezoneName(automaticTimezoneName);
}
return std::make_shared<sys::ResponseMessage>();
@@ 261,10 282,13 @@ namespace stm
if (timeFormat != std::nullopt) {
stm::internal::StaticData::get().setTimeFormat(timeFormat.value());
}
- auto timezone =
- settings->getValue(settings::SystemProperties::currentTimezone, settings::SettingsScope::AppLocal);
- stm::internal::StaticData::get().setTimezone(timezone);
- timeManager->handleTimezoneChangeRequest(timezone);
+ auto timezoneName =
+ settings->getValue(settings::SystemProperties::currentTimezoneName, settings::SettingsScope::AppLocal);
+ stm::internal::StaticData::get().setTimezoneName(timezoneName);
+ auto timezoneRules =
+ settings->getValue(settings::SystemProperties::currentTimezoneRules, settings::SettingsScope::AppLocal);
+ stm::internal::StaticData::get().setTimezoneRules(timezoneRules);
+ timeManager->handleTimezoneChangeRequest(timezoneRules);
}
} /* namespace stm */
M module-services/service-time/TimeManager.cpp => module-services/service-time/TimeManager.cpp +2 -2
@@ 17,7 17,7 @@ void TimeManager::handleTimeChangeRequest(const time_t &time)
rtcCommand->setTime(time);
}
-void TimeManager::handleTimezoneChangeRequest(const std::string &timezone)
+void TimeManager::handleTimezoneChangeRequest(const std::string &timezoneRules)
{
- rtcCommand->setTimezone(timezone);
+ rtcCommand->setTimezone(timezoneRules);
}
M module-services/service-time/api/TimeSettingsApi.cpp => module-services/service-time/api/TimeSettingsApi.cpp +7 -3
@@ 31,8 31,12 @@ namespace stm::api
{
return stm::internal::StaticData::get().getTimeFormat() == utils::time::Locale::TimeFormat::FormatTime12H;
}
- const std::string getCurrentTimezone()
+ const std::string getCurrentTimezoneName()
{
- return stm::internal::StaticData::get().getCurrentTimezone();
+ return stm::internal::StaticData::get().getCurrentTimezoneName();
}
-} // namespace stm::api>
\ No newline at end of file
+ const std::string getCurrentTimezoneRules()
+ {
+ return stm::internal::StaticData::get().getCurrentTimezoneRules();
+ }
+} // namespace stm::api
M module-services/service-time/api/TimeSettingsApi.hpp => module-services/service-time/api/TimeSettingsApi.hpp +7 -2
@@ 34,7 34,12 @@ namespace stm::api
bool isTimeFormat12h();
/**
* Gets value corresponded to current timezone setting stored in DB
- * @return current timezone
+ * @return current timezone name
*/
- const std::string getCurrentTimezone();
+ const std::string getCurrentTimezoneName();
+ /**
+ * Gets value corresponded to current timezone setting stored in DB
+ * @return current timezone rules
+ */
+ const std::string getCurrentTimezoneRules();
} // namespace stm::api
M module-services/service-time/internal/StaticData.cpp => module-services/service-time/internal/StaticData.cpp +14 -5
@@ 51,13 51,22 @@ namespace stm::internal
{
return timeFormat;
}
- void StaticData::setTimezone(const std::string &newTimezone)
+ void StaticData::setTimezoneName(const std::string &newTimezone)
{
- timezone = newTimezone;
+ timezoneName = newTimezone;
}
- std::string StaticData::getCurrentTimezone() const
+ std::string StaticData::getCurrentTimezoneName() const
{
- return timezone;
+ return timezoneName;
}
-} // namespace stm::internal>
\ No newline at end of file
+ void StaticData::setTimezoneRules(const std::string &newTimezone)
+ {
+ timezoneRules = newTimezone;
+ }
+ std::string StaticData::getCurrentTimezoneRules() const
+ {
+ return timezoneRules;
+ }
+
+} // namespace stm::internal
M module-services/service-time/internal/StaticData.hpp => module-services/service-time/internal/StaticData.hpp +17 -6
@@ 17,7 17,8 @@ namespace stm::internal
bool isAutomaticTimezoneOn = false;
utils::time::Locale::DateFormat dateFormat = utils::time::Locale::DateFormat::DD_MM_YYYY;
utils::time::Locale::TimeFormat timeFormat = utils::time::Locale::TimeFormat::FormatTime12H;
- std::string timezone;
+ std::string timezoneName;
+ std::string timezoneRules;
StaticData() = default;
@@ 70,14 71,24 @@ namespace stm::internal
*/
[[nodiscard]] utils::time::Locale::TimeFormat getTimeFormat() const noexcept;
/**
- * Sets value corresponded to current Timezone setting
+ * Sets value corresponded to current Timezone name setting
* @param timezone new timezone to set
*/
- void setTimezone(const std::string &newTimezone);
+ void setTimezoneName(const std::string &newTimezone);
/**
- * Gets value corresponded to current Timezone setting
+ * Gets value corresponded to current Timezone name setting
* @retrun actual timezone setting
*/
- [[nodiscard]] std::string getCurrentTimezone() const;
+ [[nodiscard]] std::string getCurrentTimezoneName() const;
+ /**
+ * Sets value corresponded to current Timezone rules setting
+ * @param timezone new timezone to set
+ */
+ void setTimezoneRules(const std::string &newTimezone);
+ /**
+ * Gets value corresponded to current Timezone rules setting
+ * @retrun actual timezone setting
+ */
+ [[nodiscard]] std::string getCurrentTimezoneRules() const;
};
-} // namespace stm::internal>
\ No newline at end of file
+} // namespace stm::internal
M module-services/service-time/service-time/TimeManager.hpp => module-services/service-time/service-time/TimeManager.hpp +2 -2
@@ 31,9 31,9 @@ class TimeManager
void handleTimeChangeRequest(const time_t &time);
/**
* Handles timezone change request
- * @param timezone formatted timezone string
+ * @param timezoneRules formatted timezone rules string
*/
- void handleTimezoneChangeRequest(const std::string &timezone);
+ void handleTimezoneChangeRequest(const std::string &timezoneRules);
private:
std::unique_ptr<RTCCommandInterface> rtcCommand;
M module-services/service-time/service-time/TimeMessage.hpp => module-services/service-time/service-time/TimeMessage.hpp +3 -3
@@ 186,10 186,10 @@ namespace stm::message
class SetTimezoneRequest : public sys::DataMessage
{
public:
- explicit SetTimezoneRequest(const std::string &timezoneRules)
- : sys::DataMessage(MessageType::MessageTypeUninitialized), timezone(timezoneRules)
+ explicit SetTimezoneRequest(const std::string &timezoneName)
+ : sys::DataMessage(MessageType::MessageTypeUninitialized), timezone(timezoneName)
{}
- auto getTimezone() const -> std::string
+ auto getTimezoneName() const -> std::string
{
return timezone;
}
M module-utils/time/test/unittest_TimeZone.cpp => module-utils/time/test/unittest_TimeZone.cpp +44 -12
@@ 4,16 4,38 @@
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include <time/TimeZone.hpp>
+#include <chrono>
TEST_CASE("TimeZone parser")
{
+ struct tm summerTime_tm;
+ summerTime_tm.tm_year = 121;
+ summerTime_tm.tm_mon = 5;
+ summerTime_tm.tm_mday = 20;
+ summerTime_tm.tm_hour = 12;
+ summerTime_tm.tm_min = 0;
+ summerTime_tm.tm_sec = 0;
+
+ struct tm winterTime_tm;
+ winterTime_tm.tm_year = 121;
+ winterTime_tm.tm_mon = 12;
+ winterTime_tm.tm_mday = 25;
+ winterTime_tm.tm_hour = 12;
+ winterTime_tm.tm_min = 0;
+ winterTime_tm.tm_sec = 0;
+
+ time_t summerTime = mktime(&summerTime_tm);
+ time_t winterTime = mktime(&winterTime_tm);
+
SECTION("Checking the time zone rules for Warsaw")
{
std::string zone{"Warsaw"};
auto rules = utils::time::getTimeZoneRules(zone);
- auto offset = utils::time::getTimeZoneOffset(zone);
+ auto summerOffset = utils::time::getTimeZoneOffset(zone, summerTime);
+ auto winterOffset = utils::time::getTimeZoneOffset(zone, winterTime);
- REQUIRE(offset == 4);
+ REQUIRE(summerOffset == std::chrono::hours(2));
+ REQUIRE(winterOffset == std::chrono::hours(1));
REQUIRE(rules.size() != 0);
}
@@ 21,9 43,11 @@ TEST_CASE("TimeZone parser")
{
std::string zone{"London"};
auto rules = utils::time::getTimeZoneRules(zone);
- auto offset = utils::time::getTimeZoneOffset(zone);
+ auto summerOffset = utils::time::getTimeZoneOffset(zone, summerTime);
+ auto winterOffset = utils::time::getTimeZoneOffset(zone, winterTime);
- REQUIRE(offset == 0);
+ REQUIRE(summerOffset == std::chrono::hours(1));
+ REQUIRE(winterOffset == std::chrono::hours(0));
REQUIRE(rules.size() != 0);
}
@@ 31,9 55,11 @@ TEST_CASE("TimeZone parser")
{
std::string zone{"New York"};
auto rules = utils::time::getTimeZoneRules(zone);
- auto offset = utils::time::getTimeZoneOffset(zone);
+ auto summerOffset = utils::time::getTimeZoneOffset(zone, summerTime);
+ auto winterOffset = utils::time::getTimeZoneOffset(zone, winterTime);
- REQUIRE(offset == -20);
+ REQUIRE(summerOffset == std::chrono::hours(-4));
+ REQUIRE(winterOffset == std::chrono::hours(-5));
REQUIRE(rules.size() != 0);
}
@@ 41,9 67,11 @@ TEST_CASE("TimeZone parser")
{
std::string zone{"Tehran"};
auto rules = utils::time::getTimeZoneRules(zone);
- auto offset = utils::time::getTimeZoneOffset(zone);
+ auto summerOffset = utils::time::getTimeZoneOffset(zone, summerTime);
+ auto winterOffset = utils::time::getTimeZoneOffset(zone, winterTime);
- REQUIRE(offset == 14);
+ REQUIRE(summerOffset == std::chrono::hours(4) + std::chrono::minutes(30));
+ REQUIRE(winterOffset == std::chrono::hours(3) + std::chrono::minutes(30));
REQUIRE(rules.size() != 0);
}
@@ 51,9 79,11 @@ TEST_CASE("TimeZone parser")
{
std::string zone{"Auckland"};
auto rules = utils::time::getTimeZoneRules(zone);
- auto offset = utils::time::getTimeZoneOffset(zone);
+ auto summerOffset = utils::time::getTimeZoneOffset(zone, summerTime);
+ auto winterOffset = utils::time::getTimeZoneOffset(zone, winterTime);
- REQUIRE(offset == 48);
+ REQUIRE(summerOffset == std::chrono::hours(12));
+ REQUIRE(winterOffset == std::chrono::hours(13));
REQUIRE(rules.size() != 0);
}
@@ 61,9 91,11 @@ TEST_CASE("TimeZone parser")
{
std::string zone{"unknown"};
auto rules = utils::time::getTimeZoneRules(zone);
- auto offset = utils::time::getTimeZoneOffset(zone);
+ auto summerOffset = utils::time::getTimeZoneOffset(zone, summerTime);
+ auto winterOffset = utils::time::getTimeZoneOffset(zone, winterTime);
- REQUIRE(offset == 0);
+ REQUIRE(summerOffset == std::chrono::hours(0));
+ REQUIRE(winterOffset == std::chrono::hours(0));
REQUIRE(rules.size() == 0);
}
}
M module-utils/time/time/TimeZone.cpp => module-utils/time/time/TimeZone.cpp +62 -29
@@ 9,57 9,90 @@
namespace utils::time
{
+ constexpr uint16_t maxZoneToDisplayLength{27};
constexpr uint16_t maxZoneRuleLength{50};
constexpr uint8_t localTimeYearOffset{100};
- [[nodiscard]] auto getAvailableTimeZonesToDisplay() -> std::vector<std::string>
+ namespace
+ {
+ void copyTmToUdateTime(const tm *tm, udatetime_t *dt)
+ {
+ dt->date.year = tm->tm_year - 100;
+ dt->date.month = tm->tm_mon;
+ dt->date.dayofmonth = tm->tm_mday;
+ dt->date.dayofweek = tm->tm_wday;
+ dt->time.hour = tm->tm_hour;
+ dt->time.minute = tm->tm_min;
+ dt->time.second = tm->tm_sec;
+ }
+
+ void unpackDstRules(
+ urule_packed_t *packedRules, char *dstRules, int8_t tzOffset, uint8_t currYear, bool isEndRule)
+ {
+ switch (packedRules->on_dayofmonth) {
+ case 0: // the last day of week in month
+ [[fallthrough]];
+ case 1: // first day of week in month
+ snprintf(dstRules,
+ maxZoneRuleLength,
+ ",M%d.%d.%d/%d",
+ packedRules->in_month,
+ packedRules->on_dayofmonth == 0 ? 5 : packedRules->on_dayofmonth,
+ packedRules->on_dayofweek % 7,
+ packedRules->at_hours + (isEndRule ? 1 : 0) + (packedRules->at_is_local_time ? 0 : tzOffset));
+ break;
+ default: // The Julian day n (1 <= n <= 365)
+ snprintf(dstRules,
+ maxZoneRuleLength,
+ ",J%d/%d",
+ get_day_in_year(packedRules, currYear),
+ packedRules->at_hours + (isEndRule ? 1 : 0) + (packedRules->at_is_local_time ? 0 : tzOffset));
+ }
+ }
+ } // namespace
+
+ [[nodiscard]] auto getAvailableTimeZonesWithOffset() -> std::vector<std::string>
{
std::vector<std::string> timeZonesNames;
+ char zoneToDisplay[maxZoneToDisplayLength];
auto zonePointer = reinterpret_cast<const char *>(zone_names);
uzone_t zoneOut;
for (uint16_t zone = 0; zone < NUM_ZONE_NAMES; zone++) {
- unpack_zone(&zone_defns[get_next(&zonePointer)], zonePointer, &zoneOut);
- timeZonesNames.push_back(zoneOut.name);
+ auto pointerToZoneName = zonePointer;
+ unpack_zone(&zone_defns[get_next(&zonePointer)], pointerToZoneName, &zoneOut);
+
+ snprintf(zoneToDisplay,
+ maxZoneToDisplayLength,
+ "UTC%s%02d:%02d %s",
+ zoneOut.offset.hours > 0 ? "+" : "-",
+ std::abs(zoneOut.offset.hours),
+ zoneOut.offset.minutes,
+ zoneOut.name);
+ timeZonesNames.push_back(zoneToDisplay);
zonePointer++;
}
return timeZonesNames;
}
- [[nodiscard]] auto getTimeZoneOffset(const std::string &zoneName) -> std::int8_t
+ [[nodiscard]] auto getTimeZoneOffset(const std::string &zoneName, const time_t &time) -> std::chrono::seconds
{
uzone_t zoneOut;
- if (get_zone_by_name(const_cast<char *>(zoneName.c_str()), &zoneOut)) {
+ if (zoneName.empty() || get_zone_by_name(const_cast<char *>(zoneName.c_str()), &zoneOut)) {
LOG_ERROR("Zone %s not found", zoneName.c_str());
- return 0;
+ return std::chrono::seconds(0);
}
- return zoneOut.src->offset_inc_minutes;
- }
+ auto gmTime = gmtime(&time);
+ udatetime_t udateTime;
+ copyTmToUdateTime(gmTime, &udateTime);
- void unpackDstRules(urule_packed_t *packedRules, char *dstRules, int8_t tzOffset, uint8_t currYear, bool isEndRule)
- {
- switch (packedRules->on_dayofmonth) {
- case 0: // the last day of week in month
- [[fallthrough]];
- case 1: // first day of week in month
- snprintf(dstRules,
- maxZoneRuleLength,
- ",M%d.%d.%d/%d",
- packedRules->in_month,
- packedRules->on_dayofmonth == 0 ? 5 : packedRules->on_dayofmonth,
- packedRules->on_dayofweek % 7,
- packedRules->at_hours + (isEndRule ? 1 : 0) + (packedRules->at_is_local_time ? 0 : tzOffset));
- break;
- default: // The Julian day n (1 <= n <= 365)
- snprintf(dstRules,
- maxZoneRuleLength,
- ",J%d/%d",
- get_day_in_year(packedRules, currYear),
- packedRules->at_hours + (isEndRule ? 1 : 0) + (packedRules->at_is_local_time ? 0 : tzOffset));
- }
+ uoffset_t offset;
+ get_current_offset(&zoneOut, &udateTime, &offset);
+
+ return std::chrono::seconds(std::chrono::hours(offset.hours) + std::chrono::minutes(offset.minutes));
}
[[nodiscard]] auto getTimeZoneRules(const std::string &zoneName) -> std::string
M module-utils/time/time/TimeZone.hpp => module-utils/time/time/TimeZone.hpp +11 -6
@@ 5,21 5,26 @@
#include <string>
#include <vector>
+#include <chrono>
namespace utils::time
{
- /** @brief get all available TimeZones to display
+ constexpr uint8_t timeZoneNameOffset{10};
+ constexpr auto defaultTimeZoneName{"London"};
+
+ /** @brief get all available TimeZones with offsets
*
- * @return vector of string with TimeZones names
+ * @return vector of string with TimeZones names and offsets
*/
- [[nodiscard]] auto getAvailableTimeZonesToDisplay() -> std::vector<std::string>;
+ [[nodiscard]] auto getAvailableTimeZonesWithOffset() -> std::vector<std::string>;
- /** @brief get offset of TimeZone
+ /** @brief get offset of TimeZone include DST rules
*
* @param zoneName - name of TimeZone
- * @return offset hours and minutes with a sign in the interval of 15 minutes [6 => 1h 30 min]
+ * @param time - date and time for the offset
+ * @return offset in seconds with a sign
*/
- [[nodiscard]] auto getTimeZoneOffset(const std::string &zoneName) -> std::int8_t;
+ [[nodiscard]] auto getTimeZoneOffset(const std::string &zoneName, const time_t &time) -> std::chrono::seconds;
/** @brief get offset and DST rules of TimeZone
*