7timer.info 免费天气预报对接记录
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.web.client.RestTemplate; import java.time.*; import java.time.format.DateTimeFormatter; public class SevenTimerWeather { public static void main(String[] args) throws Exception { String url = "http://www.7timer.info/bin/astro.php" + "?lon=114.54503&lat=38.138258&ac=0&lang=en&unit=metric&output=json&tzshift=0"; RestTemplate restTemplate = new RestTemplate(); String json = restTemplate.getForObject(url, String.class); ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(json); // 起报时间(UTC) String initStr = root.get("init").asText(); LocalDateTime initUtc = LocalDateTime.parse(initStr, DateTimeFormatter.ofPattern("yyyyMMddHH")); ZonedDateTime initBj = initUtc.atZone(ZoneOffset.UTC).withZoneSameInstant(ZoneId.of("Asia/Shanghai")); // 当前北京时间 ZonedDateTime nowBj = ZonedDateTime.now(ZoneId.of("Asia/Shanghai")); // 选择最接近当前时间的预报 JsonNode dataseries = root.get("dataseries"); JsonNode bestNode = null; long bestDiff = Long.MAX_VALUE; for (JsonNode node : dataseries) { int tp = node.get("timepoint").asInt(); ZonedDateTime forecastTime = initBj.plusHours(tp); long diff = Math.abs(Duration.between(forecastTime, nowBj).toMinutes()); if (diff < bestDiff) { bestDiff = diff; bestNode = node; } } if (bestNode != null) { int temp = bestNode.get("temp2m").asInt(); // 室外温度 int rh = bestNode.get("rh2m").asInt(); // 湿度% String windDir = bestNode.get("wind10m").get("direction").asText(); int windSpeed = bestNode.get("wind10m").get("speed").asInt(); int transparency = bestNode.get("transparency").asInt(); double feelsLike = calcFeelsLike(temp, rh, windSpeed); String windDirCn = windDirToChinese(windDir); String visibility = transparencyToKm(transparency); ZonedDateTime forecastTime = initBj.plusHours(bestNode.get("timepoint").asInt()); System.out.println("预报时间:" + forecastTime); System.out.println("室外温度:" + temp + " ℃"); System.out.println("体感温度:" + String.format("%.1f ℃", feelsLike)); System.out.println("风向:" + windDirCn); System.out.println("风速:" + windSpeed + " m/s"); System.out.println("能见度:" + visibility); String weatherText = getWeatherText( bestNode.get("cloudcover").asInt(), bestNode.get("prec_type").asText() ); System.out.println("天气:" + weatherText); } } // 根据 cloudcover 和 prec_type 推断天气文本 private static String getWeatherText(int cloudcover, String precType) { if ("snow".equalsIgnoreCase(precType)) { if (cloudcover >= 7) return "大雪"; else if (cloudcover >= 4) return "中雪"; else return "小雪"; } else if ("rain".equalsIgnoreCase(precType)) { if (cloudcover >= 7) return "大雨"; else if (cloudcover >= 4) return "中雨"; else return "小雨"; } else { // 无降水 if (cloudcover <= 2) return "晴"; else if (cloudcover <= 5) return "少云/多云"; else if (cloudcover <= 7) return "阴"; else return "阴天"; } } // 风向中文转换 private static String windDirToChinese(String dir) { switch (dir) { case "N": return "北风"; case "NE": return "东北风"; case "E": return "东风"; case "SE": return "东南风"; case "S": return "南风"; case "SW": return "西南风"; case "W": return "西风"; case "NW": return "西北风"; default: return dir; } } // 透明度 -> 能见度公里数 private static String transparencyToKm(int t) { switch (t) { case 1: return "≥20 km"; case 2: return "16–20 km"; case 3: return "12–16 km"; case 4: return "8–12 km"; case 5: return "4–8 km"; case 6: return "2–4 km"; case 7: return "1–2 km"; case 8: return "0.5–1 km"; case 9: return "<0.5 km"; default: return "未知"; } } // 简易体感温度计算 private static double calcFeelsLike(double tempC, int humidity, double windMs) { if (tempC >= 27) { // 热指数公式 (近似) return -8.784695 + 1.61139411 * tempC + 2.338549 * humidity - 0.14611605 * tempC * humidity - 0.012308094 * tempC * tempC - 0.016424828 * humidity * humidity + 0.002211732 * tempC * tempC * humidity + 0.00072546 * tempC * humidity * humidity - 0.000003582 * tempC * tempC * humidity * humidity; } else if (tempC <= 10) { // 风寒指数公式 double windKmh = windMs * 3.6; return 13.12 + 0.6215 * tempC - 11.37 * Math.pow(windKmh, 0.16) + 0.3965 * tempC * Math.pow(windKmh, 0.16); } else { return tempC; } } }
-
lat → 纬度 (Latitude)
-
表示南北位置
-
北纬为正,南纬为负
-
-
lon → 经度 (Longitude)
-
表示东西位置
-
东经为正,西经为负
-
坐标系使用WGS84格式,可以在谷歌地图拾取
本文来自博客园,作者:Rolay,转载请注明原文链接:https://www.cnblogs.com/rolayblog/p/19113166