Merge pull request #2340 from LukashonakV/ISSUE_2331
time conversion between time zones
This commit is contained in:
commit
e9b29613b2
|
@ -34,11 +34,18 @@ class Clock final : public ALabel {
|
||||||
|
|
||||||
auto first_day_of_week() -> date::weekday;
|
auto first_day_of_week() -> date::weekday;
|
||||||
const date::time_zone* current_timezone();
|
const date::time_zone* current_timezone();
|
||||||
bool is_timezone_fixed();
|
auto timezones_text(std::chrono::system_clock::time_point now) -> std::string;
|
||||||
auto timezones_text(std::chrono::system_clock::time_point* now) -> std::string;
|
|
||||||
|
|
||||||
/*Calendar properties*/
|
/*Calendar properties*/
|
||||||
WeeksSide cldWPos_{WeeksSide::HIDDEN};
|
WeeksSide cldWPos_{WeeksSide::HIDDEN};
|
||||||
|
/*
|
||||||
|
0 - calendar.format.months
|
||||||
|
1 - calendar.format.weekdays
|
||||||
|
2 - calendar.format.days
|
||||||
|
3 - calendar.format.today
|
||||||
|
4 - calendar.format.weeks
|
||||||
|
5 - tooltip-format
|
||||||
|
*/
|
||||||
std::map<int, std::string const> fmtMap_;
|
std::map<int, std::string const> fmtMap_;
|
||||||
CldMode cldMode_{CldMode::MONTH};
|
CldMode cldMode_{CldMode::MONTH};
|
||||||
uint cldMonCols_{3}; // Count of the month in the row
|
uint cldMonCols_{3}; // Count of the month in the row
|
||||||
|
@ -52,8 +59,10 @@ class Clock final : public ALabel {
|
||||||
std::string cldMonCached_{};
|
std::string cldMonCached_{};
|
||||||
date::day cldBaseDay_{0};
|
date::day cldBaseDay_{0};
|
||||||
/*Calendar functions*/
|
/*Calendar functions*/
|
||||||
auto get_calendar(const date::zoned_seconds& now, const date::zoned_seconds& wtime)
|
auto get_calendar(const date::year_month_day& today,
|
||||||
-> std::string;
|
const date::year_month_day& ymd,
|
||||||
|
const date::time_zone* tz)
|
||||||
|
-> const std::string;
|
||||||
/*Clock actions*/
|
/*Clock actions*/
|
||||||
void cldModeSwitch();
|
void cldModeSwitch();
|
||||||
void cldShift_up();
|
void cldShift_up();
|
||||||
|
|
|
@ -17,15 +17,15 @@
|
||||||
|
|
||||||
waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
||||||
: ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true),
|
: ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true),
|
||||||
current_time_zone_idx_(0),
|
current_time_zone_idx_{0},
|
||||||
is_calendar_in_tooltip_(false),
|
is_calendar_in_tooltip_{false},
|
||||||
is_timezoned_list_in_tooltip_(false) {
|
is_timezoned_list_in_tooltip_{false} {
|
||||||
if (config_["timezones"].isArray() && !config_["timezones"].empty()) {
|
if (config_["timezones"].isArray() && !config_["timezones"].empty()) {
|
||||||
for (const auto& zone_name : config_["timezones"]) {
|
for (const auto& zone_name : config_["timezones"]) {
|
||||||
if (!zone_name.isString()) continue;
|
if (!zone_name.isString()) continue;
|
||||||
if (zone_name.asString().empty())
|
if (zone_name.asString().empty())
|
||||||
// nullptr means that local time should be shown
|
// local time should be shown
|
||||||
time_zones_.push_back(nullptr);
|
time_zones_.push_back(date::current_zone());
|
||||||
else
|
else
|
||||||
try {
|
try {
|
||||||
time_zones_.push_back(date::locate_zone(zone_name.asString()));
|
time_zones_.push_back(date::locate_zone(zone_name.asString()));
|
||||||
|
@ -35,8 +35,7 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
||||||
}
|
}
|
||||||
} else if (config_["timezone"].isString()) {
|
} else if (config_["timezone"].isString()) {
|
||||||
if (config_["timezone"].asString().empty())
|
if (config_["timezone"].asString().empty())
|
||||||
// nullptr means that local time should be shown
|
time_zones_.push_back(date::current_zone());
|
||||||
time_zones_.push_back(nullptr);
|
|
||||||
else
|
else
|
||||||
try {
|
try {
|
||||||
time_zones_.push_back(date::locate_zone(config_["timezone"].asString()));
|
time_zones_.push_back(date::locate_zone(config_["timezone"].asString()));
|
||||||
|
@ -47,21 +46,22 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
||||||
|
|
||||||
// If all timezones are parsed and no one is good
|
// If all timezones are parsed and no one is good
|
||||||
if (!time_zones_.size()) {
|
if (!time_zones_.size()) {
|
||||||
// nullptr means that local time should be shown
|
time_zones_.push_back(date::current_zone());
|
||||||
time_zones_.push_back(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a particular placeholder is present in the tooltip format, to know what to calculate
|
// Check if a particular placeholder is present in the tooltip format, to know what to calculate
|
||||||
// on update.
|
// on update.
|
||||||
if (config_["tooltip-format"].isString()) {
|
if (config_["tooltip-format"].isString()) {
|
||||||
std::string trimmed_format = config_["tooltip-format"].asString();
|
std::string trimmed_format{config_["tooltip-format"].asString()};
|
||||||
trimmed_format.erase(std::remove_if(trimmed_format.begin(), trimmed_format.end(),
|
trimmed_format.erase(std::remove_if(trimmed_format.begin(), trimmed_format.end(),
|
||||||
[](unsigned char x) { return std::isspace(x); }),
|
[](unsigned char x) { return std::isspace(x); }),
|
||||||
trimmed_format.end());
|
trimmed_format.end());
|
||||||
if (trimmed_format.find("{" + kCalendarPlaceholder + "}") != std::string::npos) {
|
fmtMap_.insert({5, trimmed_format});
|
||||||
|
|
||||||
|
if (fmtMap_[5].find("{" + kCalendarPlaceholder + "}") != std::string::npos) {
|
||||||
is_calendar_in_tooltip_ = true;
|
is_calendar_in_tooltip_ = true;
|
||||||
}
|
}
|
||||||
if (trimmed_format.find("{" + KTimezonedTimeListPlaceholder + "}") != std::string::npos) {
|
if (fmtMap_[5].find("{" + KTimezonedTimeListPlaceholder + "}") != std::string::npos) {
|
||||||
is_timezoned_list_in_tooltip_ = true;
|
is_timezoned_list_in_tooltip_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,53 +158,34 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
||||||
}
|
}
|
||||||
|
|
||||||
const date::time_zone* waybar::modules::Clock::current_timezone() {
|
const date::time_zone* waybar::modules::Clock::current_timezone() {
|
||||||
return is_timezone_fixed() ? time_zones_[current_time_zone_idx_] : date::current_zone();
|
return time_zones_[current_time_zone_idx_];
|
||||||
}
|
|
||||||
|
|
||||||
bool waybar::modules::Clock::is_timezone_fixed() {
|
|
||||||
return time_zones_[current_time_zone_idx_] != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Clock::update() -> void {
|
auto waybar::modules::Clock::update() -> void {
|
||||||
const auto* time_zone = current_timezone();
|
const auto* tz{current_timezone()};
|
||||||
auto now = std::chrono::system_clock::now();
|
const date::zoned_time now{
|
||||||
auto ztime = date::zoned_time{time_zone, date::floor<std::chrono::seconds>(now)};
|
tz, std::chrono::system_clock::now()}; // Define local time is based on provided time zone
|
||||||
|
const date::year_month_day today{
|
||||||
|
date::floor<date::days>(now.get_local_time())}; // Convert now to year_month_day
|
||||||
|
const date::year_month_day shiftedDay{today + cldCurrShift_}; // Shift today
|
||||||
|
// Define shift local time
|
||||||
|
const auto shiftedNow{date::make_zoned(
|
||||||
|
tz, date::local_days(shiftedDay) +
|
||||||
|
(now.get_local_time() - date::floor<date::days>(now.get_local_time())))};
|
||||||
|
|
||||||
auto shifted_date = date::year_month_day{date::floor<date::days>(now)} + cldCurrShift_;
|
label_.set_markup(fmt::format(locale_, fmt::runtime(format_), now));
|
||||||
if (cldCurrShift_.count()) {
|
|
||||||
shifted_date = date::year_month_day(shifted_date.year(), shifted_date.month(), date::day(1));
|
|
||||||
}
|
|
||||||
auto now_shifted = date::sys_days{shifted_date} + (now - date::floor<date::days>(now));
|
|
||||||
auto shifted_ztime = date::zoned_time{time_zone, date::floor<std::chrono::seconds>(now_shifted)};
|
|
||||||
|
|
||||||
std::string text{""};
|
|
||||||
if (!is_timezone_fixed()) {
|
|
||||||
// As date dep is not fully compatible, prefer fmt
|
|
||||||
tzset();
|
|
||||||
auto localtime = fmt::localtime(std::chrono::system_clock::to_time_t(now));
|
|
||||||
text = fmt::format(locale_, fmt::runtime(format_), localtime);
|
|
||||||
} else {
|
|
||||||
text = fmt::format(locale_, fmt::runtime(format_), ztime);
|
|
||||||
}
|
|
||||||
label_.set_markup(text);
|
|
||||||
|
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
if (config_["tooltip-format"].isString()) {
|
const std::string tz_text{(is_timezoned_list_in_tooltip_) ? timezones_text(now.get_sys_time())
|
||||||
std::string calendar_lines{""};
|
: ""};
|
||||||
std::string timezoned_time_lines{""};
|
const std::string cld_text{(is_calendar_in_tooltip_) ? get_calendar(today, shiftedDay, tz)
|
||||||
if (is_calendar_in_tooltip_) {
|
: ""};
|
||||||
calendar_lines = get_calendar(ztime, shifted_ztime);
|
|
||||||
}
|
const std::string text{fmt::format(locale_, fmt::runtime(fmtMap_[5]), shiftedNow,
|
||||||
if (is_timezoned_list_in_tooltip_) {
|
fmt::arg(KTimezonedTimeListPlaceholder.c_str(), tz_text),
|
||||||
timezoned_time_lines = timezones_text(&now);
|
fmt::arg(kCalendarPlaceholder.c_str(), cld_text))};
|
||||||
}
|
|
||||||
auto tooltip_format = config_["tooltip-format"].asString();
|
|
||||||
text = fmt::format(locale_, fmt::runtime(tooltip_format), shifted_ztime,
|
|
||||||
fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines),
|
|
||||||
fmt::arg(KTimezonedTimeListPlaceholder.c_str(), timezoned_time_lines));
|
|
||||||
label_.set_tooltip_markup(text);
|
label_.set_tooltip_markup(text);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Call parent update
|
// Call parent update
|
||||||
ALabel::update();
|
ALabel::update();
|
||||||
|
@ -219,15 +200,15 @@ auto waybar::modules::Clock::doAction(const std::string& name) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The number of weeks in calendar month layout plus 1 more for calendar titles
|
// The number of weeks in calendar month layout plus 1 more for calendar titles
|
||||||
unsigned cldRowsInMonth(date::year_month const ym, date::weekday const firstdow) {
|
const unsigned cldRowsInMonth(const date::year_month& ym, const date::weekday& firstdow) {
|
||||||
using namespace date;
|
using namespace date;
|
||||||
return static_cast<unsigned>(
|
return static_cast<unsigned>(
|
||||||
ceil<weeks>((weekday{ym / 1} - firstdow) + ((ym / last).day() - day{0})).count()) +
|
ceil<weeks>((weekday{ym / 1} - firstdow) + ((ym / last).day() - day{0})).count()) +
|
||||||
2;
|
2;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cldGetWeekForLine(date::year_month const ym, date::weekday const firstdow, unsigned const line)
|
auto cldGetWeekForLine(const date::year_month& ym, const date::weekday& firstdow,
|
||||||
-> const date::year_month_weekday {
|
unsigned const line) -> const date::year_month_weekday {
|
||||||
unsigned index = line - 2;
|
unsigned index = line - 2;
|
||||||
auto sd = date::sys_days{ym / 1};
|
auto sd = date::sys_days{ym / 1};
|
||||||
if (date::weekday{sd} == firstdow) ++index;
|
if (date::weekday{sd} == firstdow) ++index;
|
||||||
|
@ -235,8 +216,8 @@ auto cldGetWeekForLine(date::year_month const ym, date::weekday const firstdow,
|
||||||
return ymdw;
|
return ymdw;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto getCalendarLine(date::year_month_day const currDate, date::year_month const ym,
|
auto getCalendarLine(const date::year_month_day& currDate, const date::year_month ym,
|
||||||
unsigned const line, date::weekday const firstdow,
|
const unsigned line, const date::weekday& firstdow,
|
||||||
const std::locale* const locale_) -> std::string {
|
const std::locale* const locale_) -> std::string {
|
||||||
using namespace date::literals;
|
using namespace date::literals;
|
||||||
std::ostringstream res;
|
std::ostringstream res;
|
||||||
|
@ -318,10 +299,9 @@ auto getCalendarLine(date::year_month_day const currDate, date::year_month const
|
||||||
return res.str();
|
return res.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Clock::get_calendar(const date::zoned_seconds& now,
|
auto waybar::modules::Clock::get_calendar(const date::year_month_day& today,
|
||||||
const date::zoned_seconds& wtime) -> std::string {
|
const date::year_month_day& ymd,
|
||||||
auto daypoint = date::floor<date::days>(wtime.get_local_time());
|
const date::time_zone* tz) -> const std::string {
|
||||||
const auto ymd{date::year_month_day{daypoint}};
|
|
||||||
const auto ym{ymd.year() / ymd.month()};
|
const auto ym{ymd.year() / ymd.month()};
|
||||||
const auto y{ymd.year()};
|
const auto y{ymd.year()};
|
||||||
const auto d{ymd.day()};
|
const auto d{ymd.day()};
|
||||||
|
@ -329,9 +309,6 @@ auto waybar::modules::Clock::get_calendar(const date::zoned_seconds& now,
|
||||||
const auto maxRows{12 / cldMonCols_};
|
const auto maxRows{12 / cldMonCols_};
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
std::ostringstream tmp;
|
std::ostringstream tmp;
|
||||||
// get currdate
|
|
||||||
daypoint = date::floor<date::days>(now.get_local_time());
|
|
||||||
const auto currDate{date::year_month_day{daypoint}};
|
|
||||||
|
|
||||||
if (cldMode_ == CldMode::YEAR) {
|
if (cldMode_ == CldMode::YEAR) {
|
||||||
if (y / date::month{1} / 1 == cldYearShift_)
|
if (y / date::month{1} / 1 == cldYearShift_)
|
||||||
|
@ -361,6 +338,7 @@ auto waybar::modules::Clock::get_calendar(const date::zoned_seconds& now,
|
||||||
else
|
else
|
||||||
m = 0u;
|
m = 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto row{0u}; row < maxRows; ++row) {
|
for (auto row{0u}; row < maxRows; ++row) {
|
||||||
const auto lines = *std::max_element(std::begin(ml) + (row * cldMonCols_),
|
const auto lines = *std::max_element(std::begin(ml) + (row * cldMonCols_),
|
||||||
std::begin(ml) + ((row + 1) * cldMonCols_));
|
std::begin(ml) + ((row + 1) * cldMonCols_));
|
||||||
|
@ -377,8 +355,9 @@ auto waybar::modules::Clock::get_calendar(const date::zoned_seconds& now,
|
||||||
if (line < ml[static_cast<unsigned>(ymTmp.month()) - 1u])
|
if (line < ml[static_cast<unsigned>(ymTmp.month()) - 1u])
|
||||||
os << fmt::format(fmt::runtime(fmtMap_[4]),
|
os << fmt::format(fmt::runtime(fmtMap_[4]),
|
||||||
(line == 2)
|
(line == 2)
|
||||||
? date::sys_days{ymTmp / 1}
|
? date::zoned_seconds{tz, date::local_days{ymTmp / 1}}
|
||||||
: date::sys_days{cldGetWeekForLine(ymTmp, firstdow, line)})
|
: date::zoned_seconds{tz, date::local_days{cldGetWeekForLine(
|
||||||
|
ymTmp, firstdow, line)}})
|
||||||
<< ' ';
|
<< ' ';
|
||||||
else
|
else
|
||||||
os << std::string(cldWnLen_, ' ');
|
os << std::string(cldWnLen_, ' ');
|
||||||
|
@ -387,7 +366,7 @@ auto waybar::modules::Clock::get_calendar(const date::zoned_seconds& now,
|
||||||
|
|
||||||
os << fmt::format(
|
os << fmt::format(
|
||||||
fmt::runtime((cldWPos_ != WeeksSide::LEFT || line == 0) ? "{:<{}}" : "{:>{}}"),
|
fmt::runtime((cldWPos_ != WeeksSide::LEFT || line == 0) ? "{:<{}}" : "{:>{}}"),
|
||||||
getCalendarLine(currDate, ymTmp, line, firstdow, &locale_),
|
getCalendarLine(today, ymTmp, line, firstdow, &locale_),
|
||||||
(cldMonColLen_ + ((line < 2) ? cldWnLen_ : 0)));
|
(cldMonColLen_ + ((line < 2) ? cldWnLen_ : 0)));
|
||||||
|
|
||||||
// Week numbers on the right
|
// Week numbers on the right
|
||||||
|
@ -397,8 +376,9 @@ auto waybar::modules::Clock::get_calendar(const date::zoned_seconds& now,
|
||||||
os << ' '
|
os << ' '
|
||||||
<< fmt::format(fmt::runtime(fmtMap_[4]),
|
<< fmt::format(fmt::runtime(fmtMap_[4]),
|
||||||
(line == 2)
|
(line == 2)
|
||||||
? date::sys_days{ymTmp / 1}
|
? date::zoned_seconds{tz, date::local_days{ymTmp / 1}}
|
||||||
: date::sys_days{cldGetWeekForLine(ymTmp, firstdow, line)});
|
: date::zoned_seconds{tz, date::local_days{cldGetWeekForLine(
|
||||||
|
ymTmp, firstdow, line)}});
|
||||||
else
|
else
|
||||||
os << std::string(cldWnLen_, ' ');
|
os << std::string(cldWnLen_, ' ');
|
||||||
}
|
}
|
||||||
|
@ -421,7 +401,7 @@ auto waybar::modules::Clock::get_calendar(const date::zoned_seconds& now,
|
||||||
os << fmt::format( // Apply days format
|
os << fmt::format( // Apply days format
|
||||||
fmt::runtime(fmt::format(fmt::runtime(fmtMap_[2]), tmp.str())),
|
fmt::runtime(fmt::format(fmt::runtime(fmtMap_[2]), tmp.str())),
|
||||||
// Apply today format
|
// Apply today format
|
||||||
fmt::arg("today", fmt::format(fmt::runtime(fmtMap_[3]), date::format("%e", ymd.day()))));
|
fmt::arg("today", fmt::format(fmt::runtime(fmtMap_[3]), date::format("%e", d))));
|
||||||
|
|
||||||
if (cldMode_ == CldMode::YEAR)
|
if (cldMode_ == CldMode::YEAR)
|
||||||
cldYearCached_ = os.str();
|
cldYearCached_ = os.str();
|
||||||
|
@ -457,7 +437,7 @@ void waybar::modules::Clock::tz_down() {
|
||||||
current_time_zone_idx_ = current_time_zone_idx_ == 0 ? nr_zones - 1 : current_time_zone_idx_ - 1;
|
current_time_zone_idx_ = current_time_zone_idx_ == 0 ? nr_zones - 1 : current_time_zone_idx_ - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Clock::timezones_text(std::chrono::system_clock::time_point* now)
|
auto waybar::modules::Clock::timezones_text(std::chrono::system_clock::time_point now)
|
||||||
-> std::string {
|
-> std::string {
|
||||||
if (time_zones_.size() == 1) {
|
if (time_zones_.size() == 1) {
|
||||||
return "";
|
return "";
|
||||||
|
@ -471,7 +451,7 @@ auto waybar::modules::Clock::timezones_text(std::chrono::system_clock::time_poin
|
||||||
if (!timezone) {
|
if (!timezone) {
|
||||||
timezone = date::current_zone();
|
timezone = date::current_zone();
|
||||||
}
|
}
|
||||||
auto ztime = date::zoned_time{timezone, date::floor<std::chrono::seconds>(*now)};
|
auto ztime = date::zoned_time{timezone, date::floor<std::chrono::seconds>(now)};
|
||||||
os << fmt::format(locale_, fmt::runtime(format_), ztime) << '\n';
|
os << fmt::format(locale_, fmt::runtime(format_), ztime) << '\n';
|
||||||
}
|
}
|
||||||
return os.str();
|
return os.str();
|
||||||
|
|
Loading…
Reference in New Issue