Take the 2-minute tour ×

I have a list of strings as follows:


and I'm trying to find an effective way to create two time objects (I suppose this is the only way to keep track of a range of time, which I will later combine with a date object). It is clear to humans what we mean we say 11:00-1:00AM, but wondering what's an effective way to convert this to:

datetime.time(23, 0)
datetime.time(1, 0)

My current approach is to take the first time, and create a PM and AM version, take the timedelta with the end time (which is specified), and take the shorter of the two differences to be the correct one.

share|improve this question
It's much easier to help you when you show us (some of) your code. Also, your approach of interpreting the left-hand value as both AM and PM and picking the smaller delta is how I'd do it too. –  Martijn Pieters Jul 12 '12 at 7:35
wow that's a lot of code, you're overcomplicating the implementation. –  Rik Poggi Jul 12 '12 at 7:38
add comment

2 Answers

up vote 3 down vote accepted

Here is a simple implementation.

    >>> def timeRange(timestr):
    ...     t1, t2 = timestr.split("-")
    ...     timeFormat = "%I:%M%p"
    ...     t1AM = datetime.datetime.strptime(t1 + "AM", timeFormat)
    ...     t1PM = datetime.datetime.strptime(t1 + "PM", timeFormat)
    ...     t2 = datetime.datetime.strptime(t2, timeFormat)
    ...     if (t2 - t1AM).seconds < (t2-t1PM).seconds:
    ...         return t1AM.time(), t2.time()
    ...     else:
    ...         return t1PM.time(), t2.time()
    >>> timeRange("11:00-2:00PM")
    (datetime.time(11, 0), datetime.time(14, 0))
    >>> timeRange("4:00-5:00PM")
    (datetime.time(16, 0), datetime.time(17, 0))
    >>> timeRange("11:00-1:00AM")
    (datetime.time(23, 0), datetime.time(1, 0))
    >>> timeRange("12:00-1:00PM")
    (datetime.time(12, 0), datetime.time(13, 0))

This returns a time object, but you could roll that into a datetime object if you need to.

share|improve this answer
You could add another indicator in the returned tuple to indicate that the second time is on the next day, eg if the first time is PM and the second is AM. This may help when calculating the duration of the period as requested in the OP. Otherwise time(23, 0) -> time(1, 0) would be -22 hours... –  Andrew Alcock Jul 12 '12 at 8:05
Awesome! Thank you so much, I tried an implementation of my own and it is very similar to yours, though yours is more optimized. –  zhuyxn Jul 13 '12 at 3:52
add comment

There are two assumptions implicit in your question:

  • You are looking for the shortest possible duration between these times
  • The first time is the earlier of the two.

If these assumptions are true, then a quick optimization would be:

  • If the first time is larger than the second (eg 11:00-1:00AM or 11:00-1:00PM) then the earlier time is the 'opposite' AM/PM indicator of the second. Otherwise, the AM/PM of the first time is the same.

This works even for the largest time period, eg 6:00-6:00AM (6:00PM-6:00AM is shorter than 6:00AM-6:00AM)

A second observation is that you cannot use the simple time object because

  • An AM->PM duration takes place over a day boundary (midnight). This is probably screwing up the computation of your timedelta in this condition.

Therefore I think you have to use datetime, or wrap all this up in a structure that states the time in the first time object is the previous day.

Hope this helps :)

share|improve this answer
You are right, but you have to take care not to treat 6:00AM-6:00AM to have length 0. –  glglgl Jul 12 '12 at 7:51
6:00AM-6:00AM does not conform to the format the OP provided - the first time has no AM/PM indicator –  Andrew Alcock Jul 12 '12 at 7:59
That's right. But 6:00-6:00AM could be meant to be 6:00AM-6:00AM if 6:00AM-6:00AM has length 0 and is thus shorter than 6:00PM-6:00AM, which has 12 hours in any case. If, however, 6:00AM-6:00AM is meant to have 24 hours, 6:00PM-6:00AM is shorter and thus the solution. (To be completely unambiguous, some parts of the world could finally do the switch other parts already have done about 90 years ago and write 18:00-06:00 so that everybody knows what is meant. SCNR) –  glglgl Jul 12 '12 at 8:22
add comment

Your Answer


