Selaa lähdekoodia

甘肃日天气数据切换到星图

xiaowang 1 kuukausi sitten
vanhempi
commit
d97c94c0bf

+ 25 - 0
src/main/java/com/example/getweather/job/DownloadGeovisearth.java

@@ -0,0 +1,25 @@
+package com.example.getweather.job;
+
+import com.example.getweather.service.GetWeatherGeovisearth;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+
+@Slf4j
+@Service
+@EnableScheduling
+public class DownloadGeovisearth {
+    @Resource
+    private GetWeatherGeovisearth getWeatherGeovisearth;
+
+    //中科星图气象源数据下载定时任务
+    //@Scheduled(fixedDelay = 600000000)
+    @Scheduled(cron = "0 20 6,12 * * ?")
+    public void download() {
+        getWeatherGeovisearth.download();
+    }
+}

+ 3 - 3
src/main/java/com/example/getweather/service/GetWeather.java

@@ -156,8 +156,8 @@ public class GetWeather {
             for (String code : areaCodes) {
                 //只有甘肃用xmo天气日接口
                 if (code.equals("620000")) {
-                    //20250804 甘肃气象源切换为中科星图 新建service
-                    if (isApiQuotaExhausted) break; // 检查标志变量
+                    //20250804 甘肃气象源切换为中科星图 新建service 0902执行
+                   /* if (isApiQuotaExhausted) break; // 检查标志变量
                     List<DistrictCodeDO> shiList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(code)).collect(Collectors.toList());
                     //市
                     for (DistrictCodeDO d : shiList) {
@@ -185,7 +185,7 @@ public class GetWeather {
                         if (isApiQuotaExhausted) break; // 检查标志变量
                         isApiQuotaExhausted = analysisXMO(xmoUrl, d.getCode(), d.getName(), conn); // 传递标志变量
                         if (isApiQuotaExhausted) break; // 检查标志变量
-                    }
+                    }*/
                 } else {
                     if (isApiQuotaExhausted) break; // 检查标志变量
                     List<DistrictCodeDO> shiList = districtCodeDOList.stream().filter(item -> item.getPid().toString().equals(code)).collect(Collectors.toList());

+ 503 - 0
src/main/java/com/example/getweather/service/GetWeatherGeovisearth.java

@@ -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 "晴"; // 默认返回晴
+        }
+    }
+}