/** * Copyright 2016 Nabarun Mondal * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.noga.njexl.lang.extension.iterators; import org.joda.time.*; import org.joda.time.Duration; import org.joda.time.Period; import org.joda.time.format.ISOPeriodFormat; import java.util.Calendar; import java.util.Date; /** * Created by noga on 28/04/15. */ public class DateIterator extends YieldedIterator{ public static final long DAY_IN_MILLIS = 24 * 60 * 60 * 1000 ; public static final Duration DAY = new Duration( DAY_IN_MILLIS ); public static Duration parseDuration(String text){ Period p = ISOPeriodFormat.standard().parsePeriod(text); return p.toStandardDuration(); } /** * http://stackoverflow.com/questions/4600034/calculate-number-of-weekdays-between-two-dates-in-java * @param start starting date * @param end ending date * @return number of week days in between */ static long weekDays(Date start, Date end){ //Ignore argument check Calendar c1 = Calendar.getInstance(); c1.setTime(start); int w1 = c1.get(Calendar.DAY_OF_WEEK); c1.add(Calendar.DAY_OF_WEEK, -w1); Calendar c2 = Calendar.getInstance(); c2.setTime(end); int w2 = c2.get(Calendar.DAY_OF_WEEK); c2.add(Calendar.DAY_OF_WEEK, -w2); //end Saturday to start Saturday long days = (c2.getTimeInMillis()-c1.getTimeInMillis())/(1000*60*60*24); long daysWithoutWeekendDays = days-(days*2/7); // Adjust w1 or w2 to 0 since we only want a count of *weekdays* // to add onto our daysWithoutWeekendDays if (w1 == Calendar.SUNDAY) { w1 = Calendar.MONDAY; } if (w2 == Calendar.SUNDAY) { w2 = Calendar.MONDAY; } return daysWithoutWeekendDays-w1+w2; } public final DateTime b; public final DateTime e; public final Duration s ; public final Duration duration ; protected DateTime cur; public final int seconds; public final int minutes; public final int hours ; public final int days ; public final int weeks ; public final int months ; public final int years ; public final long weekDays; public final String stringRep; public final int hashCode; public DateIterator(DateTime end){ this(end, new DateTime()); } public DateIterator(DateTime end, DateTime start){ this(end,start, DAY ); } public DateIterator(DateTime end, DateTime start, Duration interval){ this.e = end ; this.b = start ; this.s = interval ; decreasing = this.b.compareTo(this.e) > 0 ; // inclusive if ( decreasing ){ this.cur = this.b.plus(this.s) ; }else{ this.cur = this.b.minus(this.s) ; } this.duration = new Duration(this.b, this.e); years = Years.yearsBetween(start,end).getYears(); months = Months.monthsBetween(start, end).getMonths(); weeks = Weeks.weeksBetween(start, end).getWeeks(); days = Days.daysBetween(start, end).getDays(); hours = Hours.hoursBetween(start, end).getHours(); minutes = Minutes.minutesBetween(start, end).getMinutes(); seconds = Seconds.secondsBetween(start, end).getSeconds(); weekDays = weekDays( start.toDate(), end.toDate()); stringRep = String.format("%s : %s : %s", start.toDate(), end.toDate(), interval); hashCode = ( 31* (( 31 * end.hashCode() ) + start.hashCode()) + interval.hashCode()); } @Override public void reset() { // inclusive if ( decreasing ){ this.cur = this.b.plus(this.s) ; }else{ this.cur = this.b.minus(this.s) ; } } @Override public boolean equals(Object obj) { if ( !(obj instanceof DateIterator) ) return false ; DateIterator o = (DateIterator)obj; if ( e.equals(o.e) && b.equals(o.b) && s.equals(o.s) ) return true ; return false ; } @Override public int hashCode() { return hashCode ; } @Override public boolean hasNext() { if ( decreasing ){ return cur.minus(s).compareTo( e ) >=0 ; } return cur.plus(s).compareTo( e ) <= 0 ; } @Override public Object next() { if ( decreasing ){ cur = cur.minus(s); }else { cur = cur.plus(s); } return cur; } @Override public String toString(){ return stringRep ; } @Override public YieldedIterator inverse() { return new DateIterator(this.b, this.e, this.s ); } }