Skip to content

Commit

Permalink
Merge pull request #763 from yanliutafewa/main
Browse files Browse the repository at this point in the history
Add features to "API Based Weather Report" - #744
  • Loading branch information
Mrinank-Bhowmick committed Jun 8, 2024
2 parents 7d424bc + 6f6f2da commit 231caa9
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 15 deletions.
90 changes: 75 additions & 15 deletions projects/API Based Weather Report/API Based Weather Report.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import requests
from datetime import datetime
from Util_Functions import wind_degree_to_direction, unix_timestamp_to_localtime, convert_temperature


# Function to fetch weather data from OpenWeatherMap API
def fetch_weather(api_key, location):
"""
Function to fetch weather data from OpenWeatherMap API.
Parameters:
api_key (str): API key.
location (str): City name.
Returns:
str: The JSON response string.
"""
try:
# Constructing the API link with the provided API key and location
complete_api_link = f"https://api.openweathermap.org/data/2.5/weather?q={location}&appid={api_key}"
Expand All @@ -23,25 +33,34 @@ def fetch_weather(api_key, location):
return None


# Function to write weather information to a text file
def write_to_file(location, weather_data):
def write_to_file(weather_data, temperature_unit):
"""
Function to write weather information to a text file.
Parameters:
weather_data (str): The JSON API response string.
temperature_unit (str): 'C' for Celsius, 'F' for Fahrenheit.
"""

try:
# Opening the file "weatherinfo.txt" in write mode
with open("weatherinfo.txt", "w+") as f:
# Getting the current date and time
date_time = datetime.now().strftime("%d %b %Y | %I:%M:%S %p")

# Writing header information to the file
f.write("-------------------------------------------------------------\n")
f.write(f"Weather Stats for - {location.upper()} || {date_time}\n")
f.write("-------------------------------------------------------------\n")
if "name" in weather_data and "sys" in weather_data and "country" in weather_data["sys"]:
f.write("-------------------------------------------------------------\n")
f.write(f"Weather Stats for - {weather_data['name']} | {weather_data['sys']['country']} "
f"| {date_time}\n")
f.write("-------------------------------------------------------------\n")

# Writing temperature information to the file
if "main" in weather_data and "temp" in weather_data["main"]:
f.write(
"\tCurrent temperature is : {:.2f} °C\n".format(
weather_data["main"]["temp"] - 273.15
)
"\tCurrent temperature is : "
+ convert_temperature(weather_data["main"]["temp"], temperature_unit)
+ "\n"
)

# Writing weather description information to the file
Expand All @@ -68,6 +87,24 @@ def write_to_file(location, weather_data):
)
)

# Writing wind direction information to the file
if "wind" in weather_data and "deg" in weather_data["wind"]:
f.write(
"\tCurrent wind direction : " +
wind_degree_to_direction(weather_data["wind"]["deg"]) + " \n")

# Writing sunrise local time to the file
if "sys" in weather_data and "sunrise" in weather_data["sys"] and "timezone" in weather_data:
f.write(
"\tToday's sunrise time : " +
unix_timestamp_to_localtime(weather_data["sys"]["sunrise"], weather_data["timezone"]) + " \n")

# Writing sunset local time to the file
if "sys" in weather_data and "sunset" in weather_data["sys"] and "timezone" in weather_data:
f.write(
"\tToday's sunset time : " +
unix_timestamp_to_localtime(weather_data["sys"]["sunset"], weather_data["timezone"]) + " \n")

# Printing confirmation message after writing to file
print("Weather information written to weatherinfo.txt")

Expand All @@ -76,36 +113,59 @@ def write_to_file(location, weather_data):
print("Error writing to file:", e)


# Main function
def main():
"""
Main function.
"""
# Printing welcome messages and instructions
print("Welcome to the Weather Information App!")
print("You need an API key to access weather data from OpenWeatherMap.")
print(
"You can obtain your API key by signing up at https://home.openweathermap.org/users/sign_up"
)

# Prompting the user to input API key and city name
# Prompting the user to input API key, city name, and temperature unit
api_key = input("Please enter your OpenWeatherMap API key: ")
location = input("Enter the city name: ")
temperature_unit = input("Enter the temperature unit. 'C' for Celsius and 'F' for Fahrenheit: ")

if not (temperature_unit.upper() == "C" or temperature_unit.upper() == "F"):
print("Temperature unit must either be 'C' or be 'F'.")
return

# Fetching weather data using the provided API key and location
weather_data = fetch_weather(api_key, location)

# Checking if weather data was successfully fetched
if weather_data:
# Checking if the API key is invalid
if weather_data["cod"] == "401":
print("Invalid API key.")
return

# Checking if the city is not found
if weather_data["cod"] == "404":
print("City not found.")
return

# Writing weather information to file
write_to_file(location, weather_data)
write_to_file(weather_data, temperature_unit)

