如何修复Discord天气Bot中的时间偏移问题?
问题
我用下面的Discord Bot代码调用OpenWeatherMap API获取未来24小时天气,代码能正常运行返回结果,但返回的时间比对应温度的实际时间超前6小时(把示例输出里的时间回调6小时后,温度才符合实际情况),该怎么修复?
import requests import discord def get_weather(city, state, api_key): base_url = "http://api.openweathermap.org/data/2.5/forecast" params = { "q": f"{city},{state}", "appid": api_key, "units": "imperial", "cnt": 9 } response = requests.get(base_url, params=params) data = response.json() # Check if the API request was successful if response.status_code == 200: # Extract and format the weather information weather_info = [] for forecast in data['list']: date_time = forecast['dt_txt'] temperature = forecast['main']['temp'] weather_description = forecast['weather'][0]['description'] weather_info.append(f"{date_time}: {temperature}°F, {weather_description}") return weather_info else: return f"Error: {data['message']}" api_key = '' bot_token = '' intents = discord.Intents.default() intents.message_content = True client = discord.Client(intents=intents) @client.event async def on_ready(): print(f"We have logged in as {client.user}") @client.event async def on_message(message): if message.author == client.user: return if message.content.startswith("!weather"): await message.channel.send("Enter the state: ") def check_state(m): return m.author == message.author and m.channel == message.channel state_msg = await client.wait_for("message", check=check_state, timeout=60) state = state_msg.content await message.channel.send("Enter the city: ") def check_city(m): return m.author == message.author and m.channel == message.channel city_msg = await client.wait_for("message", check=check_city, timeout=60) city = city_msg.content weather_info = get_weather(city, state, api_key) if isinstance(weather_info, str): await message.channel.send(weather_info) else: await message.channel.send("\n".join(weather_info)) client.run(bot_token)
返回结果示例:
2023-07-05 00:00:00: 81.46°F, light rain 2023-07-05 03:00:00: 77.63°F, few clouds 2023-07-05 06:00:00: 72.77°F, clear sky 2023-07-05 09:00:00: 70.63°F, clear sky 2023-07-05 12:00:00: 76.95°F, clear sky 2023-07-05 15:00:00: 87.58°F, clear sky 2023-07-05 18:00:00: 93.49°F, few clouds 2023-07-05 21:00:00: 92.32°F, broken clouds 2023-07-06 00:00:00: 82.67°F, broken clouds
解决方案
问题根源是OpenWeatherMap返回的dt_txt字段是UTC标准时间,而你需要的是目标城市的本地时间。推荐以下两种修复方式:
方式一:利用API返回的时区偏移自动转换(最优解)
API返回的city字段中包含timezone值(单位为秒),代表目标城市与UTC的时间偏移量。我们可以用这个值将UTC时间转换为本地时间,适配所有时区的城市。
修改后的完整代码如下:
import requests import discord from datetime import datetime, timedelta # 导入时间处理模块 def get_weather(city, state, api_key): base_url = "http://api.openweathermap.org/data/2.5/forecast" params = { "q": f"{city},{state}", "appid": api_key, "units": "imperial", "cnt": 9 } response = requests.get(base_url, params=params) data = response.json() if response.status_code == 200: weather_info = [] # 获取目标城市的时区偏移(秒) timezone_offset = data['city']['timezone'] for forecast in data['list']: # 解析UTC时间字符串 utc_time = datetime.strptime(forecast['dt_txt'], "%Y-%m-%d %H:%M:%S") # 转换为本地时间:UTC时间 + 时区偏移量 local_time = utc_time + timedelta(seconds=timezone_offset) # 格式化本地时间为字符串 local_time_str = local_time.strftime("%Y-%m-%d %H:%M:%S") temperature = forecast['main']['temp'] weather_description = forecast['weather'][0]['description'] weather_info.append(f"{local_time_str}: {temperature}°F, {weather_description}") return weather_info else: return f"Error: {data['message']}" # 以下代码保持不变 api_key = '' bot_token = '' intents = discord.Intents.default() intents.message_content = True client = discord.Client(intents=intents) @client.event async def on_ready(): print(f"We have logged in as {client.user}") @client.event async def on_message(message): if message.author == client.user: return if message.content.startswith("!weather"): await message.channel.send("Enter the state: ") def check_state(m): return m.author == message.author and m.channel == message.channel state_msg = await client.wait_for("message", check=check_state, timeout=60) state = state_msg.content await message.channel.send("Enter the city: ") def check_city(m): return m.author == message.author and m.channel == message.channel city_msg = await client.wait_for("message", check=check_city, timeout=60) city = city_msg.content weather_info = get_weather(city, state, api_key) if isinstance(weather_info, str): await message.channel.send(weather_info) else: await message.channel.send("\n".join(weather_info)) client.run(bot_token)
方式二:手动固定偏移(仅临时应急)
如果只是临时针对当前6小时的偏移场景,可以直接给UTC时间减去6小时,但这种方法不通用,换其他时区的城市就会失效:
# 在处理时间的部分替换为以下代码 utc_time = datetime.strptime(forecast['dt_txt'], "%Y-%m-%d %H:%M:%S") local_time = utc_time - timedelta(hours=6) local_time_str = local_time.strftime("%Y-%m-%d %H:%M:%S")
关键说明
- 方式一通过API返回的
timezone字段自动适配时区,是通用且正确的解决方案。 - 必须导入
datetime和timedelta模块来完成时间解析与转换操作。
内容的提问来源于stack exchange,提问作者Ali Eke
相关产品推荐
相关产品推荐

