前言
最近有好多小伙伴私信我,遇到一个问题在做数仓项目中遇到了瓶颈
有的需求需要根据节假日去统计信息。但是由于节假日每年都不一样目前提供的方法没法动态的去获取关于节假日的信息。所以自己去编写一个实现类就完成这个操作。
一、需求描述
在Hive中生成一个表用来保存关于日期的工具。目前大公司为了提高效率。创建一个日期表 将需要的数据保存到日期表中,使用的时候只需要join下即可实现次功能。
名 | 类型 | 示例值 | 中文名 |
---|---|---|---|
date_key | string | 20000101 | 代理键 |
date_value | string | 2000-01-01 | 年-月-日 |
day_in_year | string | 1 | 当年的第几天 |
day_in_month | string | 1 | 当月的第几天 |
is_first_day_in_month | string | y | 是否月的第一天 |
is_last_day_in_month | string | n | 是否月的最后一天 |
weekday | string | 星期一 | 星期 |
week_in_month | string | 1 | 月的第几个星期 |
is_first_day_in_week | string | y、n | 是否周一 |
is_dayoff | string | y、n | 是否休息日 |
is_workday | string | y、n | 是否工作日 |
is_holiday | string | y、n | 是否国家法定节假日 |
date_type | string | workday、weekend、holiday工作日、周末、法定节假日 | 日期类型工作日:workday国家法定节假日:holiday休息日:weekend |
month_number | string | 1、2、..、12 | 月份 |
year | string | 2000 | 年份 |
quarter_name | string | Q1 | 季度名称 |
quarter_number | string | 1 | 季度 |
year_quarter | string | 2000-Q1 | 年-季度 |
year_month_number | string | 2000-01 | 年-月份 |
预期结果数据
dim_date.date_value | dim_date.day_in_month | dim_date.is_first_day_in_month | dim_date.is_last_day_in_month | dim_date.weekday | dim_date.week_in_month | dim_date.is_first_day_in_week | dim_date.is_dayoff | dim_date.is_workday | dim_date.is_holiday | dim_date.date_type | dim_date.month_number | dim_date.year | dim_date.year_month_number | dim_date.quarter_name | dim_date.quarter_number | dim_date.year_quarter |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
20200113 | 2020-01-13 | 2020 | 13 | n | n | 1 | 3 | y | n | y | n | workday | 01 | 2020 | 2020-01 | Q1 |
20200112 | 2020-01-12 | 2020 | 12 | n | n | 7 | 3 | n | n | y | n | weekend | 01 | 2020 | 2020-01 | Q1 |
20200111 | 2020-01-11 | 2020 | 11 | n | n | 6 | 2 | n | n | y | n | weekend | 01 | 2020 | 2020-01 | Q1 |
20200110 | 2020-01-10 | 2020 | 10 | n | n | 5 | 2 | n | n | y | n | workday | 01 | 2020 | 2020-01 | Q1 |
20200109 | 2020-01-09 | 2020 | 9 | n | n | 4 | 2 | n | n | y | n | workday | 01 | 2020 | 2020-01 | Q1 |
20200108 | 2020-01-08 | 2020 | 8 | n | n | 3 | 2 | n | n | y | n | workday | 01 | 2020 | 2020-01 | Q1 |
20200107 | 2020-01-07 | 2020 | 7 | n | n | 2 | 2 | n | n | y | n | workday | 01 | 2020 | 2020-01 | Q1 |
20200106 | 2020-01-06 | 2020 | 6 | n | n | 1 | 2 | y | n | y | n | workday | 01 | 2020 | 2020-01 | Q1 |
20200105 | 2020-01-05 | 2020 | 5 | n | n | 7 | 2 | n | n | y | n | weekend | 01 | 2020 | 2020-01 | Q1 |
20200104 | 2020-01-04 | 2020 | 4 | n | n | 6 | 1 | n | n | y | n | weekend | 01 | 2020 | 2020-01 | Q1 |
20200103 | 2020-01-03 | 2020 | 3 | n | n | 5 | 1 | n | n | y | n | workday | 01 | 2020 | 2020-01 | Q1 |
20200102 | 2020-01-02 | 2020 | 2 | n | n | 4 | 1 | n | n | y | n | workday | 01 | 2020 | 2020-01 | Q1 |
二、实现思路
我们可以通过爬虫的去获取官网上的节假日信息,但是对于小白了来说是有点困难的,于是就有好多大佬写了一些工具来提供我们来使用https://github.com/Haoshenqi0123/holiday 我们可以通过 大佬提供出来的API 接口发送HTTP请求来获取数据进行解析即可获取我们想要的数据。
三、编写代码
实现步骤:
- 创建hive表 用来存储结果数据
- 编写JavaScript代码
- 使用kettle 整个流程连接起来
3.1 创建hive表
代码语言:javascript复制create database kettle;
use kettle;
CREATE TABLE kettle.`date`(
`date_key` string,
`date_value` string,
`day_in_year` string,
`day_in_month` string,
`is_first_day_in_month` string,
`is_last_day_in_month` string,
`weekday` string,
`week_in_month` string,
`is_first_day_in_week` string,
`is_dayoff` string,
`is_workday` string,
`is_holiday` string,
`date_type` string,
`month_number` string,
`year` string,
`year_month_number` string,
`quarter_name` string,
`quarter_number` string,
`year_quarter` string)
ROW FORMAT SERDE
'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
'hdfs://node01:8020/user/hive/warehouse/kettle.db'
3.2 编写 JavaScript 代码
代码语言:javascript复制
// 1. 初始化上游变量
var initDateStr = "2020-01-01";
var locale = new java.util.Locale("en", "us");
var calendar = java.util.Calendar.getInstance();
var sdf = new java.text.SimpleDateFormat("yyyy-MM-dd", locale);
var initDate = sdf.parse(initDateStr);
calendar.setTime(initDate);
calendar.add(java.util.Calendar.DAY_OF_MONTH, setup);
var curDate = calendar.getTime();
// 2. 生成维度数据
// 2.1 生成代理键
sdf.applyPattern("yyyyMMdd");
var date_key = sdf.format(curDate);
// 2.2 年-月-日
sdf.applyPattern("yyyy-MM-dd");
var date_value = sdf.format(curDate);
// 2.3 当年的第几天
var day_in_year = calendar.get(java.util.Calendar.YEAR) "";
// 2.4 当月的第几天
var day_in_month = calendar.get(java.util.Calendar.DAY_OF_MONTH) "";
// 2.5 是否为当月的第一天
var is_first_day_in_month = day_in_month.equals("1") ? "y":"n";
// 2.6 是否为当月最后一天
// 1. 加一天
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
var is_last_day_in_month = calendar.get(java.util.Calendar.DAY_OF_MONTH) == 1 ? "y":"n";
// 2. 减回去
calendar.add(java.util.Calendar.DAY_OF_MONTH, -1);
// 2.7 星期
var weekday = (calendar.get(java.util.Calendar.DAY_OF_WEEK) - 1) "";
if(weekday.equals("0")) {
weekday = "7";
}
// 2.8 月的第几个星期
sdf.applyPattern("W");
var week_in_month = sdf.format(curDate);
// 2.9 是否周一
var is_first_day_in_week = calendar.get(java.util.Calendar.DAY_OF_WEEK) == java.util.Calendar.MONDAY ? "y":"n";
// 2.10 是否休息日
var is_dayoff = "n";
// 2.11 是否工作日
var is_workday = "n";
// 2.12 是否国家法定节假日
var is_holiday = "n";
// 2.12 国家法定节假日获取URL
//var holiday_url = "http://timor.tech/api/holiday/info/" date_value;
var holiday_url = "http://api.haoshenqi.top/holiday?date=" date_value
// 2.13 日期类型
var date_type = "workday";
// 2.14 月份
sdf.applyPattern("MM");
var month_number = sdf.format(curDate);
// 2.15 年份
sdf.applyPattern("yyyy");
var year = sdf.format(curDate);
// 2.16 年份-月份
sdf.applyPattern("yyyy-MM");
var year_month_number = sdf.format(curDate);
// 2.16 季度名称、季度、年季度
var quarter_name = "";
var quarter_number = "";
var year_quarter = "";
switch (calendar.get(java.util.Calendar.MONTH)) {
case java.util.Calendar.FEBRUARY:
case java.util.Calendar.JANUARY:
case java.util.Calendar.MARCH:
quarter_name = "Q1";
quarter_number = "1";
year_quarter = year "-" quarter_name;
break;
case java.util.Calendar.APRIL:
case java.util.Calendar.MAY:
case java.util.Calendar.JUNE:
quarter_name = "Q2";
quarter_number = "2";
year_quarter = year "-" quarter_name;
break;
case java.util.Calendar.JULY:
case java.util.Calendar.AUGUST:
case java.util.Calendar.SEPTEMBER:
quarter_name = "Q3";
quarter_number = "3";
year_quarter = year "-" quarter_name;
break;
case java.util.Calendar.OCTOBER:
case java.util.Calendar.NOVEMBER:
case java.util.Calendar.DECEMBER:
quarter_name = "Q4";
quarter_number = "4";
year_quarter = year "-" quarter_name;
break;
}
3.3 kettle整个流程
整体流程
3.4 运行结果图
运行结果图
小结
好了到这里我们就成功的实现了这个需求,其实kettle 上还有很多好玩的功能组件,也可以进行一个尝试。喜欢的朋友可以给你一键三连哦,源码获取微信搜搜公众号【大数据老哥】