changeset 2303:7090e394df06 beta

Rewrite of the age() utility function so it can be translated.
author Vincent Duvert <vincent@duvert.net>
date Sat, 19 May 2012 22:56:32 +0200
parents 66fa6c434ce4
children f1b76a558a66
files rhodecode/lib/utils2.py
diffstat 1 files changed, 62 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/lib/utils2.py	Sat May 19 23:32:08 2012 +0200
+++ b/rhodecode/lib/utils2.py	Sat May 19 22:56:32 2012 +0200
@@ -24,6 +24,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import re
+from datetime import datetime
+from pylons.i18n.translation import _, ungettext
 from rhodecode.lib.vcs.utils.lazy import LazyProperty
 
 
@@ -284,40 +286,76 @@
     return engine
 
 
-def age(curdate):
+def age(prevdate):
     """
     turns a datetime into an age string.
 
-    :param curdate: datetime object
+    :param prevdate: datetime object
     :rtype: unicode
     :returns: unicode words describing age
     """
 
-    from datetime import datetime
-    from webhelpers.date import time_ago_in_words
+    order = ['year', 'month', 'day', 'hour', 'minute', 'second']
+    deltas = {}
+
+    # Get date parts deltas
+    now = datetime.now()
+    for part in order:
+        deltas[part] = getattr(now, part) - getattr(prevdate, part)
 
-    _ = lambda s: s
+    # Fix negative offsets (there is 1 second between 10:59:59 and 11:00:00,
+    # not 1 hour, -59 minutes and -59 seconds)
 
-    if not curdate:
-        return ''
+    for num, length in [(5, 60), (4, 60), (3, 24)]:  # seconds, minutes, hours
+        part = order[num]
+        carry_part = order[num - 1]
+        
+        if deltas[part] < 0:
+            deltas[part] += length
+            deltas[carry_part] -= 1
 
-    agescales = [(_(u"year"), 3600 * 24 * 365),
-                 (_(u"month"), 3600 * 24 * 30),
-                 (_(u"day"), 3600 * 24),
-                 (_(u"hour"), 3600),
-                 (_(u"minute"), 60),
-                 (_(u"second"), 1), ]
-
-    age = datetime.now() - curdate
-    age_seconds = (age.days * agescales[2][1]) + age.seconds
-    pos = 1
-    for scale in agescales:
-        if scale[1] <= age_seconds:
-            if pos == 6:
-                pos = 5
-            return '%s %s' % (time_ago_in_words(curdate,
-                                                agescales[pos][0]), _('ago'))
-        pos += 1
+    # Same thing for days except that the increment depends on the (variable)
+    # number of days in the month
+    month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+    if deltas['day'] < 0:
+        if prevdate.month == 2 and (prevdate.year % 4 == 0 and
+            (prevdate.year % 100 != 0 or prevdate.year % 400 == 0)):
+            deltas['day'] += 29
+        else:
+            deltas['day'] += month_lengths[prevdate.month - 1]
+        
+        deltas['month'] -= 1
+    
+    if deltas['month'] < 0:
+        deltas['month'] += 12
+        deltas['year'] -= 1
+    
+    # Format the result
+    fmt_funcs = {
+        'year': lambda d: ungettext(u'%d year', '%d years', d) % d,
+        'month': lambda d: ungettext(u'%d month', '%d months', d) % d,
+        'day': lambda d: ungettext(u'%d day', '%d days', d) % d,
+        'hour': lambda d: ungettext(u'%d hour', '%d hours', d) % d,
+        'minute': lambda d: ungettext(u'%d minute', '%d minutes', d) % d,
+        'second': lambda d: ungettext(u'%d second', '%d seconds', d) % d,
+    }
+    
+    for i, part in enumerate(order):
+        value = deltas[part]
+        if value == 0:
+            continue
+        
+        if i < 5:
+            sub_part = order[i + 1]
+            sub_value = deltas[sub_part]
+        else:
+            sub_value = 0
+        
+        if sub_value == 0:
+            return _(u'%s ago') % fmt_funcs[part](value)
+        
+        return _(u'%s and %s ago') % (fmt_funcs[part](value),
+            fmt_funcs[sub_part](sub_value))
 
     return _(u'just now')