import math
def convert_latlon_to_grid(lat_deg: float, lon_deg: float) -> tuple[int, int]:
"""
위도(latitude)와 경도(longitude)를 기상청 격자 좌표(NX, NY)로 변환합니다.
Ref: https://www.data.go.kr/data/15084084/openapi.do (기상청 단기예보 Open API 명세)
"""
# 기상청 단기예보 좌표 변환 상수
Re = 6371.00877 # 지구 반경(km)
grid = 5.0 # 격자 간격(km)
slat1 = 30.0 # 투영 위도1(degree)
slat2 = 60.0 # 투영 위도2(degree)
olon = 126.0 # 기준점 경도(degree)
olat = 38.0 # 기준점 위도(degree)
xo = 43 # 기준점 X좌표(GRID)
yo = 136 # 기쥰점 Y좌표(GRID)
DEGRAD = math.pi / 180.0
RADDEG = 180.0 / math.pi
re = Re / grid
slat1 = slat1 * DEGRAD
slat2 = slat2 * DEGRAD
olon = olon * DEGRAD
olat = olat * DEGRAD
sn = math.tan(math.pi * 0.25 + slat2 * 0.5) / math.tan(math.pi * 0.25 + slat1 * 0.5)
sn = math.log(math.cos(slat1) / math.cos(slat2)) / math.log(sn)
sf = math.tan(math.pi * 0.25 + slat1 * 0.5)
sf = math.pow(sf, sn) * math.cos(slat1) / sn
ro = math.tan(math.pi * 0.25 + olat * 0.5)
ro = re * sf / math.pow(ro, sn)
ra = math.tan(math.pi * 0.25 + (lat_deg) * DEGRAD * 0.5)
ra = re * sf / math.pow(ra, sn)
theta = lon_deg * DEGRAD - olon
if theta > math.pi:
theta -= 2.0 * math.pi
if theta < -math.pi:
theta += 2.0 * math.pi
theta *= sn
x = math.floor(ra * math.sin(theta) + xo + 0.5)
y = math.floor(ro - ra * math.cos(theta) + yo + 0.5)
return int(x), int(y)
def get_base_date_time(minutes_offset: int = 40) -> tuple[str, str]:
"""
기상청 API 호출을 위한 base_date, base_time을 계산합니다.
초단기실황(UltraSrtNcst)은 매시간 40분 이후에 호출 가능합니다.
예: 10시 30분 호출 -> 09시 데이터(base_time=0900) 사용
10시 45분 호출 -> 10시 데이터(base_time=1000) 사용
Args:
minutes_offset (int): 데이터 생성 시점 (분). 기본값 40분.
Returns:
tuple[str, str]: (YYYYMMDD, HHMM)
"""
from datetime import datetime, timedelta
now = datetime.now()
# 현재 시간이 매시간 minutes_offset분보다 이전이면 1시간 전 데이터를 사용
if now.minute < minutes_offset:
target_time = now - timedelta(hours=1)
else:
target_time = now
base_date = target_time.strftime("%Y%m%d")
base_time = target_time.strftime("%H00")
return base_date, base_time
if __name__ == "__main__":
# Test case: 서울시청 (37.5665, 126.9780) -> (60, 127)
lat, lon = 37.5665, 126.9780
nx, ny = convert_latlon_to_grid(lat, lon)
print(f"Seoul City Hall: ({lat}, {lon}) -> NX:{nx}, NY:{ny}")