工作过程中遇到很多情况需要进行日期格式处理,通常用下面的方法来实现:
from_unixtime(to_unix_timestamp('20150813','yyyyMMdd'),'yyyy-MM-dd')
2015-08-13
如果再需要对日期进行一下加减多少天的话,还需要再增加长度:
date_sub(from_unixtime(to_unix_timestamp('20150813','yyyyMMdd'),'yyyy-MM-dd'),5)
2015-08-08
如果还需要把日期转换成整形的话,还需要再套个两层:
from_unixtime(to_unix_timestamp(date_sub(from_unixtime(to_unix_timestamp('20150813','yyyyMMdd'),'yyyy-MM-dd'),5),'yyyy-MM-dd'),'yyyyMMdd')
20150808
这样不仅使用不方便,而且代码的整洁度不好。
所以写了以下的UDF,先看效果:
myfunc('date_format','20150813','yyyyMMdd','yyyyMMdd-5d')
20150808
复杂点:
myfunc('date_format','2015-08-13 12:45:22','yyyy-MM-dd HH:mm:ss','yyyyMMddHHmmss-5d+3y-1s+1M')
20180908010244
UDF使用方法和说明:
hive> add jar /home/sospdm/Myfunc.jar;
Added /home/sospdm/Myfunc.jar to class path
Added resource: /home/sospdm/Myfunc.jar
hive> create temporary function myfunc as 'sospdm.udf.Myfunc';
udf可以支持多个参数传入,第一个参数为内置方法名称,通过不同的方法名可以执行不同的方法,方便后期扩展UDF功能,目前只支持一个'date_format',第二个参数是输入的日期,第三个是输入参数格式,第四个是输出日期的格式(可以做加减天数)。
代码如下:
package sospdm.udf;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.hive.ql.exec.Description;
import java.util.Date;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.text.SimpleDateFormat;
@Description(name = "myfunc",
value="_FUNC_(func_nm,parma1,parma2,[parma3],...)"+"",
extended = "Example:\n"
+ "> select _FUNC_('concat_low','aBc','dEf') from src;\n"
+ "Return:\n"
+ "abcdef;")
public class Myfunc extends UDF{
//***************************数据日期格式转换和加减计算****************************//
private static Date getDateAfter(Date dt,int[] num){
Calendar now =Calendar.getInstance();
now.setTime(dt);
now.add(Calendar.YEAR,num[0]);
now.add(Calendar.MONTH,num[1]);
now.add(Calendar.DAY_OF_MONTH,num[2]);
now.add(Calendar.HOUR_OF_DAY,num[3]);
now.add(Calendar.MINUTE,num[4]);
now.add(Calendar.SECOND,num[5]);
return now.getTime();
}
private static String getfmt(String str_input,String str_inputformat,String str_outputformat){
try{
//*********************通过正则表达式解析str_outputformat*********************
SimpleDateFormat in_fmt = new SimpleDateFormat(str_inputformat);
SimpleDateFormat out_fmt2 = new SimpleDateFormat(str_outputformat);
//最长支持增加或者减少12位数的计算
Pattern p = Pattern.compile("((\\+|-)\\d{1,12})([A-Za-z])");
Matcher m = p.matcher(str_outputformat);
Matcher m1 = p.matcher(str_outputformat);
Date dt_input = in_fmt.parse(str_input);
if(m1.find()){
int pos_exg = m1.start();
//*********************获取输入参数、输入参数格式参数格式*****************
SimpleDateFormat out_fmt = new SimpleDateFormat(str_outputformat.substring(0,pos_exg));
//新建HashMap类存储解析后的各个字符
Map<String,Integer> map = new HashMap<String,Integer>();
//初始化map
map.put("y", 0);
map.put("M", 0);
map.put("d", 0);
map.put("H", 0);
map.put("m", 0);
map.put("s", 0);
//第三个组作为KEY,第一组作为VALUE,更新map
while(m.find()){
map.put(m.group(3), Integer.valueOf(m.group(1)).intValue());
}
//数组初始化
int[] num_arr =
{
map.get("y"),
map.get("M"),
map.get("d"),
map.get("H"),
map.get("m"),
map.get("s")
};
return out_fmt.format(getDateAfter(dt_input,num_arr));
} else {
return out_fmt2.format(dt_input);
}
}
catch(Exception e){
e.printStackTrace();
}
return null;
}
//******************************UDF调用代码*************************************//
public String evaluate(String func_nm,String... s){
try{
switch(func_nm){
//日期格式转换
case "date_format":
return getfmt(s[0],s[1],s[2]);
default:
return null;
}
} catch(Exception e){
e.printStackTrace();
return func_nm;
}
}
}