3

I'd like to create a list of hours that is a tuple of the 24-hour based time (in a digit) and a string representation of a 12-hour based time.

The format would be like this:

[(0, "12 AM"), (1, "1 AM), ..., (13, "1PM"), ... ]

I was able to get something like this

hours = [(0,"12 AM")]
hours += [(hour,str(hour) + " AM") for hour in range(1, 12)]
hours += [(12,"12 PM")]
hours += [(hour+12,str(hour) + " PM") for hour in range(1, 12)]

But I feel that there is a cleaner way of doing this, but can't figure it out.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
staackuser2
  • 12,172
  • 4
  • 42
  • 40

4 Answers4

13
import datetime as dt
hours = [(i, dt.time(i).strftime('%I %p')) for i in range(24)]
thule
  • 4,034
  • 21
  • 31
  • 1
    better than mine, but don't you want %l not %I for a non-zero-padded hour? (that's percent-lowercase-ell compared to percent-uppercase-eye) – jcomeau_ictx May 07 '11 at 08:42
  • @jcomeau_ictx i din't know this flag (%l) existed. It is not in the docs: http://docs.python.org/library/datetime.html?highlight=datetime#strftime-strptime-behavior . How did you?) – thule May 07 '11 at 09:21
  • %l (ell) doesn't exist apparently. In Python 2.5 it is silently ignored, in 2.7 it throws an "Invalid format string" error. – ThomasH May 07 '11 at 10:43
  • @ThomasH probably depends on underlying C library. I have it in 2.7 on OSX. – thule May 07 '11 at 13:24
  • @letitbee You're right, even the Python docs say so explicitly. They give a set of format flags that is supported on all platforms with a standard C implementation; %I (eye) is among them, %l (ell) is not. – ThomasH May 07 '11 at 13:49
  • @letitbee: I couldn't find it quickly with pydoc so I looked at the manpage for strftime, hoping the same format strings would work for Python. – jcomeau_ictx May 07 '11 at 15:11
3
>>> hours = [(n, "%d %s" % (n % 12 or 12, ["AM", "PM"][n > 11])) for n in range(24)]
>>> hours
[(0, '12 AM'), (1, '1 AM'), (2, '2 AM'), (3, '3 AM'), (4, '4 AM'), (5, '5 AM'), (6, '6 AM'), (7, '7 AM'), (8, '8 AM'), (9, '9 AM'), (10, '10 AM'), (11, '11 AM'), (12, '12 PM'), (13, '1 PM'), (14, '2 PM'), (15, '3 PM'), (16, '4 PM'), (17, '5 PM'), (18, '6 PM'), (19, '7 PM'), (20, '8 PM'), (21, '9 PM'), (22, '10 PM'), (23, '11 PM')]
jcomeau_ictx
  • 37,688
  • 6
  • 92
  • 107
  • some python purists will probably choke on the use of a boolean as an index into a 2-element array, can't please everybody though. – jcomeau_ictx May 07 '11 at 08:34
  • Not when you believe Alex Martelli http://stackoverflow.com/questions/3174392/is-it-pythonic-to-use-bools-as-ints/3175293#3175293 – ThomasH May 07 '11 at 10:48
0

I also found an alternative which I am using as a generator:

def dayrange(start_date):
for n in range(25):
    yield start_date + i*timedelta(hours = 1)

with start_date a datetime.datetime object.

Dr Mouse
  • 331
  • 1
  • 5
  • 19
0

Here's another one-liner for you:

[(hour24, '%d %s' % (hour12, (lambda x: 'AM' if x < 12 else 'PM')(hour24))) for hour12, hour24 in zip(([12]+range(1, 12)*2), range(0, 24))]
Zach Kelling
  • 52,505
  • 13
  • 109
  • 108