ISSUE#1877 Calendar week numbers
1. Let's do code simplier 2. Week format using regexp. Needs when user provide additional characters in format string and need to align week days according 3. Week format has got default formats: ":%U",":%V" 4. Week number is based on the first day of the week now. The output is the same as of date library now. 5. Avoiding of unnecessary operationspull/1882/head
parent
c5babb4c44
commit
57ad7f9536
|
@ -33,6 +33,8 @@ class Clock : public ALabel {
|
||||||
|
|
||||||
bool handleScroll(GdkEventScroll* e);
|
bool handleScroll(GdkEventScroll* e);
|
||||||
|
|
||||||
|
std::string weeks_format_;
|
||||||
|
int weeks_format_left_gaps{0};
|
||||||
auto calendar_text(const waybar_time& wtime) -> std::string;
|
auto calendar_text(const waybar_time& wtime) -> std::string;
|
||||||
auto weekdays_header(const date::weekday& first_dow, std::ostream& os) -> void;
|
auto weekdays_header(const date::weekday& first_dow, std::ostream& os) -> void;
|
||||||
auto first_day_of_week() -> date::weekday;
|
auto first_day_of_week() -> date::weekday;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <regex>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include "util/ustring_clen.hpp"
|
#include "util/ustring_clen.hpp"
|
||||||
|
@ -74,6 +75,13 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
||||||
locale_ = std::locale("");
|
locale_ = std::locale("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config_["format-calendar-weeks"].isString()) {
|
||||||
|
weeks_format_ = std::regex_replace(config_["format-calendar-weeks"].asString(), std::regex("\\{\\}"), (first_day_of_week() == date::Monday) ? "{:%V}" : "{:%U}");
|
||||||
|
weeks_format_left_gaps = std::regex_replace(weeks_format_, std::regex(".*<b>|</b>.*|\\{.?+\\}"), "").length();
|
||||||
|
} else {
|
||||||
|
weeks_format_ = "";
|
||||||
|
}
|
||||||
|
|
||||||
thread_ = [this] {
|
thread_ = [this] {
|
||||||
dp.emit();
|
dp.emit();
|
||||||
auto now = std::chrono::system_clock::now();
|
auto now = std::chrono::system_clock::now();
|
||||||
|
@ -180,70 +188,63 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str
|
||||||
? date::day{0}
|
? date::day{0}
|
||||||
: ymd.day()};
|
: ymd.day()};
|
||||||
const date::year_month ym{ymd.year(), ymd.month()};
|
const date::year_month ym{ymd.year(), ymd.month()};
|
||||||
const auto weeks_format{config_["format-calendar-weeks"].isString()
|
const auto first_dow = first_day_of_week();
|
||||||
? config_["format-calendar-weeks"].asString()
|
|
||||||
: ""};
|
|
||||||
|
|
||||||
std::stringstream os;
|
std::stringstream os;
|
||||||
|
|
||||||
const date::weekday first_week_day = first_day_of_week();
|
|
||||||
|
|
||||||
enum class WeeksPlacement {
|
enum class WeeksSide {
|
||||||
LEFT,
|
LEFT,
|
||||||
RIGHT,
|
RIGHT,
|
||||||
HIDDEN,
|
HIDDEN,
|
||||||
};
|
};
|
||||||
WeeksPlacement weeks_pos = WeeksPlacement::HIDDEN;
|
WeeksSide weeks_pos = WeeksSide::HIDDEN;
|
||||||
|
|
||||||
if (config_["calendar-weeks-pos"].isString()) {
|
if (config_["calendar-weeks-pos"].isString()) {
|
||||||
if (config_["calendar-weeks-pos"].asString() == "left") {
|
if (config_["calendar-weeks-pos"].asString() == "left") {
|
||||||
weeks_pos = WeeksPlacement::LEFT;
|
weeks_pos = WeeksSide::LEFT;
|
||||||
// Add paddings before the header
|
// Add paddings before the header
|
||||||
os << std::string(4, ' ');
|
os << std::string(3 + weeks_format_left_gaps, ' ');
|
||||||
} else if (config_["calendar-weeks-pos"].asString() == "right") {
|
} else if (config_["calendar-weeks-pos"].asString() == "right") {
|
||||||
weeks_pos = WeeksPlacement::RIGHT;
|
weeks_pos = WeeksSide::RIGHT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
weekdays_header(first_week_day, os);
|
weekdays_header(first_dow, os);
|
||||||
|
|
||||||
// First week prefixed with spaces if needed.
|
// First week day prefixed with spaces if needed.
|
||||||
auto first_month_day = date::weekday(ym / 1);
|
date::sys_days print_wd{ym/1};
|
||||||
int empty_days = (first_week_day - first_month_day).count() + 1;
|
auto wd{date::weekday{print_wd}};
|
||||||
date::sys_days last_week_day{static_cast<date::sys_days>(ym / 1) + date::days{7 - empty_days}};
|
auto empty_days = (wd - first_dow).count();
|
||||||
|
|
||||||
if (first_week_day == date::Monday) {
|
|
||||||
last_week_day -= date::days{1};
|
|
||||||
}
|
|
||||||
/* Print weeknumber on the left for the first row*/
|
/* Print weeknumber on the left for the first row*/
|
||||||
if (weeks_pos == WeeksPlacement::LEFT) {
|
if (weeks_pos == WeeksSide::LEFT) {
|
||||||
os << fmt::format(weeks_format, date::format("%U", last_week_day)) << ' ';
|
os << fmt::format(weeks_format_, print_wd) << ' ';
|
||||||
last_week_day += date::weeks{1};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty_days > 0) {
|
if (empty_days > 0) {
|
||||||
os << std::string(empty_days * 3 - 1, ' ');
|
os << std::string(empty_days * 3 - 1, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto last_day = (ym / date::literals::last).day();
|
const auto last_day = (ym / date::literals::last).day();
|
||||||
auto weekday = first_month_day;
|
|
||||||
for (auto d = date::day(1); d <= last_day; ++d, ++weekday) {
|
for (auto d{date::day{1}}; d <= last_day; ++d, ++wd) {
|
||||||
if (weekday != first_week_day) {
|
if (wd != first_dow) {
|
||||||
os << ' ';
|
os << ' ';
|
||||||
} else if (unsigned(d) != 1) {
|
} else if (unsigned(d)!= 1) {
|
||||||
last_week_day -= date::days{1};
|
if (weeks_pos == WeeksSide::RIGHT) {
|
||||||
if (weeks_pos == WeeksPlacement::RIGHT) {
|
os << ' ' << fmt::format(weeks_format_, print_wd);
|
||||||
os << ' ';
|
|
||||||
os << fmt::format(weeks_format, date::format("%U", last_week_day));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os << "\n";
|
os << '\n';
|
||||||
|
|
||||||
if (weeks_pos == WeeksPlacement::LEFT) {
|
print_wd = {ym/d};
|
||||||
os << fmt::format(weeks_format, date::format("%U", last_week_day));
|
|
||||||
os << ' ';
|
if (weeks_pos == WeeksSide::LEFT) {
|
||||||
|
os << fmt::format(weeks_format_, print_wd) << ' ';
|
||||||
}
|
}
|
||||||
last_week_day += date::weeks{1} + date::days{1};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d == curr_day) {
|
if (d == curr_day) {
|
||||||
if (config_["today-format"].isString()) {
|
if (config_["today-format"].isString()) {
|
||||||
auto today_format = config_["today-format"].asString();
|
auto today_format = config_["today-format"].asString();
|
||||||
|
@ -257,12 +258,13 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str
|
||||||
os << date::format("%e", d);
|
os << date::format("%e", d);
|
||||||
}
|
}
|
||||||
/*Print weeks on the right when the endings with spaces*/
|
/*Print weeks on the right when the endings with spaces*/
|
||||||
if (weeks_pos == WeeksPlacement::RIGHT && d == last_day) {
|
if (weeks_pos == WeeksSide::RIGHT && d == last_day) {
|
||||||
last_week_day -= date::days{1};
|
empty_days = 6 - (wd.c_encoding() - first_dow.c_encoding());
|
||||||
empty_days = 6 - (weekday - first_week_day).count();
|
if (empty_days > 0) {
|
||||||
os << std::string(empty_days * 3 + 1, ' ');
|
os << std::string(empty_days * 3, ' ');
|
||||||
os << fmt::format(weeks_format, date::format("%U", last_week_day));
|
}
|
||||||
last_week_day += date::days{1};
|
|
||||||
|
os << ' ' << fmt::format(weeks_format_, print_wd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +293,7 @@ auto waybar::modules::Clock::weekdays_header(const date::weekday& first_week_day
|
||||||
const std::string pad(2 - clen, ' ');
|
const std::string pad(2 - clen, ' ');
|
||||||
res << pad << wd_ustring;
|
res << pad << wd_ustring;
|
||||||
} while (++wd != first_week_day);
|
} while (++wd != first_week_day);
|
||||||
res << "\n";
|
res << '\n';
|
||||||
|
|
||||||
if (config_["format-calendar-weekdays"].isString()) {
|
if (config_["format-calendar-weekdays"].isString()) {
|
||||||
os << fmt::format(config_["format-calendar-weekdays"].asString(), res.str());
|
os << fmt::format(config_["format-calendar-weekdays"].asString(), res.str());
|
||||||
|
@ -315,7 +317,7 @@ auto waybar::modules::Clock::timezones_text(std::chrono::system_clock::time_poin
|
||||||
timezone = date::current_zone();
|
timezone = date::current_zone();
|
||||||
}
|
}
|
||||||
wtime = {locale_, date::make_zoned(timezone, date::floor<std::chrono::seconds>(*now))};
|
wtime = {locale_, date::make_zoned(timezone, date::floor<std::chrono::seconds>(*now))};
|
||||||
os << fmt::format(format_, wtime) << "\n";
|
os << fmt::format(format_, wtime) << '\n';
|
||||||
}
|
}
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue