You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lens.apache.org by am...@apache.org on 2015/04/15 21:50:04 UTC

[30/50] [abbrv] incubator-lens git commit: LENS-412 : Fix error messaging for update periods available (Rajat Khandelwal via amareshwari

LENS-412 : Fix error messaging for update periods available (Rajat Khandelwal via amareshwari


Project: http://git-wip-us.apache.org/repos/asf/incubator-lens/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-lens/commit/5e492d93
Tree: http://git-wip-us.apache.org/repos/asf/incubator-lens/tree/5e492d93
Diff: http://git-wip-us.apache.org/repos/asf/incubator-lens/diff/5e492d93

Branch: refs/heads/current-release-line
Commit: 5e492d93f013ad533b0865ed74155ed7c5940224
Parents: 0f5ea4c
Author: Rajat Khandelwal <pr...@apache.org>
Authored: Tue Apr 7 11:01:54 2015 +0530
Committer: Amareshwari Sriramadasu <am...@apache.org>
Committed: Tue Apr 7 11:01:54 2015 +0530

----------------------------------------------------------------------
 .../lens/cube/metadata/CubeFactTable.java       |  17 +--
 .../org/apache/lens/cube/parse/DateUtil.java    | 153 ++++++++++---------
 .../lens/cube/parse/StorageTableResolver.java   |   7 +-
 .../org/apache/lens/cube/parse/TimeRange.java   |   6 +
 .../lens/cube/parse/TestCubeRewriter.java       |   2 +-
 .../apache/lens/cube/parse/TestDateUtil.java    |  91 +++++++----
 6 files changed, 152 insertions(+), 124 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5e492d93/lens-cube/src/main/java/org/apache/lens/cube/metadata/CubeFactTable.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/metadata/CubeFactTable.java b/lens-cube/src/main/java/org/apache/lens/cube/metadata/CubeFactTable.java
index cb84f66..9daccec 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/metadata/CubeFactTable.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/metadata/CubeFactTable.java
@@ -183,22 +183,7 @@ public final class CubeFactTable extends AbstractCubeTable {
     for (UpdatePeriod i : updatePeriods) {
       if (UpdatePeriod.YEARLY == i || UpdatePeriod.QUARTERLY == i || UpdatePeriod.MONTHLY == i
         || UpdatePeriod.WEEKLY == i) {
-        int intervals = 0;
-        switch (i) {
-        case YEARLY:
-          intervals = DateUtil.getYearsBetween(from, to);
-          break;
-        case QUARTERLY:
-          intervals = DateUtil.getQuartersBetween(from, to);
-          break;
-        case MONTHLY:
-          intervals = DateUtil.getMonthsBetween(from, to);
-          break;
-        case WEEKLY:
-          intervals = DateUtil.getWeeksBetween(from, to);
-          break;
-        }
-
+        int intervals = DateUtil.getTimeDiff(from, to, i);
         if (intervals > 0) {
           if (cmp.compare(i, max) > 0) {
             max = i;

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5e492d93/lens-cube/src/main/java/org/apache/lens/cube/parse/DateUtil.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/DateUtil.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/DateUtil.java
index 1094e44..a4988d4 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/DateUtil.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/DateUtil.java
@@ -23,6 +23,7 @@ import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -34,6 +35,8 @@ import org.apache.hadoop.hive.ql.ErrorMsg;
 import org.apache.hadoop.hive.ql.parse.SemanticException;
 import org.apache.log4j.Logger;
 
+import lombok.Data;
+
 public final class DateUtil {
   private DateUtil() {
 
@@ -287,15 +290,18 @@ public final class DateUtil {
     return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
   }
 
-  public static int getMonthsBetween(Date from, Date to) {
+  public static CoveringInfo getMonthlyCoveringInfo(Date from, Date to) {
     // Move 'from' to end of month, unless its the first day of month
+    boolean coverable = true;
     if (!from.equals(DateUtils.truncate(from, Calendar.MONTH))) {
       from = DateUtils.addMonths(DateUtils.truncate(from, Calendar.MONTH), 1);
+      coverable = false;
     }
 
-    // Move 'to' to beginning of month, unless its the last day of the month
-    if (!to.equals(DateUtils.round(to, Calendar.MONTH))) {
+    // Move 'to' to beginning of next month, unless its the first day of the month
+    if (!to.equals(DateUtils.truncate(to, Calendar.MONTH))) {
       to = DateUtils.truncate(to, Calendar.MONTH);
+      coverable = false;
     }
 
     int months = 0;
@@ -303,77 +309,55 @@ public final class DateUtil {
       from = DateUtils.addMonths(from, 1);
       months++;
     }
-    return months;
+    return new CoveringInfo(months, coverable);
   }
 
-  public static int getQuartersBetween(Date from, Date to) {
-    int months = getMonthsBetween(from, to);
-    if (months < 3) {
-      return 0;
+  public static CoveringInfo getQuarterlyCoveringInfo(Date from, Date to) {
+    CoveringInfo monthlyCoveringInfo = getMonthlyCoveringInfo(from, to);
+    if (monthlyCoveringInfo.getCountBetween() < 3) {
+      return new CoveringInfo(0, false);
+    }
+    boolean coverable = monthlyCoveringInfo.isCoverable();
+    if (!from.equals(DateUtils.truncate(from, Calendar.MONTH))) {
+      from = DateUtils.addMonths(DateUtils.truncate(from, Calendar.MONTH), 1);
+      coverable = false;
     }
-
     Calendar cal = Calendar.getInstance();
     cal.setTime(from);
     int fromMonth = cal.get(Calendar.MONTH);
-    int fromYear = cal.get(Calendar.YEAR);
 
     // Get the start date of the quarter
-    int qtrStartMonth;
-    if (fromMonth % 3 == 0) {
-      qtrStartMonth = fromMonth;
-    } else {
-      qtrStartMonth = fromMonth - (fromMonth % 3);
+    int beginOffset = (3 - fromMonth % 3) % 3;
+    int endOffset = (monthlyCoveringInfo.getCountBetween() - beginOffset) % 3;
+    if (beginOffset > 0 || endOffset > 0) {
+      coverable = false;
     }
+    return new CoveringInfo((monthlyCoveringInfo.getCountBetween() - beginOffset - endOffset) / 3, coverable);
+  }
 
-    cal.clear();
-    cal.set(Calendar.MONTH, qtrStartMonth);
-    cal.set(Calendar.YEAR, fromYear);
-    cal.set(Calendar.DAY_OF_MONTH, 1);
-    Date fromQtrStartDate = cal.getTime();
-
-    int moveUp = 0;
-    if (fromQtrStartDate.before(from)) {
-      moveUp = 3 - (fromMonth % 3);
-    }
 
-    if (months % 3 != 0) {
-      months = months - (months % 3);
+  public static CoveringInfo getYearlyCoveringInfo(Date from, Date to) {
+    CoveringInfo monthlyCoveringInfo = getMonthlyCoveringInfo(from, to);
+    if (monthlyCoveringInfo.getCountBetween() < 12) {
+      return new CoveringInfo(0, false);
     }
-    return (months - moveUp) / 3;
-  }
-
-  public static int getYearsBetween(Date from, Date to) {
-    int months = getMonthsBetween(from, to);
-    if (months < 12) {
-      return 0;
+    boolean coverable = monthlyCoveringInfo.isCoverable();
+    if (!from.equals(DateUtils.truncate(from, Calendar.MONTH))) {
+      from = DateUtils.addMonths(DateUtils.truncate(from, Calendar.MONTH), 1);
+      coverable = false;
     }
-
-    // Get start of year for 'from' date
     Calendar cal = Calendar.getInstance();
     cal.setTime(from);
     int fromMonth = cal.get(Calendar.MONTH);
-    int fromYear = cal.get(Calendar.YEAR);
-
-    cal.clear();
-    cal.set(Calendar.MONTH, Calendar.JANUARY);
-    cal.set(Calendar.YEAR, fromYear);
-    cal.set(Calendar.DAY_OF_MONTH, 1);
-
-    Date yearStartDate = cal.getTime();
-
-    int moveUp = 0;
-    if (yearStartDate.before(from)) {
-      moveUp = 12 - (fromMonth % 12);
-    }
-
-    if (months % 12 != 0) {
-      months = months - (months % 12);
+    int beginOffset = (12 - fromMonth % 12) % 12;
+    int endOffset = (monthlyCoveringInfo.getCountBetween() - beginOffset) % 12;
+    if (beginOffset > 0 || endOffset > 0) {
+      coverable = false;
     }
-
-    return (months - moveUp) / 12;
+    return new CoveringInfo((monthlyCoveringInfo.getCountBetween() - beginOffset - endOffset) / 12, coverable);
   }
 
-  public static int getWeeksBetween(Date from, Date to) {
+  public static CoveringInfo getWeeklyCoveringInfo(Date from, Date to) {
     int dayDiff = 0;
     Date tmpFrom = from;
     while (tmpFrom.before(to)) {
@@ -382,7 +366,7 @@ public final class DateUtil {
     }
 
     if (dayDiff < 7) {
-      return 0;
+      return new CoveringInfo(0, false);
     }
 
     Calendar cal = Calendar.getInstance();
@@ -397,40 +381,65 @@ public final class DateUtil {
     cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
     int maxDayInWeek = cal.getActualMaximum(Calendar.DAY_OF_WEEK);
     Date fromWeekStartDate = cal.getTime();
-
+    boolean coverable = dayDiff % 7 == 0;
     if (fromWeekStartDate.before(from)) {
       // Count from the start of next week
       dayDiff -= (maxDayInWeek - (fromDay - Calendar.SUNDAY));
+      coverable = false;
     }
 
-    return dayDiff / 7;
+    return new CoveringInfo(dayDiff / 7, coverable);
   }
 
-  static long getTimeDiff(Date from, Date to, UpdatePeriod interval) {
-    long diff = to.getTime() - from.getTime();
+  static CoveringInfo getCoveringInfo(Date from, Date to, UpdatePeriod interval) {
     switch (interval) {
     case SECONDLY:
-      return diff / 1000;
+      return getMilliSecondCoveringInfo(from, to, 1000);
     case MINUTELY:
-      return diff / (1000 * 60);
+      return getMilliSecondCoveringInfo(from, to, 1000 * 60);
     case HOURLY:
-      return diff / (1000 * 60 * 60);
+      return getMilliSecondCoveringInfo(from, to, 1000 * 60 * 60);
     case DAILY:
-      return diff / (1000 * 60 * 60 * 24);
+      return getMilliSecondCoveringInfo(from, to, 1000 * 60 * 60 * 24);
     case WEEKLY:
-      // return diff/(1000 * 60 * 60 * 24 * 7);
-      return getWeeksBetween(from, to);
+      return getWeeklyCoveringInfo(from, to);
     case MONTHLY:
-      // return (long) (diff/(60 * 60 * 1000 * 24 * 30.41666666));
-      return getMonthsBetween(from, to);
+      return getMonthlyCoveringInfo(from, to);
     case QUARTERLY:
-      return getQuartersBetween(from, to);
+      return getQuarterlyCoveringInfo(from, to);
     case YEARLY:
-      // return (diff/(60 * 60 * 1000 * 24 * 365));
-      return getYearsBetween(from, to);
+      return getYearlyCoveringInfo(from, to);
     default:
-      return -1;
+      return new CoveringInfo(0, false);
+    }
+  }
+
+  private static CoveringInfo getMilliSecondCoveringInfo(Date from, Date to, int millisInInterval) {
+    long diff = to.getTime() - from.getTime();
+    return new CoveringInfo((int) (diff / millisInInterval), diff % millisInInterval == 0);
+  }
+
+  static boolean isCoverableBy(Date from, Date to, Set<UpdatePeriod> intervals) {
+    for (UpdatePeriod period : intervals) {
+      if (getCoveringInfo(from, to, period).isCoverable()) {
+        return true;
+      }
     }
+    return false;
   }
 
+  public static int getTimeDiff(Date fromDate, Date toDate, UpdatePeriod updatePeriod) {
+    return getCoveringInfo(fromDate, toDate, updatePeriod).getCountBetween();
+  }
+
+  @Data
+  public static class CoveringInfo {
+    int countBetween;
+    boolean coverable;
+
+    public CoveringInfo(int countBetween, boolean coverable) {
+      this.countBetween = countBetween;
+      this.coverable = coverable;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5e492d93/lens-cube/src/main/java/org/apache/lens/cube/parse/StorageTableResolver.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/StorageTableResolver.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/StorageTableResolver.java
index 6e63483..96ca82c 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/StorageTableResolver.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/StorageTableResolver.java
@@ -351,7 +351,7 @@ class StorageTableResolver implements ContextRewriter {
          * 2. All Storage tables were skipped for some reasons.
          * 3. Storage tables do not have the update period for the timerange queried.
          */
-        if (!nonExistingParts.isEmpty()) {
+        if (failOnPartialData && !nonExistingParts.isEmpty()) {
           cubeql.addFactPruningMsgs(cfact.fact, CandidateTablePruneCause.missingPartitions(nonExistingParts));
         } else if (!skipStorageCauses.isEmpty()) {
           CandidateTablePruneCause cause = CandidateTablePruneCause.noCandidateStorages(skipStorageCauses);
@@ -405,8 +405,9 @@ class StorageTableResolver implements ContextRewriter {
     Map<UpdatePeriod, RangesPartitionTimeline> nonExistingParts)
     throws Exception {
     Set<FactPartition> partitions = new TreeSet<FactPartition>();
-    if (getPartitions(fact, range.getFromDate(), range.getToDate(), range.getPartitionColumn(), partitions,
-      updatePeriods, addNonExistingParts, skipStorageCauses, nonExistingParts)) {
+    if (range.isCoverableBy(updatePeriods)
+      && getPartitions(fact, range.getFromDate(), range.getToDate(), range.getPartitionColumn(), partitions,
+        updatePeriods, addNonExistingParts, skipStorageCauses, nonExistingParts)) {
       return partitions;
     } else {
       return new TreeSet<FactPartition>();

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5e492d93/lens-cube/src/main/java/org/apache/lens/cube/parse/TimeRange.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/TimeRange.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/TimeRange.java
index ecd7b76..612cdf9 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/TimeRange.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/TimeRange.java
@@ -20,6 +20,7 @@ package org.apache.lens.cube.parse;
 
 import java.util.Calendar;
 import java.util.Date;
+import java.util.TreeSet;
 
 import org.apache.lens.cube.metadata.UpdatePeriod;
 
@@ -40,6 +41,11 @@ public class TimeRange {
   private ASTNode parent;
   private int childIndex;
 
+  public boolean isCoverableBy(TreeSet<UpdatePeriod> updatePeriods) {
+    return DateUtil.isCoverableBy(fromDate, toDate, updatePeriods);
+  }
+
+
   public static class TimeRangeBuilder {
     private final TimeRange range;
 

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5e492d93/lens-cube/src/test/java/org/apache/lens/cube/parse/TestCubeRewriter.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/test/java/org/apache/lens/cube/parse/TestCubeRewriter.java b/lens-cube/src/test/java/org/apache/lens/cube/parse/TestCubeRewriter.java
index f9a3762..6c65953 100644
--- a/lens-cube/src/test/java/org/apache/lens/cube/parse/TestCubeRewriter.java
+++ b/lens-cube/src/test/java/org/apache/lens/cube/parse/TestCubeRewriter.java
@@ -839,7 +839,7 @@ public class TestCubeRewriter extends TestQueryRewrite {
     Assert.assertEquals(pruneCauses.getDetails().get("testfact").iterator().next().getCause(),
       CandidateTablePruneCode.MISSING_PARTITIONS);
     Assert.assertEquals(pruneCauses.getDetails().get("testfactmonthly").iterator().next().getCause(),
-      CandidateTablePruneCode.MISSING_PARTITIONS);
+      CandidateTablePruneCode.NO_FACT_UPDATE_PERIODS_FOR_GIVEN_RANGE);
     Assert.assertEquals(pruneCauses.getDetails().get("testfact2").iterator().next().getCause(),
         CandidateTablePruneCode.MISSING_PARTITIONS);
     Assert.assertEquals(pruneCauses.getDetails().get("testfact2_raw").iterator().next().getCause(),

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/5e492d93/lens-cube/src/test/java/org/apache/lens/cube/parse/TestDateUtil.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/test/java/org/apache/lens/cube/parse/TestDateUtil.java b/lens-cube/src/test/java/org/apache/lens/cube/parse/TestDateUtil.java
index fa2503e..9efd1f7 100644
--- a/lens-cube/src/test/java/org/apache/lens/cube/parse/TestDateUtil.java
+++ b/lens-cube/src/test/java/org/apache/lens/cube/parse/TestDateUtil.java
@@ -16,7 +16,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 package org.apache.lens.cube.parse;
 
 import static org.apache.lens.cube.parse.DateUtil.resolveDate;
@@ -62,93 +61,121 @@ public class TestDateUtil {
   @Test
   public void testMonthsBetween() throws Exception {
     int i = 0;
-    Assert.assertEquals(1, DateUtil.getMonthsBetween(pairs[i], DateUtils.round(pairs[i + 1], Calendar.MONTH)),
+    Assert.assertEquals(DateUtil.getMonthlyCoveringInfo(pairs[i], DateUtils.round(pairs[i + 1], Calendar.MONTH)),
+      new DateUtil.CoveringInfo(1, true),
       "2013-Jan-01 to 2013-Jan-31");
 
     i += 2;
-    Assert.assertEquals(5, DateUtil.getMonthsBetween(pairs[i], DateUtils.round(pairs[i + 1], Calendar.MONTH)),
+    Assert.assertEquals(DateUtil.getMonthlyCoveringInfo(pairs[i], DateUtils.round(pairs[i + 1], Calendar.MONTH)),
+      new DateUtil.CoveringInfo(5, true),
       "2013-Jan-01 to 2013-May-31");
 
     i += 2;
-    Assert.assertEquals(12, DateUtil.getMonthsBetween(pairs[i], DateUtils.round(pairs[i + 1], Calendar.MONTH)),
+    Assert.assertEquals(DateUtil.getMonthlyCoveringInfo(pairs[i], DateUtils.round(pairs[i + 1], Calendar.MONTH)),
+      new DateUtil.CoveringInfo(12, true),
       "2013-Jan-01 to 2013-Dec-31");
 
     i += 2;
-    Assert.assertEquals(2, DateUtil.getMonthsBetween(pairs[i], pairs[i + 1]), "2013-Feb-01 to 2013-Apr-25");
+    Assert.assertEquals(DateUtil.getMonthlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(2, false),
+      "2013-Feb-01 to 2013-Apr-25");
 
     i += 2;
-    Assert.assertEquals(12, DateUtil.getMonthsBetween(pairs[i], pairs[i + 1]), "2012-Feb-01 to 2013-Feb-01");
+    Assert.assertEquals(DateUtil.getMonthlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(12, true),
+      "2012-Feb-01 to 2013-Feb-01");
 
     i += 2;
-    Assert.assertEquals(24, DateUtil.getMonthsBetween(pairs[i], pairs[i + 1]), "2011-Feb-01 to 2013-Feb-01");
+    Assert.assertEquals(DateUtil.getMonthlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(24, true),
+      "2011-Feb-01 to 2013-Feb-01");
 
     i += 2;
-    Assert.assertEquals(0, DateUtil.getMonthsBetween(pairs[i], pairs[i + 1]), "2013-Jan-02 to 2013-Feb-02");
+    Assert.assertEquals(DateUtil.getMonthlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(0, false),
+      "2013-Jan-02 to 2013-Feb-02");
 
     i += 2;
-    Assert.assertEquals(1, DateUtil.getMonthsBetween(pairs[i], pairs[i + 1]), "2013-Jan-02 to 2013-Mar-02");
+    Assert.assertEquals(DateUtil.getMonthlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(1, false),
+      "2013-Jan-02 to 2013-Mar-02");
   }
 
   @Test
   public void testQuartersBetween() throws Exception {
     int i = 0;
-    Assert.assertEquals(0, DateUtil.getQuartersBetween(pairs[i], pairs[i + 1]), "2013-Jan-01 to 2013-Jan-31");
+    Assert.assertEquals(DateUtil.getQuarterlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(0, false),
+      "2013-Jan-01 to 2013-Jan-31");
 
     i += 2;
-    Assert.assertEquals(1, DateUtil.getQuartersBetween(pairs[i], pairs[i + 1]), "2013-Jan-01 to 2013-May-31");
+    Assert.assertEquals(DateUtil.getQuarterlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(1, false),
+      "2013-Jan-01 to 2013-May-31");
 
     i += 2;
-    Assert.assertEquals(4, DateUtil.getQuartersBetween(pairs[i], DateUtils.round(pairs[i + 1], Calendar.MONTH)),
+    Assert.assertEquals(DateUtil.getQuarterlyCoveringInfo(pairs[i], DateUtils.round(pairs[i + 1], Calendar.MONTH)),
+      new DateUtil.CoveringInfo(4, true),
       "2013-Jan-01 to 2013-Dec-31");
 
     i += 2;
-    Assert.assertEquals(0, DateUtil.getQuartersBetween(pairs[i], pairs[i + 1]), "2013-Feb-01 to 2013-Apr-25");
+    Assert.assertEquals(DateUtil.getQuarterlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(0, false),
+      "2013-Feb-01 to 2013-Apr-25");
 
     i += 2;
-    Assert.assertEquals(3, DateUtil.getQuartersBetween(pairs[i], pairs[i + 1]), "2012-Feb-01 to 2013-Feb-01");
+    Assert.assertEquals(DateUtil.getQuarterlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(3, false),
+      "2012-Feb-01 to 2013-Feb-01");
 
     i += 2;
-    Assert.assertEquals(7, DateUtil.getQuartersBetween(pairs[i], pairs[i + 1]), "2011-Feb-01 to 2013-Feb-01");
+    Assert.assertEquals(DateUtil.getQuarterlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(7, false),
+      "2011-Feb-01 to 2013-Feb-01");
   }
 
   @Test
   public void testYearsBetween() throws Exception {
     int i = 0;
-    Assert.assertEquals(0, DateUtil.getYearsBetween(pairs[i], pairs[i + 1]), "" + pairs[i] + "->" + pairs[i + 1]);
+    Assert.assertEquals(DateUtil.getYearlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(0, false),
+      "" + pairs[i] + "->" + pairs[i + 1]);
 
     i += 2;
-    Assert.assertEquals(0, DateUtil.getYearsBetween(pairs[i], pairs[i + 1]), "" + pairs[i] + "->" + pairs[i + 1]);
+    Assert.assertEquals(DateUtil.getYearlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(0, false),
+      "" + pairs[i] + "->" + pairs[i + 1]);
 
     i += 2;
-    Assert.assertEquals(1, DateUtil.getYearsBetween(pairs[i], DateUtils.round(pairs[i + 1], Calendar.MONTH)), ""
-      + pairs[i] + "->" + pairs[i + 1]);
+    Assert.assertEquals(DateUtil.getYearlyCoveringInfo(pairs[i], DateUtils.round(pairs[i + 1], Calendar.MONTH)),
+      new DateUtil.CoveringInfo(1, true), ""
+        + pairs[i] + "->" + pairs[i + 1]);
 
     i += 2;
-    Assert.assertEquals(0, DateUtil.getYearsBetween(pairs[i], pairs[i + 1]), "" + pairs[i] + "->" + pairs[i + 1]);
+    Assert.assertEquals(DateUtil.getYearlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(0, false),
+      "" + pairs[i] + "->" + pairs[i + 1]);
 
     i += 2;
-    Assert.assertEquals(0, DateUtil.getYearsBetween(pairs[i], pairs[i + 1]), "" + pairs[i] + "->" + pairs[i + 1]);
+    Assert.assertEquals(DateUtil.getYearlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(0, false),
+      "" + pairs[i] + "->" + pairs[i + 1]);
 
     i += 2;
-    Assert.assertEquals(1, DateUtil.getYearsBetween(pairs[i], pairs[i + 1]), "" + pairs[i] + "->" + pairs[i + 1]);
+    Assert.assertEquals(DateUtil.getYearlyCoveringInfo(pairs[i], pairs[i + 1]), new DateUtil.CoveringInfo(1, false),
+      "" + pairs[i] + "->" + pairs[i + 1]);
   }
 
   @Test
   public void testWeeksBetween() throws Exception {
-    int weeks = DateUtil.getWeeksBetween(DATE_FMT.parse("2013-May-26"), DATE_FMT.parse("2013-Jun-2"));
-    Assert.assertEquals(1, weeks, "2013-May-26 to 2013-Jun-2");
+    DateUtil.CoveringInfo weeks;
+
+    weeks = DateUtil.getWeeklyCoveringInfo(DATE_FMT.parse("2013-May-26"), DATE_FMT.parse("2013-Jun-2"));
+    Assert.assertEquals(weeks, new DateUtil.CoveringInfo(1, true), "2013-May-26 to 2013-Jun-2");
+
+    weeks = DateUtil.getWeeklyCoveringInfo(DATE_FMT.parse("2013-May-27"), DATE_FMT.parse("2013-Jun-3"));
+    Assert.assertEquals(weeks, new DateUtil.CoveringInfo(0, false), "2013-May-26 to 2013-Jun-2");
+
+    weeks = DateUtil.getWeeklyCoveringInfo(DATE_FMT.parse("2013-May-27"), DATE_FMT.parse("2013-Jun-9"));
+    Assert.assertEquals(weeks, new DateUtil.CoveringInfo(1, false), "2013-May-26 to 2013-Jun-2");
 
-    weeks = DateUtil.getWeeksBetween(DATE_FMT.parse("2013-May-27"), DATE_FMT.parse("2013-Jun-1"));
-    Assert.assertEquals(0, weeks, "2013-May-27 to 2013-Jun-1");
+    weeks = DateUtil.getWeeklyCoveringInfo(DATE_FMT.parse("2013-May-27"), DATE_FMT.parse("2013-Jun-1"));
+    Assert.assertEquals(weeks, new DateUtil.CoveringInfo(0, false), "2013-May-27 to 2013-Jun-1");
 
-    weeks = DateUtil.getWeeksBetween(DATE_FMT.parse("2013-May-25"), DATE_FMT.parse("2013-Jun-2"));
-    Assert.assertEquals(1, weeks, "2013-May-25 to 2013-Jun-1");
+    weeks = DateUtil.getWeeklyCoveringInfo(DATE_FMT.parse("2013-May-25"), DATE_FMT.parse("2013-Jun-2"));
+    Assert.assertEquals(weeks, new DateUtil.CoveringInfo(1, false), "2013-May-25 to 2013-Jun-1");
 
-    weeks = DateUtil.getWeeksBetween(DATE_FMT.parse("2013-May-26"), DATE_FMT.parse("2013-Jun-9"));
-    Assert.assertEquals(2, weeks, "2013-May-26 to 2013-Jun-8");
+    weeks = DateUtil.getWeeklyCoveringInfo(DATE_FMT.parse("2013-May-26"), DATE_FMT.parse("2013-Jun-9"));
+    Assert.assertEquals(weeks, new DateUtil.CoveringInfo(2, true), "2013-May-26 to 2013-Jun-8");
 
-    weeks = DateUtil.getWeeksBetween(DATE_FMT.parse("2013-May-26"), DATE_FMT.parse("2013-Jun-10"));
-    Assert.assertEquals(2, weeks, "2013-May-26 to 2013-Jun-10");
+    weeks = DateUtil.getWeeklyCoveringInfo(DATE_FMT.parse("2013-May-26"), DATE_FMT.parse("2013-Jun-10"));
+    Assert.assertEquals(weeks, new DateUtil.CoveringInfo(2, false), "2013-May-26 to 2013-Jun-10");
   }
 
   @Test