package jtrade.util; import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; import org.joda.time.DateTime; import org.joda.time.Days; import org.joda.time.Hours; import org.joda.time.LocalTime; import org.joda.time.MutableDateTime; import org.joda.time.ReadablePeriod; public class DateTimeRange implements Iterable<DateTime> { DateTime start; DateTime end; public DateTimeRange(DateTime start, DateTime end) { this.start = start; this.end = end; } public DateTime getStart() { return start; } public DateTime getEnd() { return end; } public int getDays() { return Days.daysBetween(start, end).getDays(); } public int getWorkingDays() { MutableDateTime date = start.toMutableDateTime(); int count = 0; while (date.isBefore(end)) { if (date.getDayOfWeek() <= 5) { count++; } date.addDays(1); } return count; } @Override public Iterator<DateTime> iterator() { return new DateTimeIterator(start, end, Days.ONE); } public Iterator<DateTime> iterator(ReadablePeriod period) { return new DateTimeIterator(start, end, period); } public Iterator<DateTime> iterator(ReadablePeriod period, LocalTime startTime, LocalTime endTime, int... days) { return new DateTimeExceptionsIterator(start, end, period, startTime, endTime, days); } public Iterator<DateTime> dayIterator() { return dayIterator(new int[] { 1, 2, 3, 4, 5, 6, 7 }); } public Iterator<DateTime> workingDayIterator() { return dayIterator(new int[] { 1, 2, 3, 4, 5 }); } public Iterator<DateTime> dayIterator(int... days) { return new DateTimeExceptionsIterator(start, end, Days.ONE, null, null, days); } static class DateTimeExceptionsIterator implements Iterator<DateTime> { private DateTime current; private DateTime end; private ReadablePeriod period; private long startTime; private long endTime; private int[] days; private DateTimeExceptionsIterator(DateTime start, DateTime end, ReadablePeriod period, LocalTime startTime, LocalTime endTime, int... days) { this.end = end; this.period = period; this.startTime = startTime != null ? startTime.getMillisOfDay() : -1; this.endTime = endTime != null ? endTime.getMillisOfDay() : -1; this.days = days; this.current = nextValid(start.minus(period)); } private DateTime nextValid(DateTime dt) { while (true) { dt = dt.plus(period); if (!dt.isAfter(end)) { long millisOfDay = dt.getMillisOfDay(); if (Arrays.binarySearch(days, dt.getDayOfWeek()) >= 0 && (startTime < 0 || (millisOfDay >= startTime && millisOfDay <= endTime))) { break; } } else { dt = null; break; } } return dt; } @Override public boolean hasNext() { return current != null; } @Override public DateTime next() { if (current == null) { throw new NoSuchElementException(); } DateTime ret = current; current = nextValid(current); return ret; } @Override public void remove() { throw new UnsupportedOperationException(); } } static class DateTimeIterator implements Iterator<DateTime> { private DateTime current; private DateTime end; private ReadablePeriod period; private DateTimeIterator(DateTime start, DateTime end, ReadablePeriod period) { this.current = start; this.end = end; this.period = period; } @Override public boolean hasNext() { return current != null; } @Override public DateTime next() { if (current == null) { throw new NoSuchElementException(); } DateTime ret = current; current = current.plus(period); if (current.isAfter(end)) { current = null; } return ret; } @Override public void remove() { throw new UnsupportedOperationException(); } } public static void main(String args[]) { DateTime start = new DateTime(2009, 7, 20, 0, 0, 0, 0); DateTime end = new DateTime(2009, 8, 3, 0, 0, 0, 0); for (Iterator<DateTime> dates = new DateTimeRange(start, end).iterator(Hours.ONE, new LocalTime(9, 0, 0, 0), new LocalTime(17, 0, 0, 0), 6, 7); dates .hasNext();) { System.out.println(dates.next()); } } }