import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
/**
* function:日期函数
* 参数:开始时间、结束时间和天数差
* 返回:数组,数组内是所有天数
* example:
* -----------------------------------------------------------------------|
* 起始日期 | 结束日期 | 天数差 | 返回日期数组 |
* -----------------------------------------------------------------------|
* 2021-01-01 | 2021-01-01 | 30 | ["2021-01-01"] |
* 2021-01-01 | 2021-01-15 | 30 | ["2021-01-01",......"2021-01-15"] |
* 2021-01-01 | 2021-02-15 | 30 | ["2021-01-01",......"2021-01-31"] |
* 2021-01-01 | null | 30 | ["2021-01-01",......"2021-01-31"] |
* -----------------------------------------------------------------------|
*
* @author
* @date 2021/4/30
*/
public class DateRangeUDF extends UDF {
private transient SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
private final Calendar calBegin = Calendar.getInstance();
private final Calendar calEnd = Calendar.getInstance();
/**
* 只传start_date,默认返回截至start_date当月月末的日期数组
* @param dBegin 开始日期
* @return ArrayList<String>
*/
public ArrayList<String> evaluate(Text dBegin) throws UDFArgumentLengthException {
if (dBegin==null){
throw new UDFArgumentLengthException("It requires start_date.");
}
try {
//格式化开始时间
calBegin.setTime(format.parse(dBegin.toString()));
// 获取当月月末日期
Calendar temBegin = Calendar.getInstance();
temBegin.setTime(format.parse(dBegin.toString()));
calBegin.add(Calendar.MONTH, 1);
calBegin.set(Calendar.DAY_OF_MONTH, 0);
Date lastday = calBegin.getTime();
//装返回的日期集合容器
ArrayList<String> Datelist = new ArrayList<>();
// 算上开始日期那一天
temBegin.add(Calendar.DAY_OF_MONTH, -1);
while (format.parse(format.format(lastday)).after(temBegin.getTime())) {
// 根据日历的规则,为给定的日历字段添加或减去指定的时间量
temBegin.add(Calendar.DAY_OF_MONTH, 1);
Datelist.add(format.format(temBegin.getTime()));
}
return Datelist;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* start_date 和 end_date都不为空,返回限定日期内日期数组
* start_date不为空,end_date为空,返回从start_date开始截至到月末的日期数组
*
* @param dBegin 开始日期
* @param dEnd 结束日期
* @return ArrayList<String>
*/
public ArrayList<String> evaluate(Text dBegin, Text dEnd) throws UDFArgumentException {
if (dBegin==null){
throw new UDFArgumentLengthException("It requires start_date.");
}
Date lastday;
//装返回的日期集合容器
ArrayList<String> Datelist = new ArrayList<>();
try {
//格式化开始时间
calBegin.setTime(format.parse(dBegin.toString()));
if (dEnd != null) {
//格式化结束时间
calEnd.setTime(format.parse(dEnd.toString()));
lastday = calEnd.getTime();
} else {
// 如果dEnd为空,则取dBegin当月最后一天作为dEnd
Calendar temBegin = Calendar.getInstance();
temBegin.setTime(format.parse(dBegin.toString()));
temBegin.add(Calendar.MONTH, 1);
temBegin.set(Calendar.DAY_OF_MONTH, 0);
lastday = temBegin.getTime();
}
calBegin.add(Calendar.DAY_OF_MONTH, -1);
while (format.parse(format.format(lastday)).after(calBegin.getTime())) {
// 根据日历的规则,为给定的日历字段添加或减去指定的时间量
calBegin.add(Calendar.DAY_OF_MONTH, 1);
Datelist.add(format.format(calBegin.getTime()));
}
return Datelist;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* start_date, end_date, dayNum都不为空,比较日期间隔与dayNum大小, 两者取其小返回限定日期内日期数组
* start_date不为空, end_date为空, dayNum为空 返回至start_date当月月末的日期数组
* start_date不为空, end_date为空, dayNum不为空 返回start_date加天数差范围内日期数组
* @param dBegin 开始日期
* @param dEnd 结束日期
* @param dayNum 天数差
* @return ArrayList<String>
*/
public ArrayList<String> evaluate(Text dBegin, Text dEnd, IntWritable dayNum) throws UDFArgumentException {
if (dBegin==null){
throw new UDFArgumentLengthException("It requires start_date.");
}
//装返回的日期集合容器
ArrayList<String> Datelist = new ArrayList<>();
try {
Date lastday;
//格式化开始时间
calBegin.setTime(format.parse(dBegin.toString()));
// 如果 end_date和dayNum都为空
if (dEnd == null && dayNum == null){
// 获取当月月末日期
Calendar temBegin = Calendar.getInstance();
temBegin.setTime(format.parse(dBegin.toString()));
temBegin.add(Calendar.MONTH, 1);
temBegin.set(Calendar.DAY_OF_MONTH, 0);
lastday = temBegin.getTime();
}else if (dEnd == null){
// end_date 为空,则取dBegin当月最后一天作为dEnd
Calendar calBegin1 = Calendar.getInstance();
calBegin1.setTime(format.parse(dBegin.toString()));
calBegin1.add(Calendar.DAY_OF_MONTH, dayNum.get());
lastday = calBegin1.getTime();
}else if (dayNum == null){
calEnd.setTime(format.parse(dEnd.toString()));
lastday = calEnd.getTime();
}else {
// end_date不为空,计算日期间隔相差天数
calEnd.setTime(format.parse(dEnd.toString()));
Long starTime = calBegin.getTime().getTime();
Long endTime = calEnd.getTime().getTime();
Long num = (endTime - starTime) / 24 / 60 / 60 / 1000;
// 判断日期间隔与天数差大小
if (num.intValue() >= dayNum.get()) {
Calendar calBegin1 = Calendar.getInstance();
calBegin1.setTime(format.parse(dBegin.toString()));
calBegin1.add(Calendar.DAY_OF_MONTH, dayNum.get());
lastday = calBegin1.getTime();
} else {
lastday = calEnd.getTime();
}
}
calBegin.add(Calendar.DAY_OF_MONTH, -1);
// 每次循环给calBegin日期加一天,直到calBegin.getTime()时间等于dEnd
while (format.parse(format.format(lastday)).after(calBegin.getTime())) {
// 根据日历的规则,为给定的日历字段添加或减去指定的时间量
calBegin.add(Calendar.DAY_OF_MONTH, 1);
Datelist.add(format.format(calBegin.getTime()));
}
return Datelist;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
09-25
1001
08-04
3401
06-27
07-15
2637