diff options
author | Pádraig Brady | 2009-03-04 11:07:29 +0100 |
---|---|---|
committer | Karel Zak | 2009-03-10 13:01:39 +0100 |
commit | 0a9bead039d3d5c1445d94b9f439e8b1d08b4003 (patch) | |
tree | 40131ad25b3a7a2ae235bc3ef60b048893f2ec8d /misc-utils/cal.c | |
parent | renice: add -n option for compatibility with POSIX (diff) | |
download | kernel-qcow2-util-linux-0a9bead039d3d5c1445d94b9f439e8b1d08b4003.tar.gz kernel-qcow2-util-linux-0a9bead039d3d5c1445d94b9f439e8b1d08b4003.tar.xz kernel-qcow2-util-linux-0a9bead039d3d5c1445d94b9f439e8b1d08b4003.zip |
cal: determine the first day of week from the locale
Previously it defaulted to Sunday rather than using
the value from the locale. Lauri Nurmi <lanurmi@iki.fi>
provided the detailed argument for this change while
Samuel Thibault <samuel.thibault@ens-lyon.org> provided
the information on how to read the first day of the week
from the locale correctly.
[kzak@redhat.com: - fix "cast from pointer to integer",
nl_langinfo(_NL_TIME_WEEK_1STDAY) call)]
Signed-off-by: Pádraig Brady <P@draigBrady.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'misc-utils/cal.c')
-rw-r--r-- | misc-utils/cal.c | 65 |
1 files changed, 39 insertions, 26 deletions
diff --git a/misc-utils/cal.c b/misc-utils/cal.c index 82603b1b0..753cc24c4 100644 --- a/misc-utils/cal.c +++ b/misc-utils/cal.c @@ -205,9 +205,9 @@ int sep1752[MAXDAYS] = { /* utf-8 can have up to 6 bytes per char; and an extra byte for ending \0 */ char day_headings[WEEK_LEN*6+1]; -/* week1stday = 1 => " M Tu W Th F S S " */ +/* weekstart = 1 => " M Tu W Th F S S " */ char j_day_headings[J_WEEK_LEN*6+1]; -/* week1stday = 1 => " M Tu W Th F S S " */ +/* weekstart = 1 => " M Tu W Th F S S " */ const char *full_month[12]; /* leap year -- account for gregorian reformation in 1752 */ @@ -227,8 +227,8 @@ const char *full_month[12]; #define leap_years_since_year_1(yr) \ ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr)) -/* 0 => sunday (default), 1 => monday */ -int week1stday=0; +/* 0 => sunday, 1 => monday */ +int weekstart=0; int julian; #define TODAY_FLAG 0x400 /* flag day for highlighting */ @@ -285,26 +285,39 @@ main(int argc, char **argv) { } #endif -#if 0 /* setting week1stday is against man page */ /* - * What *is* the first day of the week? Note that glibc does not - * provide any information today, it (almost) always answers Monday. - * Sunday is the Jewish and Christian tradition. - * Sometimes an answer is built into the language: - * German calls Wednesday "Mittwoch", so starts at Sunday. - * Portuguese calls Monday "segunda-feira", so starts at Sunday. - * Russian calls Friday "pyatnitsa", so starts at Monday. - * ISO 8601 decided to start at Monday. - * - * The traditional Unix cal utility starts at Sunday. - * We start at Sunday and have an option -m for starting at Monday. - * - * At some future time this may become -s for Sunday, -m for Monday, - * no option for glibc-determined locale-dependent version. + * The traditional Unix cal utility starts the week at Sunday, + * while ISO 8601 starts at Monday. We read the start day from + * the locale database, which can be overridden with the + * -s (Sunday) or -m (Monday) options. */ #ifdef HAVE_LANGINFO_H - week1stday = (int)(nl_langinfo(_NL_TIME_FIRST_WEEKDAY))[0]; -#endif + /* + * You need to use 2 locale variables to get the first day of the week. + * This is needed to support first_weekday=2 and first_workday=1 for + * the rare case where working days span across 2 weeks. + * This shell script shows the combinations and calculations involved: + + for LANG in en_US ru_RU fr_FR csb_PL POSIX; do + printf "%s:\t%s + %s -1 = " $LANG $(locale week-1stday first_weekday) + date -d"$(locale week-1stday) +$(($(locale first_weekday)-1))day" +%w + done + + en_US: 19971130 + 1 -1 = 0 #0 = sunday + ru_RU: 19971130 + 2 -1 = 1 + fr_FR: 19971201 + 1 -1 = 1 + csb_PL: 19971201 + 2 -1 = 2 + POSIX: 19971201 + 7 -1 = 0 + */ + { + int wfd; + union { unsigned int word; char *string; } val; + val.string = nl_langinfo(_NL_TIME_WEEK_1STDAY); + + wfd = val.word; + wfd = day_in_week(wfd % 100, (wfd / 100) % 100, wfd / (100 * 100)); + weekstart = (wfd + *nl_langinfo(_NL_TIME_FIRST_WEEKDAY) - 1) % 7; + } #endif yflag = 0; @@ -317,10 +330,10 @@ main(int argc, char **argv) { num_months = 3; break; case 's': - week1stday = 0; /* default */ + weekstart = 0; /* default */ break; case 'm': - week1stday = 1; + weekstart = 1; break; case 'j': julian = 1; @@ -403,7 +416,7 @@ void headers_init(void) for(i = 0 ; i < 7 ; i++ ) { ssize_t space_left; - wd = (i + week1stday) % 7; + wd = (i + weekstart) % 7; if (i) strcat(cur_dh++, " "); @@ -618,7 +631,7 @@ day_array(int day, int month, int year, int *days) { if (month == 9 && year == 1752) { d_sep1752 = julian ? j_sep1752 : sep1752; - memcpy(days, d_sep1752 + week1stday, MAXDAYS * sizeof(int)); + memcpy(days, d_sep1752 + weekstart, MAXDAYS * sizeof(int)); for (dm=0; dm<MAXDAYS; dm++) if (j_sep1752[dm] == day) days[dm] |= TODAY_FLAG; @@ -626,7 +639,7 @@ day_array(int day, int month, int year, int *days) { } memcpy(days, empty, MAXDAYS * sizeof(int)); dm = days_in_month[leap_year(year)][month]; - dw = (day_in_week(1, month, year) - week1stday + 7) % 7; + dw = (day_in_week(1, month, year) - weekstart + 7) % 7; julday = day_in_year(1, month, year); daynum = julian ? julday : 1; while (dm--) { |