--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_utils/date.py Thu Feb 19 00:46:48 2015 +0100
@@ -0,0 +1,194 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard packages
+from datetime import datetime
+
+# import interfaces
+
+# import packages
+from pyams_utils.request import check_request
+from pyams_utils.timezone import gmtime, tztime
+from zope.datetime import parseDatetimetz
+
+from pyams_utils import _
+
+
+def unidate(value):
+ """Get specified date converted to unicode ISO format
+
+ Dates are always assumed to be stored in GMT timezone
+
+ @param value: input date to convert to unicode
+ @type value: date or datetime
+ @return: input date converted to unicode
+ @rtype: unicode
+ """
+ if value is not None:
+ value = gmtime(value)
+ return value.isoformat('T')
+ return None
+
+
+def parse_date(value):
+ """Get date specified in unicode ISO format to Python datetime object
+
+ Dates are always assumed to be stored in GMT timezone
+
+ @param value: unicode date to be parsed
+ @type value: unicode
+ @return: the specified value, converted to datetime
+ @rtype: datetime
+ """
+ if value is not None:
+ return gmtime(parseDatetimetz(value))
+ return None
+
+
+def date_to_datetime(value):
+ """Get datetime value converted from a date or datetime object
+
+ @param value: a date or datetime value to convert
+ @type value: date or datetime
+ @return: input value converted to datetime
+ @rtype: datetime
+ """
+ if type(value) is datetime:
+ return value
+ return datetime(value.year, value.month, value.day)
+
+
+SH_DATE_FORMAT = _("%d/%m/%Y")
+SH_DATETIME_FORMAT = _("%d/%m/%Y - %H:%M")
+
+EXT_DATE_FORMAT = _("on %d/%m/%Y")
+EXT_DATETIME_FORMAT = _("on %d/%m/%Y at %H:%M")
+
+
+def format_date(value, format=EXT_DATE_FORMAT, request=None):
+ """Format given date with the given format"""
+ if request is None:
+ request = check_request()
+ localizer = request.localizer
+ return datetime.strftime(tztime(value), localizer.translate(format))
+
+
+def format_datetime(value, format=EXT_DATETIME_FORMAT, request=None):
+ """Format given datetime with the given format"""
+ return format_date(value, format, request)
+
+
+def get_age(value):
+ """Get age of a given datetime (including timezone) compared to current datetime (in UTC)
+
+ @param value: a datetime value, including timezone
+ @type value: datetime
+ @return: string representing value age
+ @rtype: gettext translated string
+ """
+ request = check_request()
+ translate = request.localizer.translate
+ now = gmtime(datetime.utcnow())
+ delta = now - value
+ if delta.days > 60:
+ return translate(_("%d months ago")) % int(round(delta.days * 1.0 / 30))
+ elif delta.days > 10:
+ return translate(_("%d weeks ago")) % int(round(delta.days * 1.0 / 7))
+ elif delta.days > 2:
+ return translate(_("%d days ago")) % delta.days
+ elif delta.days == 2:
+ return translate(_("the day before yesterday"))
+ elif delta.days == 1:
+ return translate(_("yesterday"))
+ else:
+ hours = int(round(delta.seconds * 1.0 / 3600))
+ if hours > 1:
+ return translate(_("%d hours ago")) % hours
+ elif delta.seconds > 300:
+ return translate(_("%d minutes ago")) % int(round(delta.seconds * 1.0 / 60))
+ else:
+ return translate(_("less than 5 minutes ago"))
+
+
+def get_duration(v1, v2=None, request=None):
+ """Get delta as string between two dates
+
+ >>> from datetime import datetime
+ >>> from pyams_utils.date import get_duration
+ >>> from pyramid.testing import DummyRequest
+ >>> request = DummyRequest()
+ >>> date1 = datetime(2015, 1, 1)
+ >>> date2 = datetime(2014, 3, 1)
+ >>> get_duration(date1, date2, request)
+ '10 months'
+
+ Dates order is not important:
+ >>> get_duration(date2, date1, request)
+ '10 months'
+ >>> date2 = datetime(2014, 11, 10)
+ >>> get_duration(date1, date2, request)
+ '7 weeks'
+ >>> date2 = datetime(2014, 12, 26)
+ >>> get_duration(date1, date2, request)
+ '6 days'
+
+ For durations lower than 2 days, duration also display hours:
+ >>> date1 = datetime(2015, 1, 1)
+ >>> date2 = datetime(2015, 1, 2, 15, 10, 0)
+ >>> get_duration(date1, date2, request)
+ '1 day and 15 hours'
+ >>> date2 = datetime(2015, 1, 2)
+ >>> get_duration(date1, date2, request)
+ '24 hours'
+ >>> date2 = datetime(2015, 1, 1, 13, 12)
+ >>> get_duration(date1, date2, request)
+ '13 hours'
+ >>> date2 = datetime(2015, 1, 1, 1, 15)
+ >>> get_duration(date1, date2, request)
+ '75 minutes'
+ >>> date2 = datetime(2015, 1, 1, 0, 0, 15)
+ >>> get_duration(date1, date2, request)
+ '15 seconds'
+ """
+ if v2 is None:
+ v2 = datetime.utcnow()
+ assert isinstance(v1, datetime) and isinstance(v2, datetime)
+ if request is None:
+ request = check_request()
+ translate = request.localizer.translate
+ v1, v2 = min(v1, v2), max(v1, v2)
+ delta = v2 - v1
+ if delta.days > 60:
+ return translate(_("%d months")) % int(round(delta.days * 1.0 / 30))
+ elif delta.days > 10:
+ return translate(_("%d weeks")) % int(round(delta.days * 1.0 / 7))
+ elif delta.days >= 2:
+ return translate(_("%d days")) % delta.days
+ else:
+ hours = int(round(delta.seconds * 1.0 / 3600))
+ if delta.days == 1:
+ if hours == 0:
+ return translate(_("24 hours"))
+ else:
+ return translate(_("%d day and %d hours")) % (delta.days, hours)
+ else:
+ if hours > 2:
+ return translate(_("%d hours")) % hours
+ else:
+ minutes = int(round(delta.seconds * 1.0 / 60))
+ if minutes > 2:
+ return translate(_("%d minutes")) % minutes
+ else:
+ return translate(_("%d seconds")) % delta.seconds