学习电商数仓搭建时,遇到创建DIM层的时间维度表。这里时间维度表数据是十分固定的(一年一更新),要将这些数据提出出来生成文件以便导入DIM层的时间维度表中。
我们可以调用网络上免费的节假日API来实现对数据的整合和统计。
具体代码如下:
这里建议使用第二种getDate2的API,注意使用第二种时需要你自己去申请app_id和app_secret去替换
package com.time;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
/**
*
* 制作时间维度表数据(日期,周,周几,每月第几天,第几月,第几季度,年,是否为鸽子肉,节假日)
* @author csw
* @time 2022/4/20 9:55
*/
public class TimeProduce {
static BufferedReader in = null;
static BufferedWriter writer = null;
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\study\\data\\date.txt"), "UTF-8"));
// getDate1();
getDate2();
close();
}
/**
* @Author: csn
* @Description: 建立API调用连接
* @DateTime: 2022/4/20 14:14
* @Params:
* @Return 字符串(日期数据)
*/
public static StringBuffer getConnect(String url) {
URL url1;
StringBuffer sb = new StringBuffer();
try {
url1 = new URL(url);
HttpURLConnection connection = (HttpURLConnection) url1.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36)"); //防止报403错误。
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
String str;
while ((str = in.readLine()) != null) {
sb.append(str);
}
} catch (IOException e) {
e.printStackTrace();
}
return sb;
}
/**
* @Author: csn
* @Description: 调用第一种API
* @DateTime: 2022/4/20 14:14
* @Params:
* @Return
*/
public static void getDate1() {
// API接口URL
String url = "https://api.apihubs.cn/holiday/get?year=2022&cn=1&size=365";
// 返回获取的字符串
StringBuffer sb = getConnect(url);
// 返回一个JSON对象(将JSON字符串转化为JSON对象)
JSONObject jsonObject = JSONObject.parseObject(sb.toString());
// 获取JSON字段为“data”的数据并将其返回为一个JSON对象
JSONObject data = jsonObject.getJSONObject("data");
// 返回JSON对象的一个(链表)对象
JSONArray jsonArray = (JSONArray) data.get("list");
// 遍历链表
for (int i = 0; i < jsonArray.size(); i++) {
// 获取时间(20220101)
String t_date = jsonArray.getJSONObject(i).getString("date");
// 获取年(2022)
String year = jsonArray.getJSONObject(i).getString("year");
// 截取月(01)
int mouth = Integer.parseInt(t_date.substring(4, 6));
// 截取日(01)
int day = Integer.parseInt(t_date.substring(6, 8));
// 将数据格式化
String date = year + "-" + mouth + "-" + day;
// 获取当前日期所在一周第几天
String week = jsonArray.getJSONObject(i).getString("week");
// 获取日期在本年的第几周
String yearweek = jsonArray.getJSONObject(i).getString("yearweek").substring(4);
String workday;
String holiday;
// 判断是否为工作日(是为“1”。反之为“0”)
if ("工作日".equals(jsonArray.getJSONObject(i).getString("workday_cn"))) {
workday = "1";
} else workday = "0";
// 是否为假期节假日(是则返回节假日名称,反之返回“\N”)
if ("假期节假日".equals(jsonArray.getJSONObject(i).getString("holiday_recess_cn"))) {
holiday = jsonArray.getJSONObject(i).getString("holiday_cn");
} else holiday = "\\N";
// 整理格式,写入文件
String dates = date + "\t" + yearweek + "\t" + week + "\t" + day + "\t" + mouth + "\t" + year + "\t" + workday + "\t" + holiday;
System.out.println(dates);
try {
writer.write(dates + "\n");
writer.flush();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public static void getDate2() {
// 这里的API需要你去官网查看它的需求(app_id和app_secret需要你去申请替换)
String url = " https://www.mxnzp.com/api/holiday//list/year/2022?ignoreHoliday=false&app_id=XXX&app_secret=XXX";
StringBuffer buffer = getConnect(url);
JSONObject jsonObject = JSONObject.parseObject(buffer.toString());
// System.out.println(jsonObject);
JSONArray jsonArray = jsonObject.getJSONArray("data");
// 初始化季度(0)
int quarter = 0;
for (int i = 0; i < jsonArray.size(); i++) {
// System.out.println(jsonArray.getJSONObject(i).getString("year"));
// 年(2022)
String year = jsonArray.getJSONObject(i).getString("year");
// 月(1)
String month = jsonArray.getJSONObject(i).getString("month");
// 三月一季度(注意取模条件)
if ( Integer.parseInt(month) % 3 == 1) {
// 季度加一
quarter++;
}
// 获取“days”字段JSON对象
JSONArray jsonArray1 = jsonArray.getJSONObject(i).getJSONArray("days");
for (int j = 0; j < jsonArray1.size(); j++) {
// 日期(2022-01-01)
String date = jsonArray1.getJSONObject(j).getString("date");
// 一月第几天
String[] strings = date.split("-");
int day = Integer.parseInt(strings[2]);
// 一年第几周(这里接口返回的是每年与每年之间是连接的,我们这里不需要连接就只要当前年开始就为1,那么就需要对数据进行处理)
String weekOfYear = jsonArray1.getJSONObject(j).getString("weekOfYear");
// 转化为整数类型
int week = Integer.parseInt(weekOfYear) + 1;
// 进行判断(一月份且周数大于10),满足就说明是上一年的那么就让他为1
if ("1".equals(month) && week > 10) {
week = 1;
}
// 一周第几天
String weekDay = jsonArray1.getJSONObject(j).getString("weekDay");
// 0 工作日 1 假日 2 节假日 (如果ignoreHoliday参数为true,这个字段不返回)
String type = jsonArray1.getJSONObject(j).getString("type");
String work;
if ("0".equals(type)) {
work = "1";
}else work = "0";
// 国庆,休息日,工作日 (如果ignoreHoliday参数为true,这个字段不返回)
String typeDes = jsonArray1.getJSONObject(j).getString("typeDes");
String holiday;
if ("休息日".equals(typeDes) || "工作日".equals(typeDes)) {
holiday = "\\N";
}else holiday = typeDes;
// 整合数据
String data = date + "\t" + week + "\t" + weekDay + "\t" + day + "\t" + month + "\t" + quarter + "\t" + year + "\t" + work + "\t" + holiday;
try {
writer.write(data + "\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(data);
}
}
}
/**
* @Author: csn
* @Description: 关闭io流
* @DateTime: 2022/4/20 14:14
* @Params:
* @Return
*/
public static void close() {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
数据如下: