Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Effective way to convert ambiguous hours into time object?

I have a list of strings as follows:

4:00-5:00PM
11:00-2:00PM
12:00-1:00PM
11:00-1:00AM

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.

like image 376
zhuyxn Avatar asked Jul 12 '12 07:07

zhuyxn


2 Answers

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("11:00-2:00PM")
    (datetime.time(11, 0), datetime.time(14, 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.

like image 91
BrenBarn Avatar answered Sep 24 '22 03:09

BrenBarn


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 :)

like image 32
Andrew Alcock Avatar answered Sep 25 '22 03:09

Andrew Alcock