🐱背景🍎
Hello,小伙伴们,许久不见,最近遇到一个需求场景,关于物流时差的计算,要求算出差值是小时,且要剔除周日周六,网上很多文章,最好的也就是按照天剔除周日周六,小时级别,考虑的情况会非常多,要比天麻烦太多,最后无奈自己制作,分享给大家且记录一下,有需要的直接Copy下方核心代码 !😊 还请留下你的赞赞👍
☕️代码如下(Java)
java">package com.trendsi.udf;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class NonWeekendHoursDiffUDF extends UDF {
// public static void main(String[] args) {
// NonWeekendHoursDiffUDF udf = new NonWeekendHoursDiffUDF();
//
// // 测试用例1:开始时间是周一,结束时间是周三
// Text startTime1 = new Text("2023-03-02 00:00:00"); // 周一
// Text endTime1 = new Text("2023-03-03 00:00:00"); // 周三
// Integer hoursDiff1 = udf.evaluate(startTime1, endTime1);
// System.out.println("Case 1: Non-weekend hours difference = " + hoursDiff1);
//
// // 测试用例2:开始时间是周六,结束时间是下一个周一
// Text startTime2 = new Text("2023-03-04 09:00:00"); // 周六
// Text endTime2 = new Text("2023-03-06 09:00:00"); // 下一个周一
// Integer hoursDiff2 = udf.evaluate(startTime2, endTime2);
// System.out.println("Case 2: Non-weekend hours difference = " + hoursDiff2);
//
// // 测试用例3:开始时间和结束时间都是周六
// Text startTime3 = new Text("2023-03-04 09:00:00"); // 周六
// Text endTime3 = new Text("2023-03-05 09:00:00"); // 下一个周六
// Integer hoursDiff3 = udf.evaluate(startTime3, endTime3);
// System.out.println("Case 3: Non-weekend hours difference = " + hoursDiff3);
//
// // 测试用例4:开始时间是周五,结束时间是下一个周一的凌晨
// Text startTime4 = new Text("2023-03-03 13:00:00"); // 周五
// Text endTime4 = new Text("2023-03-20 00:00:00"); // 下一个周一的凌晨
// Integer hoursDiff4 = udf.evaluate(startTime4, endTime4);
// System.out.println("Case 4: Non-weekend hours difference = " + hoursDiff4);
// }
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public Integer evaluate(Text startTime, Text endTime) {
try {
Date startDate = sdf.parse(startTime.toString());
Date endDate = sdf.parse(endTime.toString());
Calendar startCal = Calendar.getInstance();
startCal.setTime(startDate);
Calendar endCal = Calendar.getInstance();
endCal.setTime(endDate);
// 如果开始时间是周末,则调整到下一个周一的0点
if (isWeekend(startCal)) {
adjustToNextWeekday(startCal, Calendar.MONDAY);
}
// 如果结束时间是周末,则调整到下一个周一的前一秒(即周日23:59:59)
if (isWeekend(endCal)) {
// 注意:这里应该是调整到下一个周一的前一天(周日),然后设置时间为23:59:59
adjustToNextWeekday(endCal, Calendar.MONDAY);
endCal.add(Calendar.DAY_OF_YEAR, -1);
endCal.set(Calendar.HOUR_OF_DAY, 23);
endCal.set(Calendar.MINUTE, 59);
endCal.set(Calendar.SECOND, 59);
}
int hoursDiff = 0;
while (startCal.before(endCal)) {
// 只在非周末时增加小时数
if (!isWeekend(startCal)) {
hoursDiff++;
}
startCal.add(Calendar.HOUR_OF_DAY, 1);
}
return hoursDiff;
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
private boolean isWeekend(Calendar cal) {
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
return dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY;
}
private void adjustToNextWeekday(Calendar cal, int dayOfWeek) {
int diff = dayOfWeek - cal.get(Calendar.DAY_OF_WEEK);
if (diff <= 0) {
diff += 7;
}
cal.add(Calendar.DAY_OF_YEAR, diff);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
}
private void adjustToWeekday(Calendar cal, int dayOfWeek) {
int diff = dayOfWeek - cal.get(Calendar.DAY_OF_WEEK);
if (diff > 0) {
cal.add(Calendar.DAY_OF_YEAR, diff);
} else {
cal.add(Calendar.DAY_OF_YEAR, diff - 7);
}
}
}
简单使用
- 前提:我这里用的IDEA,Maven,Java 这些基础不再赘述,网上很多教程,关于Hive内的使用如下:
-- 打包的jar包放到你想放的地方,执行下面命令,将jar包添加至hive
add jar hdfs://xxxxxxxx/udf/xxxxx.jar;
-- 根据类的全部包名创建hive函数
create function NonWeekendHoursDiffUDF as 'com.xxx.udf.xxx' using jar 'hdfs://xxxxxxxx/udf/xxxxx.jar'
-- 最后直接测试即可
select NonWeekendHoursDiffUDF('2024-09-09 02:20:00','2024-09-10 01:00:00')
Java很久没写了,欢迎大佬提建议,其余有问题随时留言,一定回复~🐶 封面献上~