commit 245d07ef5c12c253359232d2939b8c19ab3b7118
parent 63c41312dbeb32d617614d3ec255fc8cf7a90d93
Author: Yu-Jie Lin <livibetter@gmail.com>
Date: Sat, 17 Dec 2016 19:21:47 +0800
Adjust first day of week according to locale (#13)
Since there currently is no option parsing, this commit adjust the
calendar solely according to locale, therefore this won't be portable if
the system doesn't use glibc.
In the future, even the system doesn't use glibc, user can use options,
for examples, -s (Sunday) and -m (Monday), to at least override the
default first day of week (first_weekday), currently set to Monday.
The detail of calculating the first day of week from locale setting,
LC_TIME section, can be read in locale(5) (read NOTES section first),
and util-linux's cal.c [1] is a good example to read.
[1] https://git.kernel.org/cgit/utils/util-linux/util-linux.git/tree/misc-utils/cal.c?h=stable/v2.28#n298
Diffstat:
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/diary.c b/diary.c
@@ -6,6 +6,8 @@ struct tm today;
struct tm curs_date;
struct tm cal_start;
struct tm cal_end;
+// 0 = Sunday, 1 = Monday, ..., 6 = Saturday
+int first_weekday = 1;
#define DATE_FMT "%Y-%m-%d"
@@ -26,11 +28,11 @@ void setup_cal_timeframe()
cal_start.tm_mday = 1;
mktime(&cal_start);
- if (cal_start.tm_wday != 1) {
- // adjust start date to first Mon before 01.01
+ if (cal_start.tm_wday != first_weekday) {
+ // adjust start date to first_weekday before 01.01
cal_start.tm_year--;
cal_start.tm_mon = 11;
- cal_start.tm_mday = 31 - cal_start.tm_wday + 2;
+ cal_start.tm_mday = 31 - (cal_start.tm_wday - first_weekday) + 1;
mktime(&cal_start);
}
@@ -43,9 +45,9 @@ void setup_cal_timeframe()
void draw_wdays(WINDOW* head)
{
- char** wd;
- for (wd = (char**)WEEKDAYS; *wd; wd++) {
- waddstr(head, *wd);
+ int i;
+ for (i = first_weekday; i < first_weekday + 7; i++) {
+ waddstr(head, WEEKDAYS[i % 7]);
waddch(head, ' ');
}
wrefresh(head);
@@ -298,6 +300,22 @@ int main(int argc, char** argv) {
return 1;
}
+ {
+ // references: locale(5) and util-linux's cal.c
+ // get the base date, 8-digit integer (YYYYMMDD) returned as char *
+ unsigned long d = (uintptr_t) nl_langinfo(_NL_TIME_WEEK_1STDAY);
+ struct tm base = {
+ .tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = d % 100,
+ .tm_mon = (d / 100) % 100 - 1,
+ .tm_year = d / (100 * 100) - 1900
+ };
+ mktime(&base);
+ // first_weekday is base date's day of the week offset by (_NL_TIME_FIRST_WEEKDAY - 1)
+ first_weekday = (base.tm_wday + *nl_langinfo(_NL_TIME_FIRST_WEEKDAY) - 1) % 7;
+ }
setup_cal_timeframe();
initscr();
diff --git a/diary.h b/diary.h
@@ -9,13 +9,14 @@
#include <dirent.h>
#include <ncurses.h>
#include <locale.h>
+#include <langinfo.h>
#define YEAR_RANGE 1
#define CAL_WIDTH 21
#define ASIDE_WIDTH 4
#define MAX_MONTH_HEIGHT 6
-static const char* WEEKDAYS[] = {"Mo","Tu","We","Th","Fr","Sa","Su", NULL};
+static const char* WEEKDAYS[] = {"Su","Mo","Tu","We","Th","Fr","Sa"};
void setup_cal_timeframe();
void draw_wdays(WINDOW* head);