Hive自定义函数—剔除周日周六(小时级别)

news/2024/11/5 14:42:08 标签: hive, hadoop, 数据仓库, java

🐱背景🍎


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很久没写了,欢迎大佬提建议,其余有问题随时留言,一定回复~🐶 封面献上~

在这里插入图片描述


http://www.niftyadmin.cn/n/5739585.html

相关文章

算法笔记-Day09(字符篇)

151. 反转字符串中的单词 class Solution {public String reverseWords(String s) {int lens.length(),count0;StringBuffer tempnew StringBuffer();StringBuffer ansnew StringBuffer();for(int i0;i<len;i){if(s.charAt(i)! &&(i0 || s.charAt(i-1) )){while(i&l…

DevExpress中文教程 - 如何使用AI模型检查HTML编辑中的语法?

DevExpress .NET MAUI多平台应用UI组件库提供了用于Android和iOS移动开发的高性能UI组件&#xff0c;该组件库包括数据网格、图表、调度程序、数据编辑器、CollectionView和选项卡组件等。 目前许多开发人员正在寻找多种方法将AI添加到解决方案中&#xff08;这通常比想象的要…

站长用站群安全特性怎么样

1. 高配置资源&#xff1a;站群服务器在CPU、内存、带宽等资源上通常会有较高的配置&#xff0c;这不仅确保了每个网站都能流畅运行&#xff0c;同时也为安全防护提供了硬件基础。 2. 易于管理&#xff1a;站群服务器提供集中式的控制面板或管理工具&#xff0c;使得网站管理员…

2024年前三季度币安、OKX等五大交易所上币表现分析

随着加密市场竞争的加剧&#xff0c;头部交易所逐渐在上币策略、代币选择、交易活跃度等方面采取了不同的应对策略。Animoca Digital Research近期发布的一份报告&#xff0c;通过对币安、OKX、Bitget、KuCoin和Bybit五大交易所2024年前三季度的上币情况进行了详细分析。本文将…

《Python游戏编程入门》注-第4章9

2.3 移动挡板 2.3.1 监听鼠标事件 挡板是通过鼠标来控制的,因此需要监听鼠标事件,在图7代码的基础上添加如图8所示的代码。 图15 监听鼠标事件的代码 其中,mouse_x和mouse_y分别表示鼠标当前位置的横纵坐标,这两个变量在while True循环之前定义,如图16所示。

数据结构题集-第二章-线性表-单链表的插入

说明 本文参照严蔚敏《数据结构(C语言版)题集》一书中包含的问答题和算法设计题目&#xff0c;提供解答和算法的解决方案。请读者在自己已经解决了某个题目或进行了充分的思考之后&#xff0c;再参考本解答&#xff0c;以保证复习效果。由于作者水平所限&#xff0c;本解答中一…

AD如何画PCB的外框

绘制步骤 ‌选择Mechanical层‌&#xff1a;首先&#xff0c;需要选择Mechanical层来进行外框的绘制。‌绘制外框‌&#xff1a;按下“p”键&#xff0c;再按“L”键开始绘制外框。根据需要的尺寸&#xff0c;绘制出四条边&#xff0c;形成外框。‌自定义板框尺寸‌&#xff1…

【系统架构设计师】2022年真题论文: 论区块链技术及应用(包括解题思路和素材)

更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 真题题目(2022年 试题3)解题思路区块链技术原理区块链技术的关键特性区块链技术的应用领域论文素材参考真题题目(2022年 试题3) 区块链作为一种分布式记账技术,目前已经被应用到了资产管理、物联网、医疗管理…