目录
1、功能介绍:
2、关于本文中的一些常用类和方法的介绍:
3、代码
1、首先导入hive依赖的jar包:
2、创建DateUtil类
3、创建DayBeginUDF类
4、创建WeekBeginUDF类
5、创建MonthBeginUDF类
6、创建FormatTimeUDF类
4、重新注册函数
5、测试SQL语句
首先,介绍一下关于本文函数的作用:
该文介绍的函数功能在统计用户活跃度的场景比较适用,或者跟统计某天,某几天,某周,某几个周,某月,某几个月相关的场景亦可适用。大大降低了hive SQL的编程难度。主要实现的功能如下:
(1)根据输入的时间信息,返回某天的起始时间。
getdaybegin() //计算当天的起始时刻(毫秒数)
getdaybegin(2) //以当天为坐标,指定天偏移量
getdaybegin('2017/06/29 01:02:03') //计算某天的起始时刻(毫秒数)
getdaybegin('2017/06/29 01:02:03',2) //计算以某天为坐标,指定天偏移量的起始时刻(毫秒数)
getdaybegin(date_obj) //计算某天的起始时刻(毫秒数)
getdaybegin(date_obj,2) //计算以某天为坐标,指定天偏移量的起始时刻(毫秒数)
(2)根据输入的时间信息,返回某周的起始时间 。 (注释类似上面)
getweekbegin()
getweekbegin(2)
getweekbegin('2017/06/29 01:02:03')
getweekbegin('2017/06/29 01:02:03',2)
getweekbegin(date_obj)
getweekbegin(date_obj,2)
(3)根据输入的时间信息,返回某月的起始时间。(注释类似上面)
getmonthbegin()
getmonthbegin(2)
getmonthbegin('2017/06/29 01:02:03')
getmonthbegin('2017/06/29 01:02:03',2)
getmonthbegin(date_obj)
getmonthbegin(date_obj,2)
(4)根据输入的时间和时间格式化信息,将long型的时间片格式化成指定日期格式。
formattime(1494392175246,'yyyy/MM/01')
formattime('1494392175246','yyyy/MM/dd')
1 SimleDateFormat类下的format( )方法。
//format( ):用于创建格式化的字符串以及连接多个字符串对象。
//format(String format, Object args): 新字符串使用本地语言环境,指定字符串格式和参数生成格式化的新字符串。
//format(Locale locale, String format, Object args):使用指定的语言环境,指定 字符串格式和参数生成格式化的字符串。
2 Calendar类下的常用方法。
//getInstance()使用默认时区和语言环境获得一个日历。
//setTime(Date date)使用给定的 Date 设置此 Calendar 的时间。
//add(int field, int amount) 根据日历的规则,为给定的日历字段添加或减去指定的时间量。
//Calendar.DAY_OF_WEEK:表示一周中的第几天,会因为选用的星期的表达格式的不同而受影响。
有些地区以星期日作为一周的第一天,而有些地区以星期一作为一周的第一天,这2种情况是需要区分的。
4.0.0
com.dateUtil
app-logs-hive
1.0-SNAPSHOT
junit
junit
4.11
org.apache.hive
hive-exec
2.1.1
作用:获取某天,某周,某月的起始零点时间
package com.dateUtil.udf;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
*
*/
public class DateUtil {
/**
* 得到指定date的零时刻.
*/
public static Date getDayBeginTime(Date d) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd 00:00:00");
return sdf.parse(sdf.format(d));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 得到指定date的偏移量零时刻.
*/
public static Date getDayBeginTime(Date d, int offset) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd 00:00:00");
Date beginDate = sdf.parse(sdf.format(d));
Calendar c = Calendar.getInstance();
c.setTime(beginDate);
c.add(Calendar.DAY_OF_MONTH,offset);
return c.getTime() ;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 得到指定date所在周的起始时刻.
*/
public static Date getWeekBeginTime(Date d) {
try {
//得到d的零时刻
Date beginDate= getDayBeginTime(d);
Calendar c = Calendar.getInstance();
c.setTime(beginDate);
int n = c.get(Calendar.DAY_OF_WEEK);
c.add(Calendar.DAY_OF_MONTH,-(n - 1));
return c.getTime();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 得到指定date所在周的起始时刻.
*/
public static Date getWeekBeginTime(Date d,int offset) {
try {
//得到d的零时刻
Date beginDate= getDayBeginTime(d);
Calendar c = Calendar.getInstance();
c.setTime(beginDate);
int n = c.get(Calendar.DAY_OF_WEEK);
//定位到本周第一天
c.add(Calendar.DAY_OF_MONTH,-(n - 1));
c.add(Calendar.DAY_OF_MONTH,offset * 7);
return c.getTime();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 得到指定date所在月的起始时刻.
*/
public static Date getMonthBeginTime(Date d) {
try {
//得到d的零时刻
Date beginDate= getDayBeginTime(d);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/01 00:00:00");
return sdf.parse(sdf.format(beginDate));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 得到指定date所在月的起始时刻.
*/
public static Date getMonthBeginTime(Date d,int offset) {
try {
//得到d的零时刻
Date beginDate= getDayBeginTime(d);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/01 00:00:00");
//d所在月的第一天的零时刻
Date firstDay = sdf.parse(sdf.format(beginDate));
Calendar c = Calendar.getInstance();
c.setTime(firstDay);
//对月进行滚动
c.add(Calendar.MONTH,offset);
return c.getTime();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.dateUtil.udf;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 计算day起始毫秒数
*/
@Description(name = "udf_getdaybegin",
value = "getdaybegin",
extended = "getdaybegin() ;\r\n"
+ " getdaybegin(2) \r\n"
+ " getdaybegin('2017/06/29 01:02:03') \r\n"
+ " getdaybegin('2017/06/29 01:02:03',2) \r\n"
+ " getdaybegin(date_obj) \r\n"
+ " getdaybegin(date_obj,2)")
public class DayBeginUDF extends UDF {
/**
* 计算现在的起始时刻(毫秒数)
*/
public long evaluate() throws ParseException {
return evaluate(new Date());
}
/**
* 以当天为坐标,指定天偏移量
*/
public long evaluate(int offset) throws ParseException {
return evaluate(DateUtil.getDayBeginTime(new Date(), offset));
}
/**
* 计算某天的起始时刻(毫秒数)
*/
public long evaluate(Date d) throws ParseException {
return DateUtil.getDayBeginTime(d).getTime();
}
/**
* 计算以某天为坐标,指定天偏移量的起始时刻(毫秒数)
*/
public long evaluate(Date d, int offset) throws ParseException {
return DateUtil.getDayBeginTime(d, offset).getTime();
}
/**
* 计算某天的起始时刻(毫秒数)
*/
public long evaluate(String dateStr) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d = sdf.parse(dateStr);
return evaluate(d);
}
/**
* 计算以某天为坐标,指定天偏移量的起始时刻(毫秒数)
*/
public long evaluate(String dateStr, int offset) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d = sdf.parse(dateStr);
return DateUtil.getDayBeginTime(d, offset).getTime();
}
/**
* 按照指定格式,计算某天的起始时刻(毫秒数)
*/
public long evaluate(String dateStr, String fmt) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
Date d = sdf.parse(dateStr);
return DateUtil.getDayBeginTime(d).getTime();
}
/**
* 计算以某天为坐标,按照指定格式,指定天偏移量的起始时刻(毫秒数)
*/
public long evaluate(String dateStr, String fmt, int offset) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
Date d = sdf.parse(dateStr);
return DateUtil.getDayBeginTime(d, offset).getTime();
}
}
package com.dateUtil.udf;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.hive.ql.udf.UDFType;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 计算day所在周起始毫秒数
*/
@Description(name = "udf_getweekbegin",
value = "getweekbegin",
extended = "getweekbegin() ;\r\n"
+ " getweekbegin(2) \r\n"
+ " getweekbegin('2017/06/29 01:02:03') \r\n"
+ " getweekbegin('2017/06/29 01:02:03',2) \r\n"
+ " getweekbegin(date_obj) \r\n"
+ " getweekbegin(date_obj,2)")
public class WeekBeginUDF extends UDF {
/**
* 计算当前周的起始时刻(毫秒数)
*/
public long evaluate() throws ParseException {
return DateUtil.getWeekBeginTime(new Date()).getTime() ;
}
/**
* 以当天为坐标,指定周偏移量
*/
public long evaluate(int offset) throws ParseException {
return DateUtil.getWeekBeginTime(new Date(),offset).getTime();
}
/**
*计算指定周的起始时刻(毫秒数)
*/
public long evaluate(Date d) throws ParseException {
return DateUtil.getWeekBeginTime(d).getTime();
}
/**
* 计算以某天为坐标,指定周偏移量的起始时刻(毫秒数)
*/
public long evaluate(Date d,int offset) throws ParseException {
return DateUtil.getWeekBeginTime(d,offset).getTime();
}
/**
* 计算某时间的周起始时刻(毫秒数)
*/
public long evaluate(String dateStr) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d = sdf.parse(dateStr);
return DateUtil.getWeekBeginTime(d).getTime();
}
/**
* 计算以某天为坐标,指定周偏移量的起始时刻(毫秒数)
*/
public long evaluate(String dateStr,int offset) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d = sdf.parse(dateStr);
return DateUtil.getWeekBeginTime(d, offset).getTime();
}
/**
* 按照指定格式,计算某周的起始时刻(毫秒数)
*/
public long evaluate(String dateStr, String fmt) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
Date d = sdf.parse(dateStr);
return DateUtil.getWeekBeginTime(d).getTime();
}
/**
* 计算以某天为坐标,按照指定格式,指定周偏移量的起始时刻(毫秒数)
*/
public long evaluate(String dateStr, String fmt,int offset) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
Date d = sdf.parse(dateStr);
return DateUtil.getWeekBeginTime(d, offset).getTime();
}
}
package com.dateUtil.udf;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.hive.ql.udf.UDFType;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 计算day所在月起始毫秒数
*/
@Description(name = "udf_getmonthbegin",
value = "getmonthbegin",
extended = "getmonthbegin() ;\r\n" +
" getmonthbegin(2) \r\n" +
" getmonthbegin('2017/06/29 01:02:03') \r\n" +
" getmonthbegin('2017/06/29 01:02:03',2) \r\n" +
" getmonthbegin(date_obj) \r\n" +
" getmonthbegin(date_obj,2)")
@UDFType(deterministic = true, stateful = false)
public class MonthBeginUDF extends UDF {
/**
* 计算现在的起始时刻(毫秒数)
*/
public long evaluate() throws ParseException {
return DateUtil.getMonthBeginTime(new Date()).getTime() ;
}
/**
* 指定周偏移量
*/
public long evaluate(int offset) throws ParseException {
return DateUtil.getMonthBeginTime(new Date(),offset).getTime();
}
/**
*
*/
public long evaluate(Date d) throws ParseException {
return DateUtil.getMonthBeginTime(d).getTime();
}
/**
*/
public long evaluate(Date d,int offset) throws ParseException {
return DateUtil.getMonthBeginTime(d,offset).getTime();
}
/**
*/
public long evaluate(String dateStr) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d = sdf.parse(dateStr);
return DateUtil.getMonthBeginTime(d).getTime();
}
/**
*/
public long evaluate(String dateStr,int offset) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d = sdf.parse(dateStr);
return DateUtil.getMonthBeginTime(d, offset).getTime();
}
/**
*/
public long evaluate(String dateStr, String fmt) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
Date d = sdf.parse(dateStr);
return DateUtil.getMonthBeginTime(d).getTime();
}
/**
*/
public long evaluate(String dateStr, String fmt,int offset) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
Date d = sdf.parse(dateStr);
return DateUtil.getMonthBeginTime(d, offset).getTime();
}
}
package com.dateUtil.udf;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 将long型的时间片格式化成指定日期格式
*/
@Description(name = "udf_formattime",
value = "formattime",
extended = "formattime() ;\r\n"
+ " formattime(1234567,'yyyy/MM/01') \r\n"
+ " formattime('1234567','yyyy/MM/dd')")
public class FormatTimeUDF extends UDF {
/**
* 格式化时间,long型
*/
public String evaluate(long ms,String fmt) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(fmt) ;
Date d = new Date();
d.setTime(ms);
return sdf.format(d) ;
}
/**
* 格式化时间,string类型
*/
public String evaluate(String ms,String fmt) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(fmt) ;
Date d = new Date();
d.setTime(Long.parseLong(ms));
return sdf.format(d) ;
}
/**
* 格式化时间,string类型
*/
public String evaluate(long ms ,String fmt , int week) throws ParseException {
Date d = new Date();
d.setTime(ms);
//周内第一天
Date firstDay = DateUtil.getWeekBeginTime(d) ;
SimpleDateFormat sdf = new SimpleDateFormat(fmt) ;
return sdf.format(firstDay) ;
}
}
1.maven导出hive的jar
2.部署到hive/lib下
3.删除之前的函数
drop [temporary] function xxx ;
4.注册函数
$hive>create function getdaybegin AS 'com.dateUtil.udf.DayBeginUDF';
$hive>create function getweekbegin AS 'com.dateUtil.udf.WeekBeginUDF';
$hive>create function getmonthbegin AS 'com.dateUtil.udf.MonthBeginUDF';
$hive>create function formattime AS'com.dateUtil.udf.FormatTimeUDF';
SQL语句是删减后的,重点不在SQL的写,而是UDF函数在hiveSQL中的使用。
活跃用户数据
//日活
select count(distinct deviceid) from startup_logs where ym = formattime(getdaybegin(),'yyyyMM') and day = formattime(getdaybegin(),'dd');
//周活
select count(distinct deviceid) from startup_logs where createdatms >= getweekbegin() and createdatms < getweekbegin(1) ;
//月活
select count(distinct deviceid) from startup_logs where createdatms >= getmonthbegin() and createdatms < getmonthbegin(1) ;
//一次查询出一周内每天的日活跃数。
select formattime(createdatms,'yyyy/MM/dd') day ,count(distinct deviceid) from startup_logs
where createdatms >= getweekbegin() and createdatms < getweekbegin(1)
group by day ;
//一次查询出一个月内每周的周活跃数。
select formattime(createdatms,'yyyy/MM/dd',0) week ,count(distinct deviceid) from startup_logs
where createdatms >= getweekbegin(-6) and createdatms < getweekbegin(-1)
group by week ;
//一次查询出过去的三个月内每月的月活跃数。
select formattime(createdatms,'yyyy/MM',0) month ,count(distinct deviceid) from startup_logs
where createdatms >= getmonthbegin(-4) and createdatms < getmonthbegin(-1)
group by month ;