алгоритм для расчета недели # от даты с настраиваемым началом недели? (для iCal)

Я могу найти только алгоритм получения ISO 8601 неделя (неделя начинается в понедельник).

Однако в спецификации iCal говорится

Неделя определяется как семидневный период, начинающийся в день недели, определенный как начало недели (см. WKST). Первая неделя календарного года - это первая неделя, которая содержит не менее четырех (4) дней в этом календарном году.

Следовательно, он сложнее, чем ISO 8601, поскольку начало недели может быть любым днем ​​недели.

Есть ли алгоритм для определения номера недели даты с настраиваемым днем ​​начала недели?

или ... есть ли в iCal4j функция, которая выполняет это? Определить неделю не по свиданию?

Спасибо!

p.s. Ограничение: я использую язык JVM, который не может расширять класс Java, но я могу вызывать методы Java или создавать экземпляры классов Java.


person Henry    schedule 25.01.2012    source источник
comment
И я полагаю, что jodatime - не лучший вариант, чем злоупотребление java.util.Calendar?   -  person Tetsujin no Oni    schedule 26.01.2012
comment
Номер недели iCal определяется так же, как номер недели ISO8601 по этой ссылке. Похоже, ваш вопрос рассматривается здесь: stackoverflow.com/q/1801907/93922   -  person Tetsujin no Oni    schedule 26.01.2012
comment
@TetsujinoOni не совсем. iCal использует переменную WKST, которая определяет, какой день является началом недели. Хотя по умолчанию это понедельник, как ISO8601, но это может быть любой день недели.   -  person Henry    schedule 26.01.2012
comment
Если взглянуть на JodaTime более подробно, я думаю, что настраиваемая хронология, настроенная для перебазирования с использованием вашего WKST, в сочетании с weekyear () и weekOfWeekyear () поможет вам добраться туда, куда вы собираетесь.   -  person Tetsujin no Oni    schedule 26.01.2012
comment
@TetsujinnoOni Я посмотрел на org.joda.time.chrono.ISOChronology, но не могу легко "перебазировать" его. Думаю, мне все еще нужно написать новый объект, расширяющий org.joda.time.chrono.BaseChronology, но я не могу написать новый объект, потому что я использую язык JVM, который не позволяет мне писать новый класс.   -  person Henry    schedule 26.01.2012
comment
давайте продолжим обсуждение в чате   -  person Tetsujin no Oni    schedule 26.01.2012
comment
нашел это: cflib.org/udf/customWeekNumber может работать, но не тестировал.   -  person Henry    schedule 26.01.2012


Ответы (2)


if (input_date < firstDateOfTheYear(WKST, year))
{
    return ((isLeapYear(year-1))?53:52);
}
else
{
    return ((dayOfYear(input_date) - firstDateOfTheYear(WKST, year).day)/7 + 1);
}

firstDateOfTheYear возвращает первую календарную дату с учетом начала недели (WKST) и года, например если WKST = четверг, год = 2012, возвращается 5 января.

dayOfYear возвращает последовательный числовой день года, например 1 февраля = 32

Пример №1: 18 января 2012 г., начало недели - понедельник.

  • dayOfYear (18 января 2012 г.) = 18
  • firstDateOfTheYear (понедельник, 2012 г.) = 2 января 2012 г.

(18 - 2) / 7 + 1 = 3 Ответ № недели. 3

Пример 2: 18 января 2012 г., начало недели - четверг.

  • dayOfYear (18 января 2012 г.) = 18
  • firstDateOfTheYear (четверг, 2012 г.) = 5 января 2012 г.

(18-5) / 7 + 1 = 2 Ответ № недели 2

Пример № 3: 1 января 2012 г., начало недели - понедельник.

  • firstDateOfTheYear (понедельник, 2012 г.) = 2 января 2012 г.
  • IsLeapYear (2012-1) = ложь

1 января 2012 г. ‹2 января 2012 г. Ответ Неделя № 52

person vkoo    schedule 26.01.2012
comment
1 января 2009 г., WKST = понедельник. Первый понедельник 2009 г. - 5-е число, но 1 января 2009 г. приходится на первую неделю, а не на последнюю неделю прошлого года. Этот алгоритм не работает. См. personal.ecu.edu/mccartyr/isowdcal.html. - person Henry; 26.01.2012
comment
Хорошая точка зрения! Это потому, что мое первое условие: «if (input_date‹ firstDateOfTheYear (WKST, year)) »слишком наивно. При этом не учтено ваше требование 4 дня или больше = неделя. Скорее всего, вам потребуется поставить другое условие, например, if firstDateOfTheYear.GetDay () ›4, тогда все даты до этого дня должны быть 1-й, а последующие недели - +1. Я уверен, что вы сможете понять, как уточнить псевдокод, соответствующий этой логике;) - person vkoo; 26.01.2012
comment
Это также делает пример № 2 недействительным. Ответом должна быть неделя №3, потому что до 5 января 2012 г. осталось 4 дня, которые следует рассматривать как неделю №1. - person vkoo; 26.01.2012

  1. Пусть daysInFirstWeek будет количеством дней в первой неделе года, приходящихся на январь. Неделя начинается в WKST день. (например, если 1 января - WKST день, верните 7)

  2. Установите dayOfYear на n-е дни года входной даты (например, 1 февраля = 32)

  3. Если dayOfYear меньше или равно daysInFirstWeek

    3.1. если daysInFirstWeek больше или равно 4, weekNo равно 1, переходите к шагу 5.

    3.2. Пусть daysInFirstWeekOfLastYear будет количеством дней в январе в первую неделю предыдущего года. Неделя начинается WKST день.

    3.3. если daysInFirstWeekOfLastYear равно 4 или прошлый год - високосный, а daysInFirstWeekOfLastYear - 5, weekNo - 53, иначе weekNo равно 52, переходите к шагу 5.

  4. Установите weekNo на ceiling((dayOfYear - daysInFirstWeek) / 7)

    4.1. если daysInFirstWeek больше или равно 4, увеличить weekNo на 1

    4.2. если daysInFirstWeek равно 53 и количество дней на первой неделе (начиная с WKST) января в году inputDate года + 1 больше или равно 4, установите weekNo на 1

  5. возврат weekNo

person Henry    schedule 26.01.2012
comment
Полагаю, что 4.2 должно быть: 4.2. если weekNo равно 53 и количество дней на первой неделе (начиная с WKST) января в год inputDate's year + 1 больше или равно 4, установите weekNo равным 1 - person BladeWise; 13.11.2013