Hive 功能:添加月份到日期
Posted
技术标签:
【中文标题】Hive 功能:添加月份到日期【英文标题】:Hive function: add month to date 【发布时间】:2014-12-19 14:18:52 【问题描述】:我正在 Hive 中搜索一个函数,它将添加月份至今。
例如:
add_month('2014-01-01',1) -> '2014-02-01'
add_month('2013-12-01',1) -> '2014-01-01'
【问题讨论】:
如果在 1 月 31 日加上 1 个月会怎样? 我的情况比较简单,我总是需要在月份的第一天加上1个月,例如:2014-01-01 -> 2014-02-01; 2013-12-01 -> 2014-01-01 在标准 SQL 中,这将是date '2014-01-01' + interval '1' month
。不知道 Hive 是否支持 SQL 标准。
【参考方案1】:
只需输入:
select add_months('2014-01-01', 1);
【讨论】:
【参考方案2】:您可以创建通用 UDF (GenericUDF)。
这是一个示例 UDF:
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.IntObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
public class AddMonth extends GenericUDF
@Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException
if (arguments.length != 2)
throw new UDFArgumentLengthException("The function add_month(local_date, months_to_add) requires 2 arguments.");
ObjectInspector localDateVal = arguments[0];
ObjectInspector monthsToAddVal = arguments[1];
if (!(localDateVal instanceof StringObjectInspector))
throw new UDFArgumentException("First argument must be of type String (local_date as String)");
if (!(monthsToAddVal instanceof IntObjectInspector))
throw new UDFArgumentException("Second argument must be of type int (Month to add)");
return PrimitiveObjectInspectorFactory.writableStringObjectInspector;
@Override
public Object evaluate(DeferredObject[] arguments) throws HiveException
String localDateVal = (String) ObjectInspectorUtils.copyToStandardJavaObject(arguments[0].get(),
PrimitiveObjectInspectorFactory.javaStringObjectInspector);
IntWritable monthsToAddVal = (IntWritable) ObjectInspectorUtils.copyToStandardJavaObject(arguments[1].get(),
PrimitiveObjectInspectorFactory.javaIntObjectInspector);
LocalDate localDate = null;
try
localDate = LocalDate.parse(localDateVal, DateTimeFormat.forPattern("yyyy-MM-dd"));
catch (Exception ex)
return null;
return new Text(localDate.plusMonths(monthsToAddVal.get().toString());
@Override
public String getDisplayString(String[] arguments)
assert (arguments.length == 2);
return "add_month(" + arguments[0] + ", " + arguments[1] + ")";
证明正确性的测试用例:
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredJavaObject;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredObject;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.junit.Test;
public class AddMonthTest
private final String TEST_DATA = "2014-01-01";
private final AddMonth addMonth = new AddMonth();
ObjectInspector ob = PrimitiveObjectInspectorFactory.javaStringObjectInspector;
ObjectInspector ob1 = PrimitiveObjectInspectorFactory.javaIntObjectInspector;
private final ObjectInspector[]arg = ob, ob1 ;
@Test
public void testAdd1Month() throws Exception
DeferredJavaObject def1 = new DeferredJavaObject(TEST_DATA);
DeferredJavaObject def2 = new DeferredJavaObject(1);
addMonth.initialize(arg);
DeferredObject[] def = def1, def2 ;
String resultData = addMonth.evaluate(def).toString();
assertThat(resultData, is("2014-02-01"));
@Test
public void testAdd12Month() throws Exception
DeferredJavaObject def1 = new DeferredJavaObject(TEST_DATA);
DeferredJavaObject def2 = new DeferredJavaObject(12);
addMonth.initialize(arg);
DeferredObject[] def = def1, def2 ;
String resultData = addMonth.evaluate(def).toString();
assertThat(resultData, is("2015-01-01"));
@Test
public void testSub1Month() throws Exception
DeferredJavaObject def1 = new DeferredJavaObject(TEST_DATA);
DeferredJavaObject def2 = new DeferredJavaObject(-1);
addMonth.initialize(arg);
DeferredObject[] def = def1, def2 ;
String resultData = addMonth.evaluate(def).toString();
assertThat(resultData, is("2013-12-01"));
@Test
public void testSub12Month() throws Exception
DeferredJavaObject def1 = new DeferredJavaObject(TEST_DATA);
DeferredJavaObject def2 = new DeferredJavaObject(-12);
addMonth.initialize(arg);
DeferredObject[] def = def1, def2 ;
String resultData = addMonth.evaluate(def).toString();
assertThat(resultData, is("2013-01-01"));
@Test
public void incorrectInput() throws Exception
DeferredJavaObject def1 = new DeferredJavaObject("InvalidString");
DeferredJavaObject def2 = new DeferredJavaObject(12);
addMonth.initialize(arg);
DeferredObject[] def = def1, def2 ;
Object resultData = addMonth.evaluate(def);
assertNull(resultData);
你可以使用如下函数:
CREATE TEMPORARY FUNCTION add_month AS 'AddMonth';
SELECT
add_month ('2014-01-01',1)
FROM
TAB_NAME;
预期输出将是:
2014-02-01
【讨论】:
我在转换为 Text 和 writableInt 时不断出错。有什么提示吗? 你可以使用 add_months 请看这个:***.com/questions/38221393/…以上是关于Hive 功能:添加月份到日期的主要内容,如果未能解决你的问题,请参考以下文章