Commits

Josh VanderLinden  committed 28e6b2c

Added the ability to have entry, day, week, and period times displayed as HH:MM:SS instead of a floating-point number of hours

  • Participants
  • Parent commits 4ac462b

Comments (0)

Files changed (6)

File pendulum/models.py

 from django.contrib.sites.models import Site
 from django.contrib.auth.models import User
 from datetime import datetime, date, timedelta
-from pendulum.utils import determine_period
+from pendulum import utils
 
 try:
     """
         This will pull back any log entries for the current period.
         """
         try:
-            set = self.in_period(determine_period())
+            set = self.in_period(utils.determine_period())
         except PendulumConfiguration.DoesNotExist:
             raise Exception, "Please configure Pendulum!"
         else:
             return set
 
     def previous(self, delta, user=None):
-        set = self.in_period(determine_period(delta=delta))
+        set = self.in_period(utils.determine_period(delta=delta))
 
         if user:
             return set.filter(user=user)
 
     objects = EntryManager()
 
-    def __total_hours(self):
+    def get_seconds(self):
         """
-        Determine the total number of hours worked in this entry
+        Determines the difference between the starting and ending time.  The
+        result is returned as an integer of seconds.
         """
         if self.start_time and self.end_time:
             # only calculate when the start and end are defined
             seconds = 0
             delta = timedelta(days=0)
 
-        return seconds / 3600.0 + delta.days * 24
+        return seconds + (delta.days * 86400)
+
+    def __total_hours(self):
+        """
+        Determined the total number of hours worked in this entry
+        """
+        return self.get_seconds() / 3600.0
     total_hours = property(__total_hours)
 
+    def __total_time(self):
+        """
+        Determines the amount of time spent and return it as a string formatted
+        as HH:MM:SS
+        """
+        return utils.get_total_time(self.get_seconds())
+    total_time = property(__total_time)
+
     def __hours(self):
         """
         Print the hours in a nice, rounded format

File pendulum/templates/pendulum/_day_totals.html

             Hours for
             {{ day|date:"N j" }}:
         </th>
-        <td>{{ day_total|floatformat:2 }}</td>
+        <td>
+            {{ day_time }}<br />
+            ({{ day_total|floatformat:2 }})
+        </td>
         <td colspan="3">&nbsp;</td>
     </tr>

File pendulum/templates/pendulum/_week_totals.html

             {{ week_range.start|date:"N j" }}-
             {{ week_range.end|date:"N j" }}:
         </th>
-        <td>{{ week_total|floatformat:2 }}</td>
+        <td>
+            {{ week_time }}<br />
+            {{ week_total|floatformat:2 }}
+        </td>
         <td colspan="3">&nbsp;</td>
     </tr>

File pendulum/templates/pendulum/entry_list.html

             <a href="{% url pendulum-clock-out entry.id %}">Clock Out</a>
         {% endif %}</td>
         <td class="entry-hours">{% if entry.end_time %}
-            {{ entry.hours }}{% else %}
+            {{ entry.total_time }}<br />
+            ({{ entry.hours }}){% else %}
             {% if entry.is_paused %}
             <a href="{% url pendulum-toggle-paused entry.id %}">Unpause</a>
             {% else %}
         {% if forloop.first %}<table>{% endif %}
             <tr>
                 <th>{{ project.name }}</th>
-                <td>{% filter floatformat:2 %}
-                    {% hours_in_period project period %}
-                {% endfilter %}</td>
+                <td>
+                    {% time_in_period project period %}
+                    ({% filter floatformat:2 %}{% hours_in_period project period %}{% endfilter %})
+                </td>
             </tr>
         {% if forloop.last %}</table>{% endif %}
         {% endfor %}
         {% if forloop.first %}<table>{% endif %}
             <tr>
                 <th>{{ activity.name }}</th>
-                <td>{% filter floatformat:2 %}
-                    {% hours_in_period activity period %}
-                {% endfilter %}</td>
+                <td>
+                    {% time_in_period activity period %}
+                    ({% filter floatformat:2 %}{% hours_in_period activity period %}{% endfilter %})
+                </td>
             </tr>
         {% if forloop.last %}</table>{% endif %}
         {% endfor %}
     </tr>
     <tr>
         <th>Total Hours</th>
-        <td>{% filter floatformat:2 %}
-            {% total_hours_for_period period user %}
-        {% endfilter %}</td>
+        <td>
+            {% total_time_for_period period user %}
+            ({% filter floatformat:2 %}{% total_hours_for_period period user %}{% endfilter %})
+        </td>
     </tr>
     <tr>
         <th>Total Entries</th>

File pendulum/templatetags/pendulum_tags.py

 from django import template
 from pendulum.models import Entry
+from pendulum import utils
 from datetime import datetime, timedelta, time
 
 register = template.Library()
 
+def seconds_for_entries(entries):
+    seconds = [e.get_seconds() for e in entries]
+    return sum(seconds)
+
 def total_hours_for_period(period, user=None):
     """
     Determines how many hours have been logged for the current period.
     # add up all items in the list
     return sum(hours)
 
