рассчитать частоту на определенном диапазоне - PullRequest
2 голосов
/ 10 августа 2009

У меня есть математическая задача ... (на данный момент я решил ее, используя ручную итерацию, которая довольно медленная) ...

Например, если сотруднику платят еженедельно (это может быть раз в две недели / каждые 2 недели и ежемесячно) с определенной датой (назовем сотрудника, получающего оплату каждый вторник, а за месяц сотрудник оплачивается в определенную дату).

У меня есть диапазон дат с 10 августа 2009 г. по 31 декабря 2009 г. Теперь, как узнать, как часто работник получает оплату?

можно ли рассчитать это с помощью jodatime?

Пример прояснения этого вопроса:

У меня есть диапазон дат между Пятница, 14 августа - Понедельник, 14 сентября 2009 г. (31 день) работник получает оплату за каждый вторник поэтому ему заплатили 18 и 25 августа, 1 и 8 августа мы получили 4 раза платеж (Частота)

другой пример:

с тем же диапазоном дат Пятница 14 августа - понедельник 14 сентября 2009 г. (31 день) но другая дата оплаты .. например воскресенье
ему заплатили: 15, 22 и 29 августа, 5 и 12 сентября ... мы получили 5 раз платеж.

тот же диапазон дат, но разный день оплаты .. приведет к другому.

Итак, мой вопрос: есть ли формула для решения этого дела? на данный момент я рассчитываю с помощью ручного итератора .. который очень медленный (потому что диапазон может быть несколько лет или месяцев)

спасибо

ps: я использую groovy ... любые решения, использующие java, groovy или просто алгоритм, приветствуются:)

Ответы [ 5 ]

3 голосов
/ 10 августа 2009

Часто периоды оплаты наступают 15 и в конце каждого месяца, поэтому в этом случае вы будете считать количество месяцев и умножаться на 2, проверяя условия окончания (если начало до 15 числа, вычтите один период оплаты ; если конец - после конца месяца, вычтите один платежный период).

Можно получить количество дней, недель и месяцев, но вам придется добавить логику для обработки хитроумных конечных условий. Это, вероятно, не простая формула, как показывает описанный мной случай.

1 голос
/ 10 августа 2009

абсолютно, использовать класс Weeks очень просто:

DateTime start = new LocalDate(2009, 8, 10).toDateTimeAtStartOfDay();
DateTime end = new LocalDate(2009, 12, 31).toDateTimeAtStartOfDay();
int numberOfWeeks = Weeks.weeksBetween(start, end).getWeeks();

этот код дает 20 в качестве результата. Это правильно?

EDIT

может быть, это лучше:

DateMidnight start = new DateMidnight(2009, 8, 10);
DateMidnight end = new DateMidnight(2009, 12, 31);
int numberOfWeeks = Weeks.weeksBetween(start, end).getWeeks();
System.out.println(numberOfWeeks);
0 голосов
/ 11 августа 2009

Только что получил решения, пожалуйста, проверьте, если я сделал что-то не так

import org.joda.time.* ; 

def start = new Date().parse("dd/MM/yy","14/08/2009");
def end = new Date().parse("dd/MM/yy","14/09/2009");

println("date range ${start} - ${end}");

def diff = end - start ; 
println("diff : ${diff} days ");
println("how many weeks : ${diff/7}");

def payDay = 2 ; // Monday = 1 Sunday = 0  

def startDay = new DateTime(start).dayOfWeek ; // 5 = Thursday 

def startDayDiff = payDay - startDay ; 
if(startDay > payDay){
   startDayDiff = 7 + payDay - startDay ;
}

// for example if end on Friday (5) while Pay day is day 1 (Monday) then 
// make sure end date is on Monday (same week )
// end date = end - ( endDay - payDay)


def endDay = new DateTime(end).dayOfWeek;
println("original end day: ${endDay}");
def endDayDiff = endDay - payDay ; 

// otherwise ... if endDay < payDay (for example PayDay = Friday but End day is on Monday)
// end date = end - 7 + payDay 
if(endDay < payDay){
   endDayDiff =  7 - endDay - payDay ;
}
println("endDayDiff : ${endDayDiff}");
println("startDayDiff:  ${startDayDiff}");

def startedOn = new DateTime(start).plusDays(startDayDiff);
println("started on : ${startedOn.toDate()}");

def endOn = new DateTime(end).minusDays(endDayDiff);
println("End on : ${endOn.toDate()}");

println("occurences :  ${Weeks.weeksBetween(startedOn,endOn).getWeeks()+1}");

Протестировано с помощью groovyConsole с помощью Joda Time ..:)

0 голосов
/ 10 августа 2009

Здесь есть два трюка: один из них заключается в том, что правила различаются в зависимости от сроков Я имею в виду, что если человеку платят один раз в неделю, то через 7 дней ему платят один раз, через 14 дней ему платят дважды и т. Д. Но если человеку платят 1 и 16 числа каждого месяца, я не могу Скажите, сколько раз ему заплатили за 60 дней, не зная, какие месяцы были включены: где они короткие или долгие месяцы?

Во-вторых, вам нужно беспокоиться о начале и конце периода времени. Если человеку платят каждый понедельник, то количество раз, когда ему платят за 8 дней, зависит от того, является ли первый день 8 понедельником.

Таким образом, я думаю, что вам нужно иметь различную логику для расписаний с фиксированным числом дней и с привязкой к месяцам или чему-то еще, где интервалы могут варьироваться.

Для фиксированного количества дней проблема довольно проста. Единственная сложность заключается в том, что период времени не является точным кратным интервалу. Так что я бы сказал, найти первую дату в интервале, в который происходит день выплаты жалованья. Затем найдите количество дней между этим и концом периода времени, разделите на интервал и отбросьте все дроби.

Например: человеку платят каждый понедельник. Сколько дней оплаты между 1 марта и 12 апреля? Найдите первый понедельник в этом диапазоне. Скажем, он выпадает на 4 марта. Затем рассчитайте количество дней с 4 марта по 12 апреля. Это будет 39. 39/7 = 5 и дробь. Поэтому ему платят еще 5 чеков на общую сумму 6.

Для ежемесячной оплаты, я думаю, вам нужно разделить первый и последний месяц. Затем вы можете посчитать количество месяцев в середине и умножить на количество выплат в месяц. Тогда для первого и последнего подсчитайте, сколько в них трудного пути.

0 голосов
/ 10 августа 2009

Вычитание одной даты из другой для получения «количества дней» (или недель), как правило, является неправильным способом для такого рода расчетов. Например, если кому-то 365 дней, ему ровно год, если в это время не было 29 февраля. В любой (современный) 7-дневный период всегда есть ровно один вторник; но на 8 дней это либо один, либо два. Календарь часто фигурирует в расчетах.

Если они выплачиваются один или два раза в месяц, вы выполняете простой расчет по всем месяцам - начиная с первого и заканчивая в последний день месяца, который варьируется - и затем вы должны учитывать частичное месяцев в начале и / или конце. (Не забывайте, что происходит, если 15-й или последний день месяца выпадает на выходные.) Если им платят каждые одну или две недели, вы можете выполнить синхронизацию с известным днем ​​выплаты, а затем выполнить более простую математику для расчета целые недели до и / или с тех пор. (Не забудьте праздники, которые выпадают на день выплаты жалованья.)

...