1С как то интересно определяет номер недели в году, просто берет количество недель, в то время как существует стандарт ISO 8601 и соответствующий ему межгосударственный стандарт ГОСТ ИСО 8601-2001 "ПРЕДСТАВЛЕНИЕ ДАТ И ВРЕМЕНИ".
По данному стандарту, первой неделей года является та неделя, на которую попадает первый четверг данного года. То есть в 2012 году первый четверг года попадает на 5 января. Значит 1 неделя 2012 года начинается со 2 января 2012 года. 1 января 2012 попадает на последнюю неделю 2011 года (для 2011 года - неделя под номером 52). Все это может приводить к доволе интересным результатам: год может содержать 52 или 53 недели. 29, 30, 31 декабря могут относиться к первой неделе следующего года (в случае попадания 1 января следующего года на четверг). Также может случиться наоборот, что 1, 2, и 3 января могут относиться к последней недели прошлого года (52 или 53 неделя в зависимости от года).
Итак, для чего 1С так считает - для самой себя или я что-то ни так понимаю?
Торговцы требуют корректного номера недели.
Например 14 по 20 мая НеделяГода() возвращает 21, а на календаре 20
Это что разные понятия?
Более корректным будет такой код, т.к. в указанном ГОСТ-е также сказано, что первой неделей считается та, в которой содержится 04 января.
Функция глНомерНеделиГода(_дата) Экспорт
ЧетвертоеЯнваря = НачГода(_дата) + 3;
НачалоПервойНедели = НачНедели(ЧетвертоеЯнваря);
Если _дата < НачалоПервойНедели Тогда
// дата принадлежит последней неделе прошлого года.
Возврат глНомерНеделиГода(Дата(ДатаГод(_дата)-1, 12, 31));
Иначе
// получаем разницу дат в неделях.
КоличествоНедель = Цел((НачНедели(_дата) - НачалоПервойНедели)/7);
Возврат 1 + КоличествоНедель;
КонецЕсли;
КонецФункции // глНомерНеделиГода()
т.к. в указанном ГОСТ-е также сказано, что первой неделей считается та, в которой содержится 04 января.
Это где такое сказано?
Вот дословно:
текст ISO
ISO 8601:2004
2.2.10
calendar week number ordinal number which identifies a calendar week within its calendar year according to the rule that the first calendar week of a year is that one which includes the first Thursday of that year and that the last calendar week of a calendar year is the week immediately preceding the first calendar week of the next calendar year
(с) https://www.iso.org/obp/ui/#iso:std:iso:8601:ed-3:v1:en
first Thursday - это первый четверг, а не четвертое число.
Функция должна быть такая:
Функция НеделяГодаПоISO8601(Знач Дата, Год=Неопределено) Экспорт
Если ДеньНедели(НачалоГода(Дата)) <= 4 тогда //если первая неделя года начинается до четверга, т.е. в ней есть четверг
//значит год начинается с первой недели
Год = Год(Дата);
Возврат НеделяГода(Дата);
Иначе
//год начинается с последней недели прошлого года
Год = Год(Дата) - 1;
Возврат НеделяГодаПоISO8601(НачалоГода(Дата)-1);
КонецЕсли;
КонецФункции
(7) Fox-trot, у вас год может начаться с 53 недели и закончиться 53 неделей.
Вы можете забыть об этом и сгруппировать по номеру недели, и получите неправильные данные.
Параметр Год - это напоминание о таком подводном камне.
Когда будете вызывать мою функцию, то увидите этот параметр и вспомните.
Функция НеделяГодаПоISO8601(Знач Дата, Год=Неопределено) Экспорт
Если ДеньНедели(НачалоГода(Дата)) <= 4 тогда //если первая неделя года начинается до четверга, т.е. в ней есть четверг
//значит год начинается с первой недели
Год = Год(Дата);
Неделя = НеделяГода(Дата);
Возврат Неделя;
Иначе
//год начинается с последней недели прошлого года
Неделя = НеделяГода(Дата)-1;
Если Неделя = 0 тогда //если это до первой недели года
Неделя = НеделяГодаПоISO8601(НачалоГода(Дата)-1, Год); //значит это последняя неделя прошлого года
Иначе
Год = Год(Дата);
КонецЕсли;
КонецЕсли;
Возврат Неделя;
КонецФункции
(6)Собственно эти параметры равнозначны. Если в неделе есть четверг, то в ней как минимум 4 дня, т.е. даже если четверг - 1 число, то воскресенье - 4, так что в той неделе, где есть четверг, всегда будет и 4 число
Сегодня устранял неправильный расчет номер недели в году в запросе.
Для решения задачи использовал следствие из стандарта ISO 8601 - неделя, в которой 1 января это понедельник, вторник, среда или четверг.
Согласно рекомендациям международного стандарта ISO 8601 (пункт 2.2.10), первой неделей года считается неделя, содержащая первый четверг года, что эквивалентно следующим выражениям:
1) неделя, содержащая 4 января;
2) неделя, в которой 1 января это понедельник, вторник, среда или четверг;
3) неделя, которая содержит как минимум четыре дня нового года.
Источник https://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D0%B4%D0%B5%D0%BB%D1%8F#Календарная_неделя_и_её_нумерация
Код:
ВЫБРАТЬ
ВЫБОР
КОГДА ДЕНЬНЕДЕЛИ(НАЧАЛОПЕРИОДА(&Дата, ГОД)) < 5
ТОГДА НЕДЕЛЯ(&Дата)
ИНАЧЕ ВЫБОР
КОГДА НЕДЕЛЯ(&Дата) = 1
ТОГДА 53
ИНАЧЕ НЕДЕЛЯ(&Дата) - 1
КОНЕЦ
КОНЕЦ КАК НомерНеделиПоISO8601
Показать
И функция приобретает вид:
Функция НеделяГода_ISO8601(Дата)
Если ДеньНедели(НачалоГода(Дата)) < 5 Тогда
Результат = НеделяГода(Дата);
ИначеЕсли НеделяГода(Дата) = 1 Тогда
Результат = 53;
Иначе
Результат = НеделяГода(Дата) - 1;
КонецЕсли;
Возврат Результат;
КонецФункции
Показать
Возможно, это решение будет полезно не только мне. Делюсь с Вами.
ВЫБРАТЬ
ВЫБОР
КОГДА ДЕНЬНЕДЕЛИ(НАЧАЛОПЕРИОДА(&Дата, ГОД)) < 5
ТОГДА НЕДЕЛЯ(&Дата)
ИНАЧЕ ВЫБОР
КОГДА НЕДЕЛЯ(&Дата) = 1
ТОГДА 53
ИНАЧЕ НЕДЕЛЯ(&Дата) - 1
КОНЕЦ
КОНЕЦ КАК НомерНеделиПоISO8601
Все прекрасно, только номер предыдущего года не всегда 53. Может и 52 быть.
Доработал немного, для тех кто ищет как определить номер недели в запросе
ВЫБРАТЬ
ВЫБОР
КОГДА ДЕНЬНЕДЕЛИ(НАЧАЛОПЕРИОДА(&Дата, ГОД)) < 5
ТОГДА НЕДЕЛЯ(&Дата)
ИНАЧЕ ВЫБОР
КОГДА НЕДЕЛЯ(&Дата) = 1
ТОГДА ВЫБОР
КОГДА ДЕНЬНЕДЕЛИ(ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&Дата, ГОД), СЕКУНДА, -1)) < 5
ТОГДА НЕДЕЛЯ(ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&Дата, ГОД), СЕКУНДА, -1))
ИНАЧЕ НЕДЕЛЯ(ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&Дата, ГОД), СЕКУНДА, -1))-1
КОНЕЦ
ИНАЧЕ НЕДЕЛЯ(&Дата) - 1
КОНЕЦ
КОНЕЦ КАК НомерНеделиПоISO8601
В представленных решениях неделя(понедельника 31-12-2018) = 53, а неделя(01-01-2019) = 1. Т.е. 53-я неделя 2018 года содержит 1 день?
Мне пользователи говорят, что 31-12-2018 это уже 1ая неделя 2019-го года...
Функция НеделяГода_ISO8601(Дата)
Если ДеньНедели(НачалоГода(Дата)) < 5 Тогда
Результат = НеделяГода(Дата);
ИначеЕсли НеделяГода(Дата) = 1 Тогда
Результат = 52;
Если ДеньНедели(НачалоГода(Дата)) = 5 Тогда
Результат = 53;
КонецЕсли;
Иначе
Результат = НеделяГода(Дата) - 1;
КонецЕсли;
Возврат Результат;
КонецФункции