🐱背景🍎
Hello,小伙伴们,许久不见,最近遇到一个需求场景,关于物流时差的计算,要求算出差值是小时,且要剔除周日周六,网上很多文章,最好的也就是按照天剔除周日周六,小时级别,考虑的情况会非常多,要比天麻烦太多,最后无奈自己制作,分享给大家且记录一下,有需要的直接Copy下方核心代码 !😊 还请留下你的赞赞👍
☕️代码如下(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:59adjustToNextWeekday(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很久没写了,欢迎大佬提建议,其余有问题随时留言,一定回复~🐶 封面献上~