|
@@ -0,0 +1,503 @@
|
|
|
+package com.example.getweather.service;
|
|
|
+
|
|
|
+import cn.hutool.db.Db;
|
|
|
+import cn.hutool.db.Entity;
|
|
|
+import cn.hutool.http.HttpUtil;
|
|
|
+import cn.hutool.json.JSONArray;
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import com.example.getweather.entity.DistrictCodeDO;
|
|
|
+import com.example.getweather.entity.HeFengDay;
|
|
|
+import com.example.getweather.util.WeixinPush;
|
|
|
+import com.taosdata.jdbc.TSDBDriver;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.validation.annotation.Validated;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.sql.Connection;
|
|
|
+import java.sql.DriverManager;
|
|
|
+import java.sql.Statement;
|
|
|
+import java.sql.Timestamp;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.time.Instant;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.ZonedDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+@Validated
|
|
|
+@Slf4j
|
|
|
+public class GetWeatherGeovisearth {
|
|
|
+ @Resource
|
|
|
+ private WeixinPush weixinPush;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据风速获取对应风力等级
|
|
|
+ * 2025-01-09 改为km/h单位
|
|
|
+ *
|
|
|
+ * @param speed 风速,单位为 km/h
|
|
|
+ * @return 风力等级
|
|
|
+ */
|
|
|
+ public static int speedLevel(String speed) {
|
|
|
+ BigDecimal val = new BigDecimal(speed);
|
|
|
+ //<0.3 无风 0级
|
|
|
+ if (val.compareTo(new BigDecimal("1")) < 0) {
|
|
|
+ return 0;
|
|
|
+ } else if (val.compareTo(new BigDecimal("6")) < 0) {
|
|
|
+ //0.3-1.6 微风徐徐 1级
|
|
|
+ return 1;
|
|
|
+ } else if (val.compareTo(new BigDecimal("12")) < 0) {
|
|
|
+ //1.6-3.4 清风 2级
|
|
|
+ return 2;
|
|
|
+ } else if (val.compareTo(new BigDecimal("20")) < 0) {
|
|
|
+ //3.4-5.5 树叶摇摆 3级
|
|
|
+ return 3;
|
|
|
+ } else if (val.compareTo(new BigDecimal("29")) < 0) {
|
|
|
+ //5.5-8.0 树枝摇动 4级
|
|
|
+ return 4;
|
|
|
+ } else if (val.compareTo(new BigDecimal("39")) < 0) {
|
|
|
+ //8.0-10.8 风吹折小树 5级
|
|
|
+ return 5;
|
|
|
+ } else if (val.compareTo(new BigDecimal("50")) < 0) {
|
|
|
+ //10.8-13.9 树枝折断 6级
|
|
|
+ return 6;
|
|
|
+ } else if (val.compareTo(new BigDecimal("62")) < 0) {
|
|
|
+ //13.9-17.2 风吹倒树木 7级
|
|
|
+ return 7;
|
|
|
+ } else if (val.compareTo(new BigDecimal("75")) < 0) {
|
|
|
+ //17.2-20.8 风吹断大树 8级
|
|
|
+ return 8;
|
|
|
+ } else if (val.compareTo(new BigDecimal("89")) < 0) {
|
|
|
+ //20.8-24.5 强风 9级
|
|
|
+ return 9;
|
|
|
+ } else if (val.compareTo(new BigDecimal("103")) < 0) {
|
|
|
+ //24.5-28.5 狂风 10级
|
|
|
+ return 10;
|
|
|
+ } else if (val.compareTo(new BigDecimal("117")) < 0) {
|
|
|
+ //28.5-32.7 暴风 11级
|
|
|
+ return 11;
|
|
|
+ } else if (val.compareTo(new BigDecimal("134")) < 0) {
|
|
|
+ //32.7-37.0 大暴风 12级
|
|
|
+ return 12;
|
|
|
+ } else if (val.compareTo(new BigDecimal("150")) < 0) {
|
|
|
+ //37.0-41.5 飓风 13级
|
|
|
+ return 13;
|
|
|
+ } else if (val.compareTo(new BigDecimal("167")) < 0) {
|
|
|
+ //41.5-46.2 强飓风 14级
|
|
|
+ return 14;
|
|
|
+ } else if (val.compareTo(new BigDecimal("184")) < 0) {
|
|
|
+ //46.2-50.9 猛烈飓风 15级
|
|
|
+ return 15;
|
|
|
+ } else if (val.compareTo(new BigDecimal("202")) < 0) {
|
|
|
+ //50.9-56.1 毁灭性飓风 16级
|
|
|
+ return 16;
|
|
|
+ } else {
|
|
|
+ //56.1-61.3 超级飓风 17级
|
|
|
+ return 17;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Timestamp convertStringToTimestamp(String dateStr) {
|
|
|
+ LocalDate localDate = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyyMMdd")); // 解析 yyyyMMdd
|
|
|
+ return Timestamp.valueOf(localDate.atStartOfDay()); // 转换为当天的开始时间
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Timestamp convertStringToTimestampYMD(String dateStr) {
|
|
|
+ LocalDate localDate = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd")); // 解析 yyyyMMdd
|
|
|
+ return Timestamp.valueOf(localDate.atStartOfDay()); // 转换为当天的开始时间
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Timestamp convertStringToTimestampHH(String dateStr) {
|
|
|
+ LocalDate localDate = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyyMMddHH")); // 解析 yyyyMMddHH
|
|
|
+ return Timestamp.valueOf(localDate.atStartOfDay()); // 转换为当天的开始时间
|
|
|
+ }
|
|
|
+
|
|
|
+ public static int extractLevel(String levelStr) {
|
|
|
+ if (levelStr == null || levelStr.isEmpty()) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用正则表达式匹配数字
|
|
|
+ java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("(\\d+)");
|
|
|
+ java.util.regex.Matcher matcher = pattern.matcher(levelStr);
|
|
|
+
|
|
|
+ if (matcher.find()) {
|
|
|
+ return Integer.parseInt(matcher.group(1));
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void download() {
|
|
|
+ List<String> areaCodes = new ArrayList<>();
|
|
|
+ List<DistrictCodeDO> districtCodeDOList = new ArrayList<>();
|
|
|
+ List<DistrictCodeDO> districtCodeDOList1 = new ArrayList<>();
|
|
|
+ boolean isApiQuotaExhausted = false; // 引入标志变量
|
|
|
+ try {
|
|
|
+ List<Entity> dictList = Db.use().findAll("system_dict_data");
|
|
|
+ for (Entity entity : dictList) {
|
|
|
+ String name = entity.getStr("label");
|
|
|
+ if (name.contains("area_code")) {
|
|
|
+ String code = entity.getStr("value");
|
|
|
+ String[] s = code.split(",");
|
|
|
+ areaCodes = Arrays.asList(s);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ List<Entity> districtCodes = Db.use().findAll("jy_district_code");
|
|
|
+ for (Entity e : districtCodes) {
|
|
|
+ DistrictCodeDO districtCodeDO = new DistrictCodeDO();
|
|
|
+ districtCodeDO.setCode(e.getStr("code"));
|
|
|
+ districtCodeDO.setName(e.getStr("name"));
|
|
|
+ districtCodeDO.setLevel(Integer.parseInt(e.getStr("level")));
|
|
|
+ districtCodeDO.setType(Integer.parseInt(e.getStr("type")));
|
|
|
+ districtCodeDO.setAbname(e.getStr("abname"));
|
|
|
+ districtCodeDO.setPid(Integer.parseInt(e.getStr("pid")));
|
|
|
+ districtCodeDO.setLat(!Objects.equals(e.getStr("lat"), "") && e.getStr("lat") != null ? new BigDecimal(e.getStr("lat")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
|
|
|
+ districtCodeDO.setLng(!Objects.equals(e.getStr("lng"), "") && e.getStr("lng") != null ? new BigDecimal(e.getStr("lng")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
|
|
|
+ districtCodeDOList.add(districtCodeDO);
|
|
|
+ }
|
|
|
+ List<Entity> districtCodes1 = Db.use().findAll("jy_power_station");
|
|
|
+ for (Entity e : districtCodes1) {
|
|
|
+ DistrictCodeDO districtCodeDO = new DistrictCodeDO();
|
|
|
+ districtCodeDO.setCode(e.getStr("code"));
|
|
|
+ districtCodeDO.setName(e.getStr("name"));
|
|
|
+ districtCodeDO.setLat(!Objects.equals(e.getStr("lat"), "") && e.getStr("lat") != null ? new BigDecimal(e.getStr("lat")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
|
|
|
+ districtCodeDO.setLng(!Objects.equals(e.getStr("lng"), "") && e.getStr("lng") != null ? new BigDecimal(e.getStr("lng")).setScale(6, RoundingMode.HALF_UP).doubleValue() : 0d);
|
|
|
+ districtCodeDOList1.add(districtCodeDO);
|
|
|
+ }
|
|
|
+ String jdbcUrl = "jdbc:TAOS://192.168.12.241:29500/etadm_local?user=root&password=taosdata";
|
|
|
+ Properties connProps = new Properties();
|
|
|
+ connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
|
|
+ connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
|
|
+ connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
|
|
+ Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
|
|
|
+ //省份
|
|
|
+ for (String code : areaCodes) {
|
|
|
+ //中科星图 只接甘肃
|
|
|
+ if (code.equals("620000")) {
|
|
|
+ if (isApiQuotaExhausted) break; // 检查标志变量
|
|
|
+ List<DistrictCodeDO> shiList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(code)).collect(Collectors.toList());
|
|
|
+ //市
|
|
|
+ for (DistrictCodeDO d : shiList) {
|
|
|
+ if (isApiQuotaExhausted) break; // 检查标志变量
|
|
|
+ List<DistrictCodeDO> quList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(d.getCode())).collect(Collectors.toList());
|
|
|
+ String url;
|
|
|
+ String url120;
|
|
|
+ String caiyunUrl;
|
|
|
+ String location = d.getLng() + "," + d.getLat();
|
|
|
+ //xmo综合数据查询
|
|
|
+ url = "https://api.open.geovisearth.com/v2/cn/city/basic?token=15d7d762ca3eca516c8344a24c8af2b6&location=" + location + "&yesterday=false";
|
|
|
+ url120 = "https://api.open.geovisearth.com/v2/precision_grid/forecast/day?start=" + getNowDateString() + "&end=" + getSevenDaysLater() + "&token=15d7d762ca3eca516c8344a24c8af2b6&meteCodes=ws_day,ws_night,wd_day,wd_night&location=" + location;
|
|
|
+ caiyunUrl = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + location + "/weather?alert=true&dailysteps=7&hourlysteps=72";
|
|
|
+ isApiQuotaExhausted = analysisGeovisearth(url, url120, caiyunUrl, d.getCode(), d.getName(), conn); // 传递标志变量
|
|
|
+ if (isApiQuotaExhausted) break; // 检查标志变量
|
|
|
+ //区
|
|
|
+ for (DistrictCodeDO q : quList) {
|
|
|
+ if (isApiQuotaExhausted) break; // 检查标志变量
|
|
|
+ location = q.getLng() + "," + q.getLat();
|
|
|
+ url = "https://api.open.geovisearth.com/v2/cn/city/basic?token=15d7d762ca3eca516c8344a24c8af2b6&location=" + location + "&yesterday=false";
|
|
|
+ url120 = "https://api.open.geovisearth.com/v2/precision_grid/forecast/day?start=" + getNowDateString() + "&end=" + getSevenDaysLater() + "&token=15d7d762ca3eca516c8344a24c8af2b6&meteCodes=ws_day,ws_night,wd_day,wd_night&location=" + location;
|
|
|
+ caiyunUrl = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + location + "/weather?alert=true&dailysteps=7&hourlysteps=72";
|
|
|
+ isApiQuotaExhausted = analysisGeovisearth(url, url120, caiyunUrl, q.getCode(), q.getName(), conn); // 传递标志变量
|
|
|
+ if (isApiQuotaExhausted) break; // 检查标志变量
|
|
|
+ //线程睡5秒 防止请求过快
|
|
|
+ //花钱了 硬气 不管他
|
|
|
+ //Thread.sleep(5000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //2025-07-18 新增 甘肃库里 powerstation表里场站的经纬度也获取数据, td表的tag是场站编号而不是地区编号
|
|
|
+ for (DistrictCodeDO d : districtCodeDOList1) {
|
|
|
+ String location = d.getLng() + "," + d.getLat();
|
|
|
+ String url = "https://api.open.geovisearth.com/v2/cn/city/basic?token=15d7d762ca3eca516c8344a24c8af2b6&location=" + location + "&yesterday=false";
|
|
|
+ String url120 = "https://api.open.geovisearth.com/v2/precision_grid/forecast/day?start=" + getNowDateString() + "&end=" + getSevenDaysLater() + "&token=15d7d762ca3eca516c8344a24c8af2b6&meteCodes=ws_day,ws_night,wd_day,wd_night&location=" + location;
|
|
|
+ String caiyunUrl = "https://api.caiyunapp.com/v2.6/SRQIFijX5MGtdmhe/" + location + "/weather?alert=true&dailysteps=7&hourlysteps=72";
|
|
|
+ if (isApiQuotaExhausted) break; // 检查标志变量
|
|
|
+ isApiQuotaExhausted = analysisGeovisearth(url, url120, caiyunUrl, d.getCode(), d.getName(), conn); // 传递标志变量
|
|
|
+ if (isApiQuotaExhausted) break; // 检查标志变量
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ conn.close();
|
|
|
+ String alarm = "电力交易系统在获取甘肃日级天气数据时报错, 请尽快查看";
|
|
|
+ String description = "接口调用异常";
|
|
|
+ if (isApiQuotaExhausted) {
|
|
|
+ //给企业微信发送消息
|
|
|
+ weixinPush.sendMessageBot(alarm, description);
|
|
|
+ } else {
|
|
|
+ alarm = "电力交易系统甘肃每日天气数据全部下载完毕";
|
|
|
+ description = "接口调用成功";
|
|
|
+ weixinPush.sendMessageBot(alarm, description);
|
|
|
+ log.info("甘肃每日天气数据全部下载完毕");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param url 星图15天
|
|
|
+ * @param url120 星图网格7天
|
|
|
+ * @param caiyunUrl 彩云7天
|
|
|
+ * @param areaCode
|
|
|
+ * @param name
|
|
|
+ * @param conn 星图15天数据没有风速风向辐照度
|
|
|
+ * 星图网格7天没有辐照度
|
|
|
+ * 彩云7天只用辐照度
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public boolean analysisGeovisearth(String url, String url120, String caiyunUrl, String areaCode, String name, Connection conn) {
|
|
|
+ log.info("开始下载地区:{} 的天气数据", name);
|
|
|
+ try {
|
|
|
+ Statement ps = conn.createStatement();
|
|
|
+ String body = HttpUtil.createGet(url).execute().charset("utf-8").body();
|
|
|
+ String body120 = HttpUtil.createGet(url120).execute().charset("utf-8").body();
|
|
|
+ JSONObject jsonObject = JSONUtil.parseObj(body);
|
|
|
+ JSONObject jsonObject120 = JSONUtil.parseObj(body120);
|
|
|
+ String bodyCaiyun = HttpUtil.createGet(caiyunUrl).header("apikey", "51bcabf8-3a5e-41e9-8bf2-b7676936cb22").execute().charset("utf-8").body();
|
|
|
+ JSONObject jsonObjectCaiyun = JSONUtil.parseObj(bodyCaiyun);
|
|
|
+ JSONObject resultCaiyun = JSONUtil.parseObj(jsonObjectCaiyun.get("result"));
|
|
|
+ JSONObject dailyCaiyun = JSONUtil.parseObj(resultCaiyun.get("daily"));
|
|
|
+ JSONArray dswrf = JSONUtil.parseArray(dailyCaiyun.get("dswrf"));
|
|
|
+ //log.info("获取到的数据为:{}", body);
|
|
|
+ if (jsonObject.toString().contains("API call limit has been reached") || jsonObject120.toString().contains("API call limit has been reached")) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ //日数据 15天
|
|
|
+ JSONObject result = JSONUtil.parseObj(jsonObject.get("result"));
|
|
|
+ JSONObject result120 = JSONUtil.parseObj(jsonObject120.get("result"));
|
|
|
+ JSONArray datas = JSONUtil.parseArray(result.get("datas"));
|
|
|
+ JSONArray datas120 = JSONUtil.parseArray(result120.get("datas"));
|
|
|
+ //日数据写入
|
|
|
+ List<HeFengDay> heFengDayList = new ArrayList<>();
|
|
|
+ List<HeFengDay> heFengDay120List = new ArrayList<>();
|
|
|
+ List<HeFengDay> caiyunList = new ArrayList<>();
|
|
|
+ //数据结果是16天 D-1 到 D+14
|
|
|
+ if (datas.size() == 15) {
|
|
|
+ for (int i = 0; i < datas.size(); i++) {
|
|
|
+ JSONObject data = (JSONObject) datas.get(i);
|
|
|
+ HeFengDay heFengDay = new HeFengDay();
|
|
|
+ heFengDay.setTs(convertStringToTimestamp(data.get("fc_time").toString()));
|
|
|
+ heFengDay.setTextDay(data.get("wp_day").toString());
|
|
|
+ heFengDay.setTextNight(data.get("wp_night").toString());
|
|
|
+ heFengDay.setTempMax(Float.parseFloat(data.get("tem_max").toString()));
|
|
|
+ heFengDay.setTempMin(Float.parseFloat(data.get("tem_min").toString()));
|
|
|
+ heFengDay.setWindDirDay(data.get("wd_day").toString());
|
|
|
+ heFengDay.setWindDirNight(data.get("wd_night").toString());
|
|
|
+ heFengDay.setWindScaleDay(extractLevel(data.get("ws_day").toString()));
|
|
|
+ heFengDay.setWindScaleNight(extractLevel(data.get("ws_night").toString()));
|
|
|
+ heFengDay.setPrecip(Integer.parseInt(data.get("rh_max").toString()));
|
|
|
+ heFengDay.setPressure(Integer.parseInt(data.get("prs").toString()));
|
|
|
+ heFengDay.setHumidity(Float.parseFloat(data.get("pre_day").toString()) + Float.parseFloat(data.get("pre_night").toString()));
|
|
|
+ heFengDayList.add(heFengDay);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ log.info("{} 的星图日数据不足15天,不入库!", name);
|
|
|
+ }
|
|
|
+ if (datas120.size() == 7) {
|
|
|
+ for (int i = 0; i < datas120.size(); i++) {
|
|
|
+ JSONObject data = (JSONObject) datas120.get(i);
|
|
|
+ HeFengDay heFengDay = new HeFengDay();
|
|
|
+ heFengDay.setTs(convertStringToTimestampYMD(data.get("fc_time").toString()));
|
|
|
+ JSONArray hour = JSONUtil.parseArray(data.get("values"));
|
|
|
+ heFengDay.setWindSpeedDay(Float.parseFloat(hour.get(0).toString()));
|
|
|
+ heFengDay.setWindSpeedNight(Float.parseFloat(hour.get(1).toString()));
|
|
|
+ heFengDay.setWindSpeedMDay(Float.parseFloat(hour.get(0).toString()));
|
|
|
+ heFengDay.setWindSpeedMNight(Float.parseFloat(hour.get(1).toString()));
|
|
|
+ heFengDay.setWind360Day(Float.parseFloat(hour.get(2).toString()));
|
|
|
+ heFengDay.setWind360Night(Float.parseFloat(hour.get(3).toString()));
|
|
|
+ heFengDay120List.add(heFengDay);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ log.info("{} 的星图精细化网格日数据不足7天,不入库!", name);
|
|
|
+ }
|
|
|
+ if (dswrf.size() == 7) {
|
|
|
+ for (int j = 0; j < dswrf.size(); j++) {
|
|
|
+ JSONObject data = JSONUtil.parseObj(dswrf.get(j));
|
|
|
+ HeFengDay heFengDay = new HeFengDay();
|
|
|
+ heFengDay.setTs(getTimestamp(data.get("date").toString()));
|
|
|
+ heFengDay.setDswrf(Float.parseFloat(data.get("avg").toString()));
|
|
|
+ caiyunList.add(heFengDay);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ log.info("{} 的彩云综合预报数据不足7天,不入库!", name);
|
|
|
+ }
|
|
|
+ //捏合数据
|
|
|
+ // 使用Map按日期进行数据合并,更加精确
|
|
|
+ Map<Timestamp, HeFengDay> mergedMap = new HashMap<>();
|
|
|
+
|
|
|
+ // 将第一个列表数据放入Map
|
|
|
+ for (HeFengDay item : heFengDayList) {
|
|
|
+ mergedMap.put(item.getTs(), item);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 合并第二个列表数据
|
|
|
+ for (HeFengDay item : heFengDay120List) {
|
|
|
+ Timestamp date = item.getTs();
|
|
|
+ if (mergedMap.containsKey(date)) {
|
|
|
+ HeFengDay existing = mergedMap.get(date);
|
|
|
+ existing.setWindSpeedDay(item.getWindSpeedDay());
|
|
|
+ existing.setWindSpeedNight(item.getWindSpeedNight());
|
|
|
+ existing.setWindSpeedMDay(item.getWindSpeedMDay());
|
|
|
+ existing.setWindSpeedMNight(item.getWindSpeedMNight());
|
|
|
+ existing.setWind360Day(item.getWind360Day());
|
|
|
+ existing.setWind360Night(item.getWind360Night());
|
|
|
+ } else {
|
|
|
+ mergedMap.put(date, item);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 合并第三个列表数据
|
|
|
+ for (HeFengDay item : caiyunList) {
|
|
|
+ Timestamp date = item.getTs();
|
|
|
+ if (mergedMap.containsKey(date)) {
|
|
|
+ HeFengDay existing = mergedMap.get(date);
|
|
|
+ existing.setDswrf(item.getDswrf());
|
|
|
+ } else {
|
|
|
+ mergedMap.put(date, item);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转换为列表
|
|
|
+ List<HeFengDay> mergedList = new ArrayList<>(mergedMap.values());
|
|
|
+ mergedList.sort(Comparator.comparing(HeFengDay::getTs));
|
|
|
+ for (HeFengDay item : mergedList) {
|
|
|
+ String insertSQL = "INSERT INTO hefeng_day_unit_" + areaCode + " USING hefeng_day_unit TAGS('" + areaCode + "') " +
|
|
|
+ "(ts,wind_speed_day,wind_speed_m_day,wind_scale_day,wind_360_Day,precip,text_day,temp_max,temp_min,humidity,dswrf) values('"
|
|
|
+ + item.getTs() + "', " + item.getWindSpeedDay() + ", " + item.getWindSpeedMDay() + ", " + item.getWindScaleDay() + ", " + item.getWind360Day() + ", "
|
|
|
+ + item.getPrecip() + ", '" + item.getTextDay() + "', " + item.getTempMax() + ", " + item.getTempMin() + ", " + item.getHumidity() + ", "
|
|
|
+ + item.getDswrf() + ")";
|
|
|
+ SimpleDateFormat simpleFormatter = new SimpleDateFormat("yyyy-MM-dd");
|
|
|
+ String insertSnap = "INSERT INTO weather_day_snap_" + areaCode + "_" + simpleFormatter.format(new Date()) + " USING hefeng_day_unit TAGS('" + areaCode + "','" + simpleFormatter.format(new Date()) + "') " +
|
|
|
+ "(ts,wind_speed_day,wind_speed_m_day,wind_scale_day,wind_360_Day,precip,text_day,temp_max,temp_min,humidity,dswrf) values('"
|
|
|
+ + item.getTs() + "', " + item.getWindSpeedDay() + ", " + item.getWindSpeedMDay() + ", " + item.getWindScaleDay() + ", " + item.getWind360Day() + ", "
|
|
|
+ + item.getPrecip() + ", '" + item.getTextDay() + "', " + item.getTempMax() + ", " + item.getTempMin() + ", " + item.getHumidity() + ", "
|
|
|
+ + item.getDswrf() + ")";
|
|
|
+ int affectedRows = ps.executeUpdate(insertSQL);
|
|
|
+ }
|
|
|
+ if (ps != null)
|
|
|
+ ps.close();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("星图天气,地区:{} 日天气数据下载失败JSON格式化错误", name);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ log.info("星图天气,地区:{} 日天气数据下载完成", name);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Timestamp getTimestamp(String time) {
|
|
|
+ // 解析字符串为 ZonedDateTime
|
|
|
+ ZonedDateTime zonedDateTime = ZonedDateTime.parse(time);
|
|
|
+ // 将 ZonedDateTime 转换为 Instant
|
|
|
+ Instant instant = zonedDateTime.toInstant();
|
|
|
+ // 将 Instant 转换为 Timestamp
|
|
|
+ return Timestamp.from(instant);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getNowDateString() {
|
|
|
+ LocalDate yesterday = LocalDate.now();
|
|
|
+ return yesterday.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getSevenDaysLater() {
|
|
|
+ LocalDate sevenDaysLater = LocalDate.now().plusDays(7);
|
|
|
+ return sevenDaysLater.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
|
|
+ }
|
|
|
+
|
|
|
+ private String ConversionWeatherCodeGeovisearth(String code) {
|
|
|
+ switch (code) {
|
|
|
+ case "00":
|
|
|
+ return "晴";
|
|
|
+ case "01":
|
|
|
+ return "多云";
|
|
|
+ case "02":
|
|
|
+ return "阴";
|
|
|
+ case "03":
|
|
|
+ return "阵雨";
|
|
|
+ case "04":
|
|
|
+ return "雷阵雨";
|
|
|
+ case "05":
|
|
|
+ return "雷阵雨伴有冰雹";
|
|
|
+ case "06":
|
|
|
+ return "雨夹雪";
|
|
|
+ case "07":
|
|
|
+ return "小雨";
|
|
|
+ case "08":
|
|
|
+ return "中雨";
|
|
|
+ case "09":
|
|
|
+ return "大雨";
|
|
|
+ case "10":
|
|
|
+ return "暴雨";
|
|
|
+ case "11":
|
|
|
+ return "大暴雨";
|
|
|
+ case "12":
|
|
|
+ return "特大暴雨";
|
|
|
+ case "13":
|
|
|
+ return "阵雪";
|
|
|
+ case "14":
|
|
|
+ return "小雪";
|
|
|
+ case "15":
|
|
|
+ return "中雪";
|
|
|
+ case "16":
|
|
|
+ return "大雪";
|
|
|
+ case "17":
|
|
|
+ return "暴雪";
|
|
|
+ case "18":
|
|
|
+ return "雾";
|
|
|
+ case "19":
|
|
|
+ return "冻雨";
|
|
|
+ case "20":
|
|
|
+ return "沙尘暴";
|
|
|
+ case "21":
|
|
|
+ return "小到中雨";
|
|
|
+ case "22":
|
|
|
+ return "中到大雨";
|
|
|
+ case "23":
|
|
|
+ return "大到暴雨";
|
|
|
+ case "24":
|
|
|
+ return "暴雨到大暴雨";
|
|
|
+ case "25":
|
|
|
+ return "大暴雨到特大暴雨";
|
|
|
+ case "26":
|
|
|
+ return "小到中雪";
|
|
|
+ case "27":
|
|
|
+ return "中到大雪";
|
|
|
+ case "28":
|
|
|
+ return "大到暴雪";
|
|
|
+ case "29":
|
|
|
+ return "浮尘";
|
|
|
+ case "30":
|
|
|
+ return "扬沙";
|
|
|
+ case "31":
|
|
|
+ return "强沙尘暴";
|
|
|
+ case "32":
|
|
|
+ return "浓雾";
|
|
|
+ case "49":
|
|
|
+ return "强浓雾";
|
|
|
+ case "53":
|
|
|
+ return "霾";
|
|
|
+ case "54":
|
|
|
+ return "中度霾";
|
|
|
+ case "55":
|
|
|
+ return "重度霾";
|
|
|
+ case "56":
|
|
|
+ return "严重霾";
|
|
|
+ case "57":
|
|
|
+ return "大雾";
|
|
|
+ case "58":
|
|
|
+ return "特强浓雾";
|
|
|
+ case "301":
|
|
|
+ return "雨";
|
|
|
+ case "302":
|
|
|
+ return "雪";
|
|
|
+ case "99":
|
|
|
+ return "无";
|
|
|
+ default:
|
|
|
+ return "晴"; // 默认返回晴
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|