+def total_time_for_period(period, user=None):
+    """
+    Determines how much time has been logged for the current period.
+    """
+
+    # find all entries in the period
+    entries = Entry.objects.in_period(period, user)
+
+    seconds = seconds_for_entries(entries)
+    return utils.get_total_time(seconds)
+
 class EntriesProjectsOrActivitiesNode(template.Node):
     """
     Finds all projects or activities for a list of entries.  This tag is used to
 
     return EntriesProjectsOrActivitiesNode(entries, varname, activities=True)
 
-class HoursInPeriodNode(template.Node):
+class TimeInPeriodNode(template.Node):
     """
     Determines how many hours were logged during the specified period for a
     project or an activity (or any other object with an "entries" attribute).
     """
-    def __init__(self, obj, period):
+    def __init__(self, obj, period, time=False):
         self.obj = template.Variable(obj)
         self.period = template.Variable(period)
+        self.time = time
 
     def render(self, context):
         # pull the object back from the context
 
         # find all entries in that period
         entries = obj.entries.in_period(period, context['user'])
-        hours = [e.total_hours for e in entries]
-        return sum(hours)
+
+        if self.time:
+            seconds = seconds_for_entries(entries)
+            return utils.get_total_time(seconds)
+        else:
+            hours = [e.total_hours for e in entries]
+            return float(sum(hours))
 
 def hours_in_period(parser, token):
     """
     except ValueError:
         raise template.TemplateSyntaxError('hours_in_period usage: {% hours_in_period project period %}')
 
-    return HoursInPeriodNode(obj, period)
+    return TimeInPeriodNode(obj, period)
+
+def time_in_period(parser, token):
+    """
+    Used to determine how much time was logged for a particular project or
+    activitiy during the specified period.
+    """
+    try:
+        t, obj, period = token.split_contents()
+    except ValueError:
+        raise template.TemplateSyntaxError('time_in_period usage: {% time_in_period project period %}')
+
+    return TimeInPeriodNode(obj, period, time=True)
 
 class DayTotalsNode(template.Node):
     def __init__(self, date_obj):
         total = sum(hours)
 
         context['day_total'] = total
+        context['day_time'] = utils.get_total_time(seconds_for_entries(entries))
         context['day'] = date_obj
 
         t = template.loader.get_template('pendulum/_day_totals.html')
         total = sum(hours)
 
         context['week_total'] = total
+        context['week_time'] = utils.get_total_time(seconds_for_entries(entries))
         context['week_range'] = {'start': date_range[0],
                                  'end': date_range[1]}
 
     return WeekTotalsNode(date_obj)
 
 register.simple_tag(total_hours_for_period)
+register.simple_tag(total_time_for_period)
 register.tag(entries_projects)
 register.tag(entries_activities)
 register.tag(hours_in_period)
+register.tag(time_in_period)
 register.tag(day_totals)
 register.tag(week_totals)

File pendulum/utils.py

 
     # return None if there's no matching format
     return None
+
+def get_total_time(seconds):
+    """
+    Returns the specified number of seconds in an easy-to-read HH:MM:SS format
+    """
+    hours = int(seconds / 3600)
+    seconds %= 3600
+    minutes = int(seconds / 60)
+    seconds %= 60
+
+    return u'%02i:%02i:%02i' % (hours, minutes, seconds)