importgroovy.transform.Fieldimportjava.time.*;importstaticjava.time.DayOfWeek.*;importstaticjava.time.temporal.ChronoUnit.*;importstaticjava.time.LocalTime.MIDNIGHTimportstaticjava.time.temporal.TemporalAdjusters.previousOrSameimportstaticjava.time.temporal.TemporalAdjusters.next@FielddefWEEKEND_DAYS=[FRIDAY,SATURDAY]@FieldintWORK_DAY_START_HOUR=8@FieldintWORK_DAY_END_HOUR=17@FieldLocalTimeWORK_DAY_START=LocalTime.of(WORK_DAY_START_HOUR,0)@FieldLocalTimeWORK_DAY_END=LocalTime.of(WORK_DAY_END_HOUR,0)@FieldlongWORK_DAY_SECONDS=SECONDS.between(WORK_DAY_START,WORK_DAY_END)DatestartDateDateendDate// Set values of startDate and endDate here...// code code codedefstart=LocalDateTime.ofInstant(startDate.toInstant(),ZoneId.systemDefault())defend=LocalDateTime.ofInstant(endDate.toInstant(),ZoneId.systemDefault())/* We normalise the time range to (almost) a whole number of weeks, going from theimmediately preceding Sunday midnight to the immediately following Friday midnight,while keeping track of how much extra time we add by doing so. The total time canthen be calculated as a simple multiple of the number of weeks, minus the additionaltime introduced by normalisation. */defstartCorrectionSecondsdefsundayMidnightBeforeStart=start.with(previousOrSame(SUNDAY)).with(MIDNIGHT)if(start.dayOfWeekinWEEKEND_DAYS){/* If it's the weekend then we're always adding five full working days' worth of seconds. */startCorrectionSeconds=5*WORK_DAY_SECONDS}else{/* Otherwise we calculate the number of full working days preceding, convert to seconds, and add the number of extra seconds in the current, incomplete day. */defsecondsSinceWorkDayStart=clampSeconds(SECONDS.between(WORK_DAY_START,start.toLocalTime()))defdaysSinceSunday=DAYS.between(sundayMidnightBeforeStart,start)startCorrectionSeconds=daysSinceSunday*WORK_DAY_SECONDS+secondsSinceWorkDayStart}defendCorrectionSecondsdeffridayMidnightAfterEnd=end.with(next(FRIDAY)).with(MIDNIGHT)//Have to special-case Sunday midnight to avoid double countingif(end.dayOfWeekinWEEKEND_DAYS||end.dayOfWeek==SUNDAY&&end.toLocalTime()==MIDNIGHT){/* If it's the weekend then we're always adding five full working days' worth of seconds. */endCorrectionSeconds=5*WORK_DAY_SECONDS}else{/* Otherwise we calculate the number of full working days following, convert to seconds, and add the number of extra seconds in the current, incomplete day. */defsecondsUntilWorkDayEnd=clampSeconds(SECONDS.between(end.toLocalTime(),WORK_DAY_END))defdaysUntilFriday=DAYS.between(end,fridayMidnightAfterEnd)endCorrectionSeconds=secondsUntilWorkDayEnd+daysUntilFriday*WORK_DAY_SECONDS}defdaysBetween=DAYS.between(sundayMidnightBeforeStart,fridayMidnightAfterEnd)/* We're measuring from Sunday midnight to Friday midnight, so we always expectto get a positive number of days which is two fewer than a whole number of weeks. */assertdaysBetween>0&&(daysBetween+2)%7==0/* Add 2 to get a multiple of 7, divide by 7 to get number of weeks, multiply by 5to get number of work days. */defworkDaysBetween=((daysBetween+2)/ 7) * 5log.info([workDaysBetween, startCorrectionSeconds, endCorrectionSeconds])def secondsBetween = workDaysBetween * WORK_DAY_SECONDS - (startCorrectionSeconds + endCorrectionSeconds)return Math.round(secondsBetween /60.0asDouble)//***************************************************/* If a time falls before the start, or after the end, of a work day, then thedifference between that time and the start/end of the day might be negative, orlarger than the length of a work day.In either case we only want to count the seconds that are part of the work day,so we use this function to restrict the value into that range. */longclampSeconds(longseconds){Math.max(0,Math.min(WORK_DAY_SECONDS,seconds))}
Comments (0)
HTTPSSSH
You can clone a snippet to your computer for local editing.
Learn more.