#!/usr/bin/env python # # Humandate - a web service to humanize dates with Yahoo! Pipes # MS-potilas 2012. See http://yabtb.blogspot.com/2012/05/extending-yahoo-pipes-with-google-app.html # from google.appengine.ext import webapp from google.appengine.ext.webapp import util import simplejson # # MS-potilas: time humanizing code begins, borrowed from Django's "contrib.humanize". # import time from datetime import datetime, timedelta, date def _now(): return datetime.now() def abs_timedelta(delta): """Returns an "absolute" value for a timedelta, always representing a time distance.""" if delta.days < 0: now = _now() return now - (now + delta) return delta def date_and_delta(value): """Turn a value into a date and a timedelta which represents how long ago it was. If that's not possible, return (None, value).""" now = _now() if isinstance(value, datetime): date = value delta = now - value elif isinstance(value, timedelta): date = now - value delta = value else: try: value = int(value) delta = timedelta(seconds=value) date = now - delta except (ValueError, TypeError): return (None, value) return date, abs_timedelta(delta) def naturaldelta(value, months=True, onlyoneyear=True): """Given a timedelta or a number of seconds, return a natural representation of the amount of time elapsed. This is similar to ``naturaltime``, but does not add tense to the result. If ``months`` is True, then a number of months (based on 30.5 days) will be used for fuzziness between years. MS-potilas: if ``onlyoneyear`` is True, no fuzziness between years 1-2. Changed "an hour" to "1 hour" etc. (don't change "a moment"!) """ date, delta = date_and_delta(value) if date is None: return value use_months = months seconds = abs(delta.seconds) days = abs(delta.days) years = days // 365 days = days % 365 months = int(days // 30.5) if not years and days < 1: if seconds == 0: return "a moment" elif seconds == 1: return "1 second" elif seconds < 60: return "%d seconds" % (seconds) elif 60 <= seconds < 120: return "1 minute" elif 120 <= seconds < 3600: return "%d minutes" % (seconds // 60) elif 3600 <= seconds < 3600*2: return "1 hour" elif 3600 < seconds: return "%d hours" % (seconds // 3600) elif years == 0: if days == 1: return "1 day" if not use_months: return "%d days" % days else: if not months: return "%d days" % days elif months == 1: return "1 month" else: return "%d months" % months elif years == 1: if onlyoneyear: return "1 year" if not months and not days: return "1 year" elif not months: return "1 year, %d days" % days elif use_months: if months == 1: return "1 year, 1 month" else: return "1 year, %d months" % months else: return "1 year, %d days" % days else: return "%d years" % years def naturaltime(value, future=False, months=True): """Given a datetime or a number of seconds, return a natural representation of that time in a resolution that makes sense. This is more or less compatible with Django's ``naturaltime`` filter. ``future`` is ignored for datetimes, where the tense is always figured out based on the current time. If an integer is passed, the return value will be past tense by default, unless ``future`` is set to True.""" now = _now() date, delta = date_and_delta(value) if date is None: return value # determine tense by value only if datetime/timedelta were passed if isinstance(value, (datetime, timedelta)): future = date > now ago = 'from now' if future else 'ago' delta = naturaldelta(delta) if delta == "a moment": return "now" return "%s %s" % (delta, ago) # # MS-potilas: time humanizing code ends. # class MainHandler(webapp.RequestHandler): def get(self): try: utime = int(self.request.get("unixtime")) if utime > 0: dt = datetime.fromtimestamp(utime) self.response.headers['Content-Type'] = 'text/plain' self.response.out.write(naturaltime(dt)) except: self.response.headers.add_header("Cache-Control", "public, max-age=14400") self.response.out.write('Humanized Dates Web ServiceWorks either as Yahoo! Pipes web service: makes a new field "when" based on "y:published.utime",
or by giving url parameter unixtime, example. By MS-potilas 2012. See yabtb.blogspot.com.') self.response.out.write('') return 0; def post(self): try: data = self.request.get("data") items = simplejson.loads(data) items = items["items"] for item in items: utime = int(item['y:published']['utime']) dt = datetime.fromtimestamp(utime) item['when'] = naturaltime(dt) self.response.content_type = "application/json" simplejson.dump(items, self.response.out) finally: return 0; def main(): application = webapp.WSGIApplication([('/', MainHandler)], debug=True) util.run_wsgi_app(application) if __name__ == '__main__': main()