# Build a 12-hour digital clock

In my essay "Use the 24-hour clock", I claim that trying to represent the 12-hour clock directly in data is a terrible exercise in patchy, inelegant programming:

"No problem, we'll just use computers to do these calculations for us." Yes, but computers need to be programmed. And trying to account for AM and PM directly in a computer program, especially the extremely tricky way we've encoded it, with 12 representing 0, is prone to bugs and programming mistakes, which can cost millions at the airport in scheduling mishaps. As it is, it's much easier for computers to work in 24-hour time in internal calculations, and then convert the times to 12-hour time for easy human reading, instead of having to deal with dozens of notational issues as would be the case when using 12-hour time directly. In which case, why not just get rid of the whole 12-hour conversion and work with 24-hour time in the first place?

Here's your chance to prove me wrong. Your task is to build a `Clock` class that supports the following functions:

• `addHours(x)`, that advances the clock by `x` hours (or moves back `|x|` hours if `x` is negative)
• `addMinutes(x)`, that advances the clock by `x` minutes.
• `diffMinutes(c1, c2)` that gives the time difference from clock `c1` to clock `c2` in minutes (which always assumes that c1 and c2 are representing times in the same day). If `c2` is earlier than `c1`, the time should be negative.

and has the following publicly accessible variables:

• `hours`, which represents the hour digit of the clock, from 1 to 12.
• `minutes`, which represents the minute digit of the clock, from 0 to 59.
• `ampm`, which is `true` if the clock is AM and `false` if the clock is PM.

as well as a setter and getter method (e.g. `setHours(hours)` and `getHours()`) for each. (You may assume that the setters and getters will always be passed valid values.) The reason the variables must be publicly accessible is to ensure that the internal data representation of the clock is also in a 12-hour format, to fit the data representation of the clock described in the essay.

Your code must pass all the unit tests contained in this file (translated to the programming language of your choice) except for test 0.2, which should be removed for this problem. (If the descriptions of the corner cases and their resultant times start to make your head spin, that's good. It means that my point about the strangeness of the notation is verified. It certainly made my head spin trying to make sure I had all the corner cases covered.)

Your score is calculated based on the number of operators and function calls in your class code, rather than the number of characters (so don't golf your code, make it readable but still short). Lowest score wins, of course.

Note: This problem has a part 2, namely, to create a 12-hour clock that uses 24-hour time in its internal representation. If my hypothesis is true, the winner of that problem will have a much lower score than the winner of this problem.

-

## Python (38)

Full code with tests here. A ton of the tests were wrong, so I modified them. Most of the changes are marked with the string "patch" in a comment, but I'm sure I forgot to mark some.

It was completely unclear if `diffMinutes(a, b)` was `abs(a-b)`, `a-b` or `b-a`, so I went with `b-a` because I had to change less tests that way.

Also, `ampm` is a terrible variable name. `isAM` would be a far more readable name, and `isPM` would be preferable, as true and false are often associated with 1 and 0, and PM is a higher/later value.

The interesting part (getters and setters in the link above):

``````def getMinutesFromMidnight(clock):
return clock.hours * 60 % 720 + 720 * (not clock.ampm) + clock.minutes

def diffMinutes(a,b):
return getMinutesFromMidnight(b) - getMinutesFromMidnight(a)

class Clock(object):
def __init__(self):
self.hours = 12
self.minutes = 0
self.ampm = True

Yeah, `ampm` is a pretty bad variable name. It's a carry-over from `ampm` being "am" and "pm" text variables instead, but I just didn't change it when I decided to use a boolean variable instead. – Joe Z. Feb 24 '13 at 3:07