Хм, и правда, числа сбиты. Я это не проверил.
Судя по первой части письма, приведенного раньше (
LC_TIME first_weekday locale consolidation), некоторые приложения предполагают, что неделя начинается с воскресенья. Также в nl_langinfo(3) написано примерно то же самое:
Код: Выделить всё
DAY_{1–7} (LC_TIME)
Return name of the n-th day of the week. [Warning: this
follows the US convention DAY_1 = Sunday, not the international
convention (ISO 8601) that Monday is the first day of the week.]
Те, если мы предположим, что cal тоже думает, что DAY_1 - это воскресенье, то сдвиг можно объяснить. Возьмем такую локаль
Код: Выделить всё
$ bash -c '( export LC_TIME=ru_R2.utf8; locale -k LC_TIME |grep "week\|day=" ; ~/tmp/t/first_week )'
abday="Пнд;Втр;Срд;Чтв;Птн;Сбт;Вск"
day="Понедельник;Вторник;Среда;Четверг;Пятница;Суббота;Воскресенье"
week-ndays=7
week-1stday=19971201
week-1stweek=4
first_weekday=1
first_workday=1
[LC_CTYPE=ru_RU.utf8;LC_NUMERIC=en_US.utf8;LC_TIME=ru_R2.utf8;LC_COLLATE=ru_R
U.utf8;LC_MONETARY=en_US.utf8;LC_MESSAGES=en_US.utf8;LC_PAPER=en_US.utf8;LC_NAME=
en_US.utf8;LC_ADDRESS=en_US.utf8;LC_TELEPHONE=en_US.utf8;LC_MEASUREMENT=en_US.utf
8;LC_IDENTIFICATION=en_US.utf8] week_1stday 1, first_weekday 1, english[first] Mon, days[first] Понедельник, strftime[first] Вторник
где first_week - вот
эта программа из ссылки в моем предыдущем посте. Попробуем запустить `ncal`, сказав ему, что первый день недели - воскресенье:
Код: Выделить всё
$ bash -c '( export LC_TIME=ru_R2.utf8; ncal -S 1970 )'
1970
Январь Февраль Март Апрель
Пн 4 11 18 25 1 8 15 22 1 8 15 22 29 5 12 19 26
Вт 5 12 19 26 2 9 16 23 2 9 16 23 30 6 13 20 27
Ср 6 13 20 27 3 10 17 24 3 10 17 24 31 7 14 21 28
Чт 7 14 21 28 4 11 18 25 4 11 18 25 1 8 15 22 29
Пт 1 8 15 22 29 5 12 19 26 5 12 19 26 2 9 16 23 30
Сб 2 9 16 23 30 6 13 20 27 6 13 20 27 3 10 17 24
Вс 3 10 17 24 31 7 14 21 28 7 14 21 28 4 11 18 25
Май Июнь Июль Август
Пн 3 10 17 24 31 7 14 21 28 5 12 19 26 2 9 16 23 30
Вт 4 11 18 25 1 8 15 22 29 6 13 20 27 3 10 17 24 31
Ср 5 12 19 26 2 9 16 23 30 7 14 21 28 4 11 18 25
Чт 6 13 20 27 3 10 17 24 1 8 15 22 29 5 12 19 26
Пт 7 14 21 28 4 11 18 25 2 9 16 23 30 6 13 20 27
Сб 1 8 15 22 29 5 12 19 26 3 10 17 24 31 7 14 21 28
Вс 2 9 16 23 30 6 13 20 27 4 11 18 25 1 8 15 22 29
Сентябрь Октябрь Ноябрь Декабрь
Пн 6 13 20 27 4 11 18 25 1 8 15 22 29 6 13 20 27
Вт 7 14 21 28 5 12 19 26 2 9 16 23 30 7 14 21 28
Ср 1 8 15 22 29 6 13 20 27 3 10 17 24 1 8 15 22 29
Чт 2 9 16 23 30 7 14 21 28 4 11 18 25 2 9 16 23 30
Пт 3 10 17 24 1 8 15 22 29 5 12 19 26 3 10 17 24 31
Сб 4 11 18 25 2 9 16 23 30 6 13 20 27 4 11 18 25
Вс 5 12 19 26 3 10 17 24 31 7 14 21 28 5 12 19 26
Получается, что дни недели расставлены также, как в day: те первый - понедельник, а не воскресенье. В то же время числа сдвинуты (1970-1-1 - четверг на самом деле). Другими словами, все было бы правильно, если бы в day первым было воскресенье.
Теперь попробуем сказать `ncal`, что первый день - понедельник:
Код: Выделить всё
$ bash -c '( export LC_TIME=ru_R2.utf8; ncal -M 1970 )'
1970
Январь Февраль Март Апрель
Вт 5 12 19 26 2 9 16 23 2 9 16 23 30 6 13 20 27
Ср 6 13 20 27 3 10 17 24 3 10 17 24 31 7 14 21 28
Чт 7 14 21 28 4 11 18 25 4 11 18 25 1 8 15 22 29
Пт 1 8 15 22 29 5 12 19 26 5 12 19 26 2 9 16 23 30
Сб 2 9 16 23 30 6 13 20 27 6 13 20 27 3 10 17 24
Вс 3 10 17 24 31 7 14 21 28 7 14 21 28 4 11 18 25
Пн 4 11 18 25 1 8 15 22 1 8 15 22 29 5 12 19 26
Май Июнь Июль Август
Вт 4 11 18 25 1 8 15 22 29 6 13 20 27 3 10 17 24 31
Ср 5 12 19 26 2 9 16 23 30 7 14 21 28 4 11 18 25
Чт 6 13 20 27 3 10 17 24 1 8 15 22 29 5 12 19 26
Пт 7 14 21 28 4 11 18 25 2 9 16 23 30 6 13 20 27
Сб 1 8 15 22 29 5 12 19 26 3 10 17 24 31 7 14 21 28
Вс 2 9 16 23 30 6 13 20 27 4 11 18 25 1 8 15 22 29
Пн 3 10 17 24 31 7 14 21 28 5 12 19 26 2 9 16 23 30
Сентябрь Октябрь Ноябрь Декабрь
Вт 7 14 21 28 5 12 19 26 2 9 16 23 30 7 14 21 28
Ср 1 8 15 22 29 6 13 20 27 3 10 17 24 1 8 15 22 29
Чт 2 9 16 23 30 7 14 21 28 4 11 18 25 2 9 16 23 30
Пт 3 10 17 24 1 8 15 22 29 5 12 19 26 3 10 17 24 31
Сб 4 11 18 25 2 9 16 23 30 6 13 20 27 4 11 18 25
Вс 5 12 19 26 3 10 17 24 31 7 14 21 28 5 12 19 26
Пн 6 13 20 27 4 11 18 25 1 8 15 22 29 6 13 20 27
Получается, что ncal сдвинул дни недели в day на 1. Числа остались сдвинутыми на 1. Другими словами, опять же, результат был бы правильным, если бы day начинался с воскресенья.
Итак, отсюда видно, что ncal предполагает, что, как и написано в nl_langinfo(3), первый день недели - это воскресенье. Теперь проверим, смотрит ли он на week-1stday:
Код: Выделить всё
$ bash -c '( export LC_TIME=ru_R2.utf8; ncal 1970 )'
1970
Январь Февраль Март Апрель
Вт 5 12 19 26 2 9 16 23 2 9 16 23 30 6 13 20 27
Ср 6 13 20 27 3 10 17 24 3 10 17 24 31 7 14 21 28
Чт 7 14 21 28 4 11 18 25 4 11 18 25 1 8 15 22 29
Пт 1 8 15 22 29 5 12 19 26 5 12 19 26 2 9 16 23 30
Сб 2 9 16 23 30 6 13 20 27 6 13 20 27 3 10 17 24
Вс 3 10 17 24 31 7 14 21 28 7 14 21 28 4 11 18 25
Пн 4 11 18 25 1 8 15 22 1 8 15 22 29 5 12 19 26
Май Июнь Июль Август
Вт 4 11 18 25 1 8 15 22 29 6 13 20 27 3 10 17 24 31
Ср 5 12 19 26 2 9 16 23 30 7 14 21 28 4 11 18 25
Чт 6 13 20 27 3 10 17 24 1 8 15 22 29 5 12 19 26
Пт 7 14 21 28 4 11 18 25 2 9 16 23 30 6 13 20 27
Сб 1 8 15 22 29 5 12 19 26 3 10 17 24 31 7 14 21 28
Вс 2 9 16 23 30 6 13 20 27 4 11 18 25 1 8 15 22 29
Пн 3 10 17 24 31 7 14 21 28 5 12 19 26 2 9 16 23 30
Сентябрь Октябрь Ноябрь Декабрь
Вт 7 14 21 28 5 12 19 26 2 9 16 23 30 7 14 21 28
Ср 1 8 15 22 29 6 13 20 27 3 10 17 24 1 8 15 22 29
Чт 2 9 16 23 30 7 14 21 28 4 11 18 25 2 9 16 23 30
Пт 3 10 17 24 1 8 15 22 29 5 12 19 26 3 10 17 24 31
Сб 4 11 18 25 2 9 16 23 30 6 13 20 27 4 11 18 25
Вс 5 12 19 26 3 10 17 24 31 7 14 21 28 5 12 19 26
Пн 6 13 20 27 4 11 18 25 1 8 15 22 29 6 13 20 27
те без указания 1-го дня недели результат совпадает с результатом с опцией '-M'. Те он использует week-1stday.
И теперь можно придумать фикс: первый день нужно сделать воскресеньем, как ncal и хочет. Но week-1stday поставить в понедельник. Те вот так:
Код: Выделить всё
day "<U0412><U043E><U0441><U043A><U0440><U0435><U0441><U0435><U043D><U044C><U0435>";/
"<U041F><U043E><U043D><U0435><U0434><U0435><U043B><U044C><U043D><U0438><U043A>";/
"<U0412><U0442><U043E><U0440><U043D><U0438><U043A>";/
"<U0421><U0440><U0435><U0434><U0430>";/
"<U0427><U0435><U0442><U0432><U0435><U0440><U0433>";/
"<U041F><U044F><U0442><U043D><U0438><U0446><U0430>";/
"<U0421><U0443><U0431><U0431><U043E><U0442><U0430>"
abday "<U0412><U0441><U043A>";/
"<U041F><U043D><U0434>";/
"<U0412><U0442><U0440>";/
"<U0421><U0440><U0434>";/
"<U0427><U0442><U0432>";/
"<U041F><U0442><U043D>";/
"<U0421><U0431><U0442>"
week 7;19971201;0
first_weekday 1
Тогда с одной стороны, cal сдвинет дни недели на 1, как он это делал с опцией '-M'. С другой стороны, его предположение DAY_1 = воскресенье будет правильно. Результат:
Код: Выделить всё
$ bash -c '( export LC_TIME=ru_R2.utf8; locale -k LC_TIME |grep "week\|day=" ; ~/tmp/t/first_week )'
abday="Вск;Пнд;Втр;Срд;Чтв;Птн;Сбт"
day="Воскресенье;Понедельник;Вторник;Среда;Четверг;Пятница;Суббота"
week-ndays=7
week-1stday=19971201
week-1stweek=0
first_weekday=1
first_workday=1
[LC_CTYPE=ru_RU.utf8;LC_NUMERIC=en_US.utf8;LC_TIME=ru_R2.utf8;LC_COLLATE=ru_R
U.utf8;LC_MONETARY=en_US.utf8;LC_MESSAGES=en_US.utf8;LC_PAPER=en_US.utf8;LC_NAME=
en_US.utf8;LC_ADDRESS=en_US.utf8;LC_TELEPHONE=en_US.utf8;LC_MEASUREMENT=en_US.utf
8;LC_IDENTIFICATION=en_US.utf8] week_1stday 1, first_weekday 1, english[first] Mon, days[first] Воскресенье, strftime[first] Понедельник
$ bash -c '( export LC_TIME=ru_R2.utf8; ncal 1970 )'
1970
Январь Февраль Март Апрель
Пн 5 12 19 26 2 9 16 23 2 9 16 23 30 6 13 20 27
Вт 6 13 20 27 3 10 17 24 3 10 17 24 31 7 14 21 28
Ср 7 14 21 28 4 11 18 25 4 11 18 25 1 8 15 22 29
Чт 1 8 15 22 29 5 12 19 26 5 12 19 26 2 9 16 23 30
Пт 2 9 16 23 30 6 13 20 27 6 13 20 27 3 10 17 24
Сб 3 10 17 24 31 7 14 21 28 7 14 21 28 4 11 18 25
Вс 4 11 18 25 1 8 15 22 1 8 15 22 29 5 12 19 26
Май Июнь Июль Август
Пн 4 11 18 25 1 8 15 22 29 6 13 20 27 3 10 17 24 31
Вт 5 12 19 26 2 9 16 23 30 7 14 21 28 4 11 18 25
Ср 6 13 20 27 3 10 17 24 1 8 15 22 29 5 12 19 26
Чт 7 14 21 28 4 11 18 25 2 9 16 23 30 6 13 20 27
Пт 1 8 15 22 29 5 12 19 26 3 10 17 24 31 7 14 21 28
Сб 2 9 16 23 30 6 13 20 27 4 11 18 25 1 8 15 22 29
Вс 3 10 17 24 31 7 14 21 28 5 12 19 26 2 9 16 23 30
Сентябрь Октябрь Ноябрь Декабрь
Пн 7 14 21 28 5 12 19 26 2 9 16 23 30 7 14 21 28
Вт 1 8 15 22 29 6 13 20 27 3 10 17 24 1 8 15 22 29
Ср 2 9 16 23 30 7 14 21 28 4 11 18 25 2 9 16 23 30
Чт 3 10 17 24 1 8 15 22 29 5 12 19 26 3 10 17 24 31
Пт 4 11 18 25 2 9 16 23 30 6 13 20 27 4 11 18 25
Сб 5 12 19 26 3 10 17 24 31 7 14 21 28 5 12 19 26
Вс 6 13 20 27 4 11 18 25 1 8 15 22 29 6 13 20 27
$ bash -c '( export LC_TIME=ru_R2.utf8; ncal )'
Июнь 2013
Пн 3 10 17 24
Вт 4 11 18 25
Ср 5 12 19 26
Чт 6 13 20 27
Пт 7 14 21 28
Сб 1 8 15 22 29
Вс 2 9 16 23 30
Обратите внимание, что strftime() теперь заработала, зато другая часть программы first_week, которая основывается на locale(5), теперь не работает:
Код: Выделить всё
[..]
LC_TIME
The definition starts with the string LC_TIME in the first column.
[..]
abday followed by a list of abbreviated weekday names. The list
starts with the first day of the week as specified by week
(Sunday by default).
day followed by a list of weekday names. The list starts with the
first day of the week as specified by week (Sunday by default).
[..]
week [..] Regarding the start of the week, 19971130 shall be used
for Sunday and 19971201 shall be used for Monday. Thus,
countries using 19971130 should have local Sunday name as the
first day in the day list, while countries using 19971201 should
have Monday translation as the first item in the day list.
Соответственно, какие программы такой фикс сломает, а какие починит (кроме cal) - я не знаю.