Geophysics_class / services /usgs_service.py
cwadayi's picture
Update services/usgs_service.py
19ad81e verified
# usgs_service.py
import requests
import pandas as pd
from datetime import datetime, timedelta, timezone
# ✨ CORRECTED IMPORT
from config.settings import USGS_API_BASE_URL, CURRENT_YEAR
def _iso(dt: datetime) -> str:
"""將 datetime 物件格式化為 USGS API 需要的 ISO 8601 字串。"""
return dt.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S")
def fetch_global_last24h_text(min_mag: float = 5.0, limit: int = 10) -> str:
"""從 USGS 擷取過去 24 小時的全球顯著地震。"""
now_utc = datetime.now(timezone.utc)
since = now_utc - timedelta(hours=24)
params = {
"format": "geojson",
"starttime": _iso(since),
"endtime": _iso(now_utc),
"minmagnitude": float(min_mag),
"limit": int(limit),
"orderby": "time",
}
try:
r = requests.get(USGS_API_BASE_URL, params=params, timeout=15)
r.raise_for_status()
features = r.json().get("features", [])
if not features:
return f"✅ 過去 24 小時內,全球無規模 {min_mag} 以上的顯著地震。"
lines = [f"🚨 近 24 小時全球顯著地震 (M≥{min_mag}):", "-" * 20]
for f in features:
p = f["properties"]
t_utc = datetime.fromtimestamp(p["time"] / 1000, tz=timezone.utc)
lines.append(
# [修改] 將 "震級" 改為 "規模"
f"規模: {p['mag']:.1f} | 日期時間: {t_utc.strftime('%Y-%m-%d %H:%M')} (UTC)\n"
f"地點: {p.get('place', 'N/A')}\n"
f"報告連結: {p.get('url', '無')}"
)
return "\n\n".join(lines)
except Exception as e:
return f"❌ 查詢失敗:{e}"
def fetch_taiwan_df_this_year(min_mag: float = 5.0) -> pd.DataFrame | str:
"""從USGS擷取今年以來台灣區域的顯著地震。"""
now_utc = datetime.now(timezone.utc)
start_of_year_utc = datetime(now_utc.year, 1, 1, tzinfo=timezone.utc)
params = {
"format": "geojson", "starttime": _iso(start_of_year_utc), "endtime": _iso(now_utc),
"minmagnitude": float(min_mag),
"minlatitude": 21, "maxlatitude": 26,
"minlongitude": 119, "maxlongitude": 123,
"limit": 250,
"orderby": "time",
}
try:
r = requests.get(USGS_API_BASE_URL, params=params, timeout=20)
r.raise_for_status()
features = r.json().get("features", [])
if not features:
return f"✅ 今年 ({CURRENT_YEAR} 年) 以來,台灣區域無 M≥{min_mag:.1f} 的顯著地震。"
rows = []
for f in features:
p = f["properties"]
lon, lat, *_ = f["geometry"]["coordinates"]
rows.append({
"latitude": lat,
"longitude": lon,
"magnitude": p["mag"],
"place": p.get("place", ""),
"time_utc": datetime.fromtimestamp(p["time"]/1000, tz=timezone.utc),
"url": p.get("url", "")
})
return pd.DataFrame(rows)
except Exception as e:
return f"❌ 查詢失敗: {e}"
# --- ✨ 以下是新增的函式 ---
def fetch_usgs_earthquakes_by_date(start_time_str: str, end_time_str: str, min_mag: float, limit: int = 20) -> str:
"""根據指定的日期範圍和最小規模,從 USGS API 查詢全球地震。"""
params = {
"format": "geojson",
"starttime": start_time_str,
"endtime": end_time_str,
"minmagnitude": float(min_mag),
"limit": int(limit),
"orderby": "time-asc", # 按時間正序排列
}
try:
r = requests.get(USGS_API_BASE_URL, params=params, timeout=20)
r.raise_for_status()
features = r.json().get("features", [])
if not features:
return f"✅ 在 {start_time_str}{end_time_str} 期間,全球無規模 {min_mag} 以上的地震紀錄。"
lines = [f"🔎 {start_time_str}{end_time_str} 全球地震 (M≥{min_mag}):", "-" * 20]
for f in features:
p = f["properties"]
t_utc = datetime.fromtimestamp(p["time"] / 1000, tz=timezone.utc)
lines.append(
f"規模: {p['mag']:.1f} | 時間: {t_utc.strftime('%Y-%m-%d %H:%M')} (UTC)\n"
f"地點: {p.get('place', 'N/A')}\n"
f"報告: {p.get('url', '無')}"
)
if len(features) >= limit:
lines.append(f"\n(注意:結果已達上限 {limit} 筆,可能還有更多地震未顯示)")
return "\n\n".join(lines)
except Exception as e:
return f"❌ 查詢失敗:{e}"