Skip to content

Commit

Permalink
Merge pull request #46 from jdhok/develop
Browse files Browse the repository at this point in the history
Allow user specified granularity in relative time ranges
  • Loading branch information
Jaideep Dhok committed Sep 23, 2014
2 parents 3e00cd7 + e4c3f6b commit 73258b7
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 12 deletions.
59 changes: 47 additions & 12 deletions ql/src/java/org/apache/hadoop/hive/ql/cube/parse/DateUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ public class DateUtil {
* NOW (+-) <NUM>UNIT
* or Hardcoded dates in DD-MM-YYYY hh:mm:ss,sss
*/
public static final String RELATIVE = "(now){1}";
public static final String UNIT = "year|month|week|day|hour|minute|second";
public static final String GRANULARITY = "\\.(" + UNIT + ")";
public static final String RELATIVE = "(now){1}(" + GRANULARITY + "){0,1}";
public static final Pattern P_RELATIVE = Pattern.compile(RELATIVE,
Pattern.CASE_INSENSITIVE);

Expand All @@ -58,7 +60,6 @@ public class DateUtil {
public static final String QUANTITY = "\\d+";
public static final Pattern P_QUANTITY = Pattern.compile(QUANTITY);

public static final String UNIT = "year|month|week|day|hour|minute|second";
public static final Pattern P_UNIT = Pattern.compile(UNIT,
Pattern.CASE_INSENSITIVE);

Expand Down Expand Up @@ -121,21 +122,58 @@ public static Date resolveDate(String str, Date now) throws SemanticException {
}
}

private static Date resolveRelativeDate(String str, Date now)
public static Date resolveRelativeDate(String str, Date now)
throws SemanticException {
if (StringUtils.isBlank(str)) {
throw new SemanticException(ErrorMsg.NULL_DATE_VALUE);
}
// Get rid of whitespace
String raw = str.replaceAll(WSPACE, "").replaceAll(RELATIVE, "");

if (raw.isEmpty()) { // String is just "now"
return now;
// Resolve NOW with proper granularity
Calendar calendar = Calendar.getInstance();
calendar.setTime(now);

str = str.toLowerCase();
Matcher relativeMatcher = P_RELATIVE.matcher(str);
if (relativeMatcher.find()) {
String nowWithGranularity = relativeMatcher.group();
nowWithGranularity = nowWithGranularity.replaceAll("now", "");
nowWithGranularity = nowWithGranularity.replaceAll("\\.", "");

Matcher granularityMatcher = P_UNIT.matcher(nowWithGranularity);
if (granularityMatcher.find()) {
String unit = granularityMatcher.group().toLowerCase();
if ("year".equals(unit)) {
calendar = DateUtils.truncate(calendar, Calendar.YEAR);
} else if ("month".equals(unit)) {
calendar = DateUtils.truncate(calendar, Calendar.MONTH);
} else if ("week".equals(unit)) {
calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
calendar = DateUtils.truncate(calendar, Calendar.DAY_OF_MONTH);
} else if ("day".equals(unit)) {
calendar = DateUtils.truncate(calendar, Calendar.DAY_OF_MONTH);
} else if ("hour".equals(unit)) {
calendar = DateUtils.truncate(calendar, Calendar.HOUR_OF_DAY);
} else if ("minute".equals(unit)) {
calendar = DateUtils.truncate(calendar, Calendar.MINUTE);
} else if ("second".equals(unit)) {
calendar = DateUtils.truncate(calendar, Calendar.SECOND);
} else {
throw new SemanticException(ErrorMsg.INVALID_TIME_UNIT, unit);
}
}
}

// Get rid of 'now' part and whitespace
String raw = str.replaceAll(GRANULARITY, "").replace(WSPACE, "");

if (raw.isEmpty()) { // String is just "now" with granularity
return calendar.getTime();
}

// Get the relative diff part to get eventual date based on now.
Matcher qtyMatcher = P_QUANTITY.matcher(raw);
int qty = 1;
if (qtyMatcher.find() && true) {
if (qtyMatcher.find()) {
qty = Integer.parseInt(qtyMatcher.group());
}

Expand All @@ -148,9 +186,6 @@ private static Date resolveRelativeDate(String str, Date now)
}

Matcher unitMatcher = P_UNIT.matcher(raw);
Calendar calendar = Calendar.getInstance();
calendar.setTime(now);

if (unitMatcher.find()) {
String unit = unitMatcher.group().toLowerCase();
if ("year".equals(unit)) {
Expand All @@ -168,7 +203,7 @@ private static Date resolveRelativeDate(String str, Date now)
} else if ("second".equals(unit)) {
calendar.add(Calendar.SECOND, qty);
} else {
throw new SemanticException(ErrorMsg.INVALID_TIME_UNIT);
throw new SemanticException(ErrorMsg.INVALID_TIME_UNIT, unit);
}
}

Expand Down
31 changes: 31 additions & 0 deletions ql/src/test/org/apache/hadoop/hive/ql/cube/parse/TestDateUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import org.junit.Before;
import org.junit.Test;

import static org.apache.hadoop.hive.ql.cube.parse.DateUtil.resolveDate;

/**
* Unit tests for cube DateUtil class
* TestDateUtil.
Expand Down Expand Up @@ -184,4 +186,33 @@ public void testWeeksBetween() throws Exception {
Assert.assertEquals("2013-May-26 to 2013-Jun-10", 2, weeks);
}

@Test
public void testNowWithGranularity() throws Exception {
String dateFmt = "yyyy/MM/dd-HH.mm.ss.SSS";
// Tuesday Sept 23, 2014, 12.02.05.500 pm
String testDateStr = "2014/09/23-12.02.05.500";
final SimpleDateFormat sdf = new SimpleDateFormat(dateFmt);
final Date testDate = sdf.parse(testDateStr);

System.out.print("@@ testDateStr=" + testDateStr + " parsed date=" + testDate);

// Tests without a diff, just resolve now with different granularity
Assert.assertEquals(testDateStr, sdf.format(resolveDate("now", testDate)));
Assert.assertEquals("2014/01/01-00.00.00.000", sdf.format(resolveDate("now.year", testDate)));
Assert.assertEquals("2014/09/01-00.00.00.000", sdf.format(resolveDate("now.month", testDate)));
// Start of week resolves to Sunday
Assert.assertEquals("2014/09/21-00.00.00.000", sdf.format(resolveDate("now.week", testDate)));
Assert.assertEquals("2014/09/23-00.00.00.000", sdf.format(resolveDate("now.day", testDate)));
Assert.assertEquals("2014/09/23-12.00.00.000", sdf.format(resolveDate("now.hour", testDate)));
Assert.assertEquals("2014/09/23-12.02.00.000", sdf.format(resolveDate("now.minute", testDate)));
Assert.assertEquals("2014/09/23-12.02.05.000", sdf.format(resolveDate("now.second", testDate)));

// Tests with a diff
Assert.assertEquals("2014/09/22-00.00.00.000", sdf.format(resolveDate("now.day -1day", testDate)));
Assert.assertEquals("2014/09/23-10.00.00.000", sdf.format(resolveDate("now.hour -2hour", testDate)));
Assert.assertEquals("2014/09/24-12.00.00.000", sdf.format(resolveDate("now.hour +24hour", testDate)));
Assert.assertEquals("2015/01/01-00.00.00.000", sdf.format(resolveDate("now.year +1year", testDate)));
Assert.assertEquals("2014/02/01-00.00.00.000", sdf.format(resolveDate("now.year +1month", testDate)));
}

}

0 comments on commit 73258b7

Please sign in to comment.