2
\$\begingroup\$

Create a Time class.

Time is on my side

Specification

  • Basic attributes: hour, minute, second and day (default is 0), + getters, + setters (using a decorator)

  • If you try to initialize an incorrect value of seconds or minutes, i.e. greater than or equal to 60, raise an exception from your own WrongSeconds or WrongMinutes class

Add the following operators:

  • +: works as follows - adds hours to hours, minutes to minutes, and so on, e.g. 2 h 30 m 4 s + 6 h 35 m 50 s = 9 h 5 m 54 s (we also return an instance of the Time class), if we exceed 24 h, the day should be 1

  • <: Compare first day, hours, then minutes, seconds. Return True / False, e.g. 2 h 40 m 30 s d 0 < 1 h 59 m 30 s d 0 → False, 2 h 40 m 30 s d -1 < 1 h 59 m 30 s d 0 → True

  • __str__: Time should be displayed as: "20:05:25, day without any changes" (when day = 1, -1 : next / previous day)

Add the function zone, which for a given instance of the Time class returns the appropriate time in another time zone. The argument of the function is the city for which we find the time: Warsaw, London, New York, Tokyo, Syndey, Moscow, Los Angeles. We assume that the default time is GMT.

  • PEP8
  • DOC
  • tests

And here is the code!

class WrongSeconds(Exception): def __str__(self): return "Wrong amount of seconds passed (greater or equal 60)" class WrongMinutes(Exception): def __str__(self): return "Wrong amount of minutes passed (greater or equal 60)" class Time: TIME_ZONES = { "Warsaw": 2, "London": 1, "Tokio": 9, "Sydney": 10, "Moscow": 3, "Los angeles": -7 } def __init__(self, d = 0, h = 0, m = 0, s = 0): self.days = d self.hours = h self.minutes = m self.seconds = s @property def days(self): return self._d @days.setter def days(self, val): self._d = val @property def hours(self): return self._h @hours.setter def hours(self, val): if val < 0: self.days += val//60 val = 24 - abs(val)%24 elif val >= 24: self.days += val//24 val %= 24 self._h = val @property def minutes(self): return self._m @minutes.setter def minutes(self, val): if "_m" not in self.__dict__ and val >= 60: raise WrongMinutes if val < 0: self.hours += val//60 val = 60 - abs(val)%60 elif val >= 60: self.hours += val//60 val %= 60 self._m = val @property def seconds(self): return self._s @seconds.setter def seconds(self, val): if "_s" not in self.__dict__ and val >= 60: raise WrongSeconds if val < 0: self.minutes += val//60 val = 60 - abs(val)%60 elif val >= 60: self.minutes += val//60 val %= 60 self._s = val def strefa(self, city): if city.capitalize() not in self.TIME_ZONES: raise ValueError(f"City {city} not in time zone database") result_time = self.__class__( self.days, self.hours, self.minutes, self.seconds) result_time.hours += self.TIME_ZONES[city.capitalize()] return str(result_time) def __add__(self, other): assert isinstance(other, self.__class__), f"Cannot add {type(other)} to a time object" result = self.__class__() result.seconds += self.seconds + other.seconds result.minutes += self.minutes + other.minutes result.hours += self.hours + other.hours result.days += self.days + other.days return result def __lt__(self, other): assert isinstance(other, self.__class__), f"Cannot compare {type(other)} with a time object" if self.days < other.days: return True elif self.hours < other.hours: return True elif self.minutes < other.minutes: return True elif self.seconds < other.seconds: return True return False def __str__(self): s = f"{self.hours}:{self.minutes:02}:{self.seconds:02}" if self.days == 0 : return s + ", day without any changes" elif self.days == 1 : return s + ", the next day" elif self.days == -1 : return s + ", previous day" return s + f", day: {self.days}" # --- TEST CASES --- try: time = Time(m = 60) except Exception as e: print(e.__class__, e, "\n") time = Time(d = 0, h = 23, m = 59, s = 59) print(time) time.seconds += 1 print(time, "\n") time1 = Time(h = 3, m = 2, s = 1) time2 = Time(h = 6, m = 5, s = 4) print(time1 + time2, "\n") print(time1 < time2 ) print(time2 < time1, "\n") time_gmt = Time(h = 2, m = 0, s = 0) print(time_gmt.strefa("London")) print(time_gmt.strefa("Sydney")) print(time_gmt.strefa("Los Angeles")) print("------------------------------------") print("Comparisons") t1 = Time(h = 14, m = 4, s = 35) t2 = Time(h = 8, m = 50, s = 25) print(t1 + t2) print(t1) print(t2) print(t1 < t2) 

Output:

<class '__main__.WrongMinutes'> Wrong amount of minutes passed (greater or equal 60) 23:59:59, day without any changes 0:00:00, the next day 9:07:05, day without any changes True False 3:00:00, day without any changes 12:00:00, day without any changes 19:00:00, previous day ------------------------------------ Comparisons 22:55:00, day without any changes 14:04:35, day without any changes 8:50:25, day without any changes True 

And here is my question, how to get a better solution? Maybe shorter? Maybe get rid of some operations, terms?

\$\endgroup\$
6
  • \$\begingroup\$If you can't represent the 61st second of a minute, what's supposed to happen when there's a leap second??\$\endgroup\$CommentedJun 22, 2021 at 16:19
  • \$\begingroup\$um raise a wrongseconds/wrongminutes error i guess\$\endgroup\$CommentedJun 22, 2021 at 16:21
  • \$\begingroup\$That's fine - the code just pretends leap seconds don't exist. I'm poking fun a little, but also pointing out that real date-time code has a lot of awkward real-world stuff to deal with, so better using the libraries than writing your own for actual use.\$\endgroup\$CommentedJun 22, 2021 at 16:23
  • 1
    \$\begingroup\$Well you know, sometimes (because its a task for school) I also don't see any sense in creating such complicated and thus simple things, but yeah, here we are! :D\$\endgroup\$CommentedJun 22, 2021 at 16:25
  • \$\begingroup\$One comment is, whenever you are implementing either of the comparison operators, you need to make sure you always implement them all. This would be, <, <=, >, >=, == and !=. Otherwise, the whoever used your Time class might run into trouble during comparisons without noticing.\$\endgroup\$CommentedJun 22, 2021 at 19:35

1 Answer 1

1
\$\begingroup\$

One small point:

When we inherit from Exception, we get its (actually, BaseException's) str() implementation, so we don't need to provide __str__() if we initialise the base class args with the required string:

class WrongSeconds(Exception): def __init__(self): self.args = [ "Wrong amount of seconds passed (greater or equal 60)" ] 

In the addition, we have these new values:

 result.seconds += self.seconds + other.seconds result.minutes += self.minutes + other.minutes result.hours += self.hours + other.hours result.days += self.days + other.days 

I don't see anything that handles overflow of any of these values (e.g. if hours > 24, we need to add a day and subtract 24 of the hours to get the values back into their allowed ranges).

\$\endgroup\$

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.