3
\$\begingroup\$

Given a string representing the hour and minute, where: 00:00 <= time <= 23:59, the program should output the number of angles the sun is above the horizon.

  • When time is "06:00" the sun angles are 0o
  • At "12:00" the sun is at 90o
  • At "18:00" the sun goes to 180o
  • After "18:00" and before "06:00" the program should output "I don't see the sun!"

sun angles

Examples:

  • sun_angle("07:00") == 15
  • sun_angle("01:23") == "I don't see the sun!"
  • sun_angle("12:15") == 93.75

The code:

import datetime as dt
def check_you_dont_see_sun(time_dt, end_dt, start_dt):
 return ((time_dt > start_dt and time_dt < end_dt)
 or (time_dt > start_dt or time_dt < end_dt))
def calculate_sun_angle(time_dt, end_dt):
 difference = time_dt - end_dt
 hours_of_difference = (difference.seconds / 60) / 60
 angle_increase_each_hour = 15
 return hours_of_difference * angle_increase_each_hour
def sun_angle(time):
 start_dt = dt.datetime.strptime('18:00', '%H:%M')
 end_dt = dt.datetime.strptime('06:00', '%H:%M')
 time_dt = dt.datetime.strptime(time, '%H:%M')
 if check_you_dont_see_sun(time_dt,end_dt,start_dt):
 return "I don't see the sun!"
 else:
 return calculate_sun_angle(time_dt, end_dt)

What could we improve?

asked May 25, 2019 at 8:59
\$\endgroup\$
1
  • 1
    \$\begingroup\$ The task involves calculating some kind of angle, but it certainly isn't calculating the angle of the sun above the horizon! \$\endgroup\$ Commented May 25, 2019 at 19:05

1 Answer 1

3
\$\begingroup\$

One immediate thing I would improve is the naming of your variables. While in general very descriptive, it took me a while to realize that start_dt is actually the time of sunset and end_dt the time of sunrise, instead of the other way around. I would also make these variables global constants and use those as default values. This way you can do it all in one still short and readable function.

I would add some docstring describing what your function(s) do and use a compound comparison instead of two comparisons to determine if the time is day or night.

The datetime module is often imported as from datetime import datetime, although your import is also OK.

The calling of the code should happen under a if __name__ == "__main__": guard, where I would also put at least some very rudimentary testing code.

from datetime import datetime
SUNRISE = datetime.strptime('06:00', '%H:%M')
SUNSET = datetime.strptime('18:00', '%H:%M')
def sun_angle(time, sunrise=SUNRISE, sunset=SUNSET):
 """Return the angle of the sun at `time`.
 Assumes that the sun moves 180 degrees between `sunrise` and `sunset`.
 During night return 'I don\'t see the sun!'.
 """
 time = datetime.strptime(time, '%H:%M')
 if not sunrise <= time <= sunset:
 return "I don't see the sun!"
 angle_per_hour = 180 / (sunset - sunrise).seconds * 3600
 time_since_sunrise = (time - sunrise).seconds / 3600
 return time_since_sunrise * angle_per_hour
if __name__ == "__main__":
 test_cases = [("07:00", 15),
 ("01:23", "I don't see the sun!"),
 ("12:15", 93.75)]
 for time, expected in test_cases:
 output = sun_angle(time)
 print(f"solar_angle({time!r}) == {output!r}")
 assert output == expected, f"Failed: expected {expected!r}!" 

The calculation of the sun angle could probably still be a bit better in order to be able to be extended for different latitudes in the future.

If this is not a class exercise or programming challenge, I would also recommend to change the interface of the function a bit. Make time always a datetime object and instead of returning a string in case of invalid input raise a custom exception:

class NightTimeException(ValueError):
 pass
...
 if not sunrise <= time <= sunset:
 raise NightTimeException("I don't see the sun!")
answered May 25, 2019 at 12:51
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.