Index: ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java (revision 1438333) +++ ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java (working copy) @@ -79,6 +79,8 @@ import org.apache.hadoop.hive.ql.udf.UDFLpad; import org.apache.hadoop.hive.ql.udf.UDFMinute; import org.apache.hadoop.hive.ql.udf.UDFMonth; +import org.apache.hadoop.hive.ql.udf.UDFMonthAdd; +import org.apache.hadoop.hive.ql.udf.UDFMonthSub; import org.apache.hadoop.hive.ql.udf.UDFOPBitAnd; import org.apache.hadoop.hive.ql.udf.UDFOPBitNot; import org.apache.hadoop.hive.ql.udf.UDFOPBitOr; @@ -332,6 +334,9 @@ registerUDF("date_add", UDFDateAdd.class, false); registerUDF("date_sub", UDFDateSub.class, false); registerUDF("datediff", UDFDateDiff.class, false); + + registerUDF("month_add", UDFMonthAdd.class, false); + registerUDF("month_sub", UDFMonthSub.class, false); registerUDF("get_json_object", UDFJson.class, false); Index: ql/src/java/org/apache/hadoop/hive/ql/udf/UDFMonthAdd.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/UDFMonthAdd.java (revision 0) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/UDFMonthAdd.java (revision 0) @@ -0,0 +1,70 @@ +package org.apache.hadoop.hive.ql.udf; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.hive.serde2.io.TimestampWritable; +import org.apache.hadoop.io.IntWritable; +import org.apache.hadoop.io.Text; + +@Description(name = "month_add", + value = "_FUNC_(start_date, num_months) - Returns the date that is num_months after start_date.", + extended = "start_date is a string in the format 'yyyy-MM-dd HH:mm:ss' or" + + " 'yyyy-MM-dd'. num_months is a number. The time part of start_date is " + + "ignored.\n" + + "Example:\n " + + " " + "SELECT _FUNC_('2012-04-12', 1) FROM src LIMIT 1; --Return 2012-05-12\n" + + " " + "SELECT _FUNC_('2012-04-12 11:22:31', 1) FROM src LIMIT 1; --Return 2012-05-12\n" + + " " + "SELECT _FUNC_(cast('2012-04-12 11:22:31' as timestamp), 1) FROM src LIMIT 1; --Return 2012-05-12") +public class UDFMonthAdd extends UDF { + private final Text result = new Text(); + private final Calendar calendar = Calendar.getInstance(); + private final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + + public UDFMonthAdd() { + } + + /** + * Add a number of months to the date. The time part of the string will be + * ignored. + * + * @param dateString1 + * the date string in the format of "yyyy-MM-dd HH:mm:ss" or + * "yyyy-MM-dd". + * @param months + * The number of months to add. + * @return the date in the format of "yyyy-MM-dd". + */ + public Text evaluate(Text dateString1, IntWritable months) { + + if (dateString1 == null || months == null) { + return null; + } + + try { + calendar.setTime(formatter.parse(dateString1.toString())); + calendar.add(Calendar.MONTH, months.get()); + Date newDate = calendar.getTime(); + result.set(formatter.format(newDate)); + return result; + } catch (ParseException e) { + return null; + } + } + + public Text evaluate(TimestampWritable t, IntWritable months) { + if (t == null || months == null) { + return null; + } + calendar.setTime(t.getTimestamp()); + calendar.add(Calendar.MONTH, months.get()); + Date newDate = calendar.getTime(); + result.set(formatter.format(newDate)); + return result; + } + +} Index: ql/src/java/org/apache/hadoop/hive/ql/udf/UDFMonthSub.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/UDFMonthSub.java (revision 0) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/UDFMonthSub.java (revision 0) @@ -0,0 +1,70 @@ +package org.apache.hadoop.hive.ql.udf; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.hive.serde2.io.TimestampWritable; +import org.apache.hadoop.io.IntWritable; +import org.apache.hadoop.io.Text; + +@Description(name = "month_sub", + value = "_FUNC_(start_date, num_months) - Returns the date that is num_months before start_date.", + extended = "start_date is a string in the format 'yyyy-MM-dd HH:mm:ss' or" + + " 'yyyy-MM-dd'. num_months is a number. The time part of start_date is " + + "ignored.\n" + + "Example:\n " + + " " + "SELECT _FUNC_('2012-04-12', 1) FROM src LIMIT 1; --Return 2012-03-12\n" + + " " + "SELECT _FUNC_('2012-04-12 11:22:31', 1) FROM src LIMIT 1; --Return 2012-03-12\n" + + " " + "SELECT _FUNC_(cast('2012-04-12 11:22:31' as timestamp), 1) FROM src LIMIT 1; --Return 2012-03-12\n") +public class UDFMonthSub extends UDF { + private final Text result = new Text(); + private final Calendar calendar = Calendar.getInstance(); + private final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + + public UDFMonthSub() { + } + + /** + * Subtract a number of months to the date. The time part of the string will be + * ignored. + * + * @param dateString1 + * the date string in the format of "yyyy-MM-dd HH:mm:ss" or + * "yyyy-MM-dd". + * @param months + * The number of months to subtract. + * @return the date in the format of "yyyy-MM-dd". + */ + public Text evaluate(Text dateString1, IntWritable months) { + + if (dateString1 == null || months == null) { + return null; + } + + try { + calendar.setTime(formatter.parse(dateString1.toString())); + calendar.add(Calendar.MONTH, -months.get()); + Date newDate = calendar.getTime(); + result.set(formatter.format(newDate)); + return result; + } catch (ParseException e) { + return null; + } + } + + public Text evaluate(TimestampWritable t, IntWritable months) { + if (t == null || months == null) { + return null; + } + calendar.setTime(t.getTimestamp()); + calendar.add(Calendar.MONTH, -months.get()); + Date newDate = calendar.getTime(); + result.set(formatter.format(newDate)); + return result; + } + +}