# Printing weather information to console
print("Current City : " + weather_data['name'] + ', ' +
weather_data['sys']['country'])
print(
"Current temperature is: {:.2f} °C".format(
weather_data["main"]["temp"] - 273.15
)
"Current temperature is: "
+ convert_temperature(weather_data["main"]["temp"], temperature_unit)
)
print("Current weather desc : " + weather_data["weather"][0]["description"])
print("Current Humidity :", weather_data["main"]["humidity"], "%")
print("Current wind speed :", weather_data["wind"]["speed"], "kmph")
print("Current wind direction:", wind_degree_to_direction(weather_data["wind"]["deg"]))
print("Today's sunrise time :",
unix_timestamp_to_localtime(weather_data["sys"]["sunrise"], weather_data["timezone"]))
print("Today's sunset time :",
unix_timestamp_to_localtime(weather_data["sys"]["sunset"], weather_data["timezone"]))
else:
# Printing error message if weather data fetching fails
print("Failed to fetch weather data. Please check your input and try again.")
Expand Down
93 changes: 93 additions & 0 deletions projects/API Based Weather Report/Util_Functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from datetime import datetime, timedelta


def wind_degree_to_direction(str_wind_degree):
"""
Convert wind degree to wind direction.
Parameters:
str_wind_degree (str): Wind degree from API (0 to 360)
Returns:
str: Wind direction (e.g., N, NE, E, etc.)
Or message "API Wind Degree data format error!"
"""
# convert wind degree from str to int.
try:
wind_degree = int(str_wind_degree)
except ValueError:
return "API Wind Degree data format error!"

directions = [
"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE",
"S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"
]
index = int((wind_degree + 11.25) // 22.5) % 16
return directions[index]


def unix_timestamp_to_localtime(str_unix_timestamp, str_timezone_offset_seconds):
"""
Convert unix timestamp to localtime (for sunrise and sunset).
Parameters:
str_unix_timestamp (str): Unix timestamp (e.g., "1717715516")
str_timezone_offset_seconds (str): timezone offset in second (e.g., "28800" represents UTC+8)
Returns:
str: local_time (e.g., "2024-06-07 07:11:56")
Or message "API sunset/sunrise data format error!"
Or message "API timezone data format error!"
"""
# Convert strings to integers
try:
unix_timestamp = int(str_unix_timestamp)
except ValueError:
return "API sunset/sunrise data format error!"

try:
timezone_offset_seconds = int(str_timezone_offset_seconds)
except ValueError:
return "API timezone data format error!"

# Convert Unix timestamp to UTC datetime
utc_time = datetime.utcfromtimestamp(unix_timestamp)

# Apply timezone offset
local_time = utc_time + timedelta(seconds=timezone_offset_seconds)

return local_time.strftime('%Y-%m-%d %H:%M:%S')


def convert_temperature(str_temperature_kelvin, temperature_unit):
"""
Convert temperature in Kelvin degree to Celsius degree or Fahrenheit degree based on second parameter .
Parameters:
str_temperature_kelvin (str): temperature in Kelvin degree (e.g., "291.19")
temperature_unit (str): "C" for Celsius, "F" for Fahrenheit
Returns:
str: temperature (e.g., "21.07 °C" or "67.12 °F")
Or message "API temperature data format error!"
Or message "Temperature unit must either be 'C' or be 'F'!"
"""
# Convert strings to integers
try:
temperature_k = float(str_temperature_kelvin)
except ValueError:
return "API temperature data format error!"

# Validate temperature_unit
unit = str(temperature_unit).upper()
if not (unit == "C" or unit == "F"):
return "Temperature unit must either be 'C' or be 'F'!"

# Converting
if unit == 'C':
temperature_c = temperature_k - 273.15
return f"{temperature_c:.2f} °C"

if unit == 'F':
temperature_f = temperature_k * 9 / 5 - 459.67
return f"{temperature_f:.2f} °F"
45 changes: 45 additions & 0 deletions projects/API Based Weather Report/test_Util_Functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import unittest
from Util_Functions import wind_degree_to_direction, unix_timestamp_to_localtime, convert_temperature


class MyTestCase(unittest.TestCase):
def test_wind_degree_to_direction(self):
self.assertEqual("ENE", wind_degree_to_direction("60"))
self.assertEqual("SE", wind_degree_to_direction("130"))
self.assertEqual("W", wind_degree_to_direction("280"))

def test_wind_degree_to_direction_parameter_format_error(self):
self.assertEqual("API Wind Degree data format error!",
wind_degree_to_direction("abc"))

def test_unix_timestamp_to_localtime(self):
self.assertEqual("2024-06-07 07:11:56",
unix_timestamp_to_localtime("1717715516", "28800"))

def test_unix_timestamp_to_localtime_unix_timestamp_format_error(self):
self.assertEqual("API sunset/sunrise data format error!",
unix_timestamp_to_localtime("abc", "28800"))

def test_unix_timestamp_to_localtime_timezone_format_error(self):
self.assertEqual("API timezone data format error!",
unix_timestamp_to_localtime("1717715516", "abc"))

def test_convert_temperature_to_celsius(self):
self.assertEqual("15.44 °C",
convert_temperature("288.59", "C"))

def test_convert_temperature_to_fahrenheit(self):
self.assertEqual("59.79 °F",
convert_temperature("288.59", "F"))

def test_convert_temperature_temperature_format_error(self):
self.assertEqual("API temperature data format error!",
convert_temperature("abc", "F"))

def test_convert_temperature_temperature_unit_error(self):
self.assertEqual("Temperature unit must either be 'C' or be 'F'!",
convert_temperature("288.59", "H"))


if __name__ == '__main__':
unittest.main()

0 comments on commit 231caa9

Please sign in to comment.