Java 在一定范围内计算频率

Java 在一定范围内计算频率,java,datetime,time,groovy,Java,Datetime,Time,Groovy,我有一道数学题。。。(当时我用手动迭代法解决了这个问题,速度非常慢) 例如,如果某个员工在某个日期每周(可以是两周/每两周和每月)领取工资(让我们每周二给该员工打电话,每月给该员工打电话,该员工在某个日期领取工资) 我的日期范围是2009年8月10日至2009年12月31日,现在如何获取员工获得工资的频率 是否可以使用jodatime计算此值 举例说明这个问题: 我的日期范围为2009年8月14日星期五至9月14日星期一(31天) 该员工在每周二领取工资 因此,他在8月18日和25日、8月1日和

我有一道数学题。。。(当时我用手动迭代法解决了这个问题,速度非常慢)

例如,如果某个员工在某个日期每周(可以是两周/每两周和每月)领取工资(让我们每周二给该员工打电话,每月给该员工打电话,该员工在某个日期领取工资)

我的日期范围是2009年8月10日至2009年12月31日,现在如何获取员工获得工资的频率

是否可以使用jodatime计算此值

举例说明这个问题:

我的日期范围为2009年8月14日星期五至9月14日星期一(31天) 该员工在每周二领取工资 因此,他在8月18日和25日、8月1日和8日获得了报酬,我们获得了4次报酬 (频率)

另一个例子:

同一日期范围为2009年8月14日星期五至9月14日星期一(31天) 但是不同的付款日期。。例如在周日
因此,他在8月15日、22日和29日、9月5日和12日获得了报酬。。。我们得到了5次付款

相同的日期范围但不同的发薪日。。结果会有所不同

所以我的问题是,有什么公式可以解决这个问题吗? 目前,我使用手动迭代器进行计算。。这是非常缓慢的(因为范围可能是几年或几个月)

多谢各位


ps:我正在使用groovy。。欢迎使用java、groovy或just算法的任何解决方案:)

通常支付期在每月15日和月末,因此在这种情况下,您需要计算月数并乘以2,检查结束条件(如果开始时间在15日之前,则减去一个支付期;如果结束时间在月底之后,则减去一个支付期)

可以获得天数、周数和月数,但必须添加逻辑来处理不可靠的结束条件。这可能不是一个简单的公式,正如我所描述的案例所示。

当然,使用该类非常简单:

DateTime start = new LocalDate(2009, 8, 10).toDateTimeAtStartOfDay();
DateTime end = new LocalDate(2009, 12, 31).toDateTimeAtStartOfDay();
int numberOfWeeks = Weeks.weeksBetween(start, end).getWeeks();
这个代码给出了20个结果。是吗?

编辑

也许这样更好:

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);

用一个日期减去另一个日期得到“天数”(或周数)通常是进行此类计算的错误方法。例如,如果某人已经365天了,那么他们正好是一岁,除非在这段时间内有一个2月29日。在任何(现代)7天的时间里,总有一个星期二;但在8天里,不是一天就是两天。日历经常被计算在内


如果一个月支付一次或两次,你会在整个月内进行简单的计算——从第一个月开始,到月底的最后一天结束,这是不同的,然后你必须考虑在开始和/或结束的几个月。(别忘了如果一个月的第15天或最后一天是周末会发生什么。)如果他们每一周或两周发一次工资,你可以在一个已知的发薪日同步,然后用更简单的数学计算出之前和/或之后的整周。(别忘了发薪日的假期。)

这里有两个诀窍:一个是规则根据时间框架而不同。我的意思是,如果一个人每周发一次工资,那么他在7天内发一次工资,在14天内发两次工资,等等。但是如果一个人在每个月的1号和16号发工资,我不能告诉你他在60天内发了多少次工资,而不知道包括哪些月份:短月份还是长月份

第二,你必须担心时间段的开始和结束。如果一个人每周一领工资,那么他在8天内领工资的次数取决于8天的第一天是否是周一

因此,我认为对于固定天数的日程安排和与月或其他时间间隔可能不同的日程安排,您需要有不同的逻辑

对于固定天数,问题相当简单。唯一的复杂性是如果时间范围不是时间间隔的精确倍数。所以我想说,在发薪日发生的时间间隔中找到第一个日期。然后找出从那里到时间段结束的天数,除以时间间隔,去掉任何分数

例如:一个人每周一领工资。3月1日至4月12日之间有多少个发薪日?找到该范围内的第一个星期一。比如说是在3月4日。然后计算从3月4日到4月12日的天数。那将是39。39/7=5和一个分数。因此,他多拿了5张薪水支票,总共6张


至于月薪,我想你得把第一个月和最后一个月分开。然后,你可以计算每月数在中间,乘以每月支付的数量。然后,第一次和最后一次计算,他们中有多少人是艰难的。

刚刚得到解决方案,请检查我是否做错了什么

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}");
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(“日期范围${start}-${end}”);
def diff=结束-开始;
println(“diff:${diff}天”);
println(“多少周:${diff/7}”);
def发薪日=2;//星期一=1星期日=0
def startDay=新日期时间(开始).dayOfWeek;//5=星期四
def startDayDiff=发薪日-startDay;
如果(开始日期>发薪日){
startDayDiff=7+发薪日-startDay;
}
//例如,如果在星期五(5)结束,而发薪日是第1天(星期一),那么
//确保结束日期为星期一(同一周)
//结束日期=结束-(结束日-发薪日)
def endDay=新的日期时间(end).dayOfWeek;
println(“原始结束日期:${endDay}”);
def endDayDiff=结束日-发薪日;
//否则。。。如果结束日<发薪日(例如,发薪日=星期五,但结束日在星期一)
//结束日期=结束-7+发薪日
如果(结束日<发薪日){
endDayDiff=7-endDay-发薪日;
}
println(“endDayDiff:${endDayDiff}”);
println(“startDayDiff:${startD