Finding the nth business day of the month in Groovy
Does anyone know the b开发者_运维知识库est way to calculate the nth business day of the month in Groovy?
i.e. the 7th business day in April (4), in 2011, would be 11th April.
I wrote a quick DSL for working with days (the linked example shows working out the UK holidays)
Using that, to find (for example) the 5th weekday in September this year (2011), you can do:
// 5th weekday in September
println new DateDSL().with {
every.weekday.in.september( 2011 )
}[ 4 ]
Which prints
Wed Sep 07 00:00:00 UTC 2011
Using your example, you would do:
// 7th Weekday in April
println new DateDSL().with {
every.weekday.in.april( 2011 )
}[ 6 ]
which prints (as you wanted)
Mon Apr 11 00:00:00 UTC 2011
As you probably don't have the month by name but by an integer, you could wrap the call in a function:
// n and month starts from 1 (for first day/month)
Date nthWeekdayInMonth( int n, int month, int year ) {
new DateDSL().with {
every.weekday.in."${months[month-1]}"( year )
}[ n - 1 ]
}
println nthWeekdayInMonth( 7, 4, 2011 )
If you don't want t use that (and it is probably over-comlpex for this specific issue), you're back to using a java Calendar and rolling the date (as it does inside the workings of the dsl)
Edit
A less convoluted method might be to create a class which iterates over weekdays like so:
class WeekdayIterator {
private static GOOD_DAYS = [Calendar.MONDAY..Calendar.FRIDAY].flatten()
private Calendar c = Calendar.instance
private Date nxt
private int month, year
WeekdayIterator( int month, int year ) {
c.set( year, month, 1 )
this.month = month
nxt = nextWeekday()
}
private Date nextWeekday() {
while( c.get( Calendar.MONTH ) == month ) {
if( c.get( Calendar.DAY_OF_WEEK ) in GOOD_DAYS ) {
Date ret = c.time.clearTime()
c.add( Calendar.DATE, 1 )
return ret
}
c.add( Calendar.DATE, 1 )
}
null
}
Iterator iterator() {
[ hasNext:{ nxt != null }, next:{ Date ret = nxt ; nxt = delegate.nextWeekday() ; ret } ] as Iterator
}
}
This can then be called like this to get the 7th business day by either:
def weekdays = new WeekdayIterator( Calendar.APRIL, 2011 )
println weekdays.collect { it }[ 6 ]
or
def weekdays = new WeekdayIterator( Calendar.APRIL, 2011 )
println weekdays.iterator()[ 6 ]
精彩评论