src/pyams_utils/date.py
changeset 1 3f89629b9e54
child 15 79a35932c5cc
equal deleted inserted replaced
0:16d47bd81d84 1:3f89629b9e54
       
     1 #
       
     2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
       
     3 # All Rights Reserved.
       
     4 #
       
     5 # This software is subject to the provisions of the Zope Public License,
       
     6 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    10 # FOR A PARTICULAR PURPOSE.
       
    11 #
       
    12 
       
    13 __docformat__ = 'restructuredtext'
       
    14 
       
    15 
       
    16 # import standard packages
       
    17 from datetime import datetime
       
    18 
       
    19 # import interfaces
       
    20 
       
    21 # import packages
       
    22 from pyams_utils.request import check_request
       
    23 from pyams_utils.timezone import gmtime, tztime
       
    24 from zope.datetime import parseDatetimetz
       
    25 
       
    26 from pyams_utils import _
       
    27 
       
    28 
       
    29 def unidate(value):
       
    30     """Get specified date converted to unicode ISO format
       
    31     
       
    32     Dates are always assumed to be stored in GMT timezone
       
    33     
       
    34     @param value: input date to convert to unicode
       
    35     @type value: date or datetime
       
    36     @return: input date converted to unicode
       
    37     @rtype: unicode
       
    38     """
       
    39     if value is not None:
       
    40         value = gmtime(value)
       
    41         return value.isoformat('T')
       
    42     return None
       
    43 
       
    44 
       
    45 def parse_date(value):
       
    46     """Get date specified in unicode ISO format to Python datetime object
       
    47     
       
    48     Dates are always assumed to be stored in GMT timezone
       
    49     
       
    50     @param value: unicode date to be parsed
       
    51     @type value: unicode
       
    52     @return: the specified value, converted to datetime
       
    53     @rtype: datetime
       
    54     """
       
    55     if value is not None:
       
    56         return gmtime(parseDatetimetz(value))
       
    57     return None
       
    58 
       
    59 
       
    60 def date_to_datetime(value):
       
    61     """Get datetime value converted from a date or datetime object
       
    62     
       
    63     @param value: a date or datetime value to convert
       
    64     @type value: date or datetime
       
    65     @return: input value converted to datetime
       
    66     @rtype: datetime
       
    67     """
       
    68     if type(value) is datetime:
       
    69         return value
       
    70     return datetime(value.year, value.month, value.day)
       
    71 
       
    72 
       
    73 SH_DATE_FORMAT = _("%d/%m/%Y")
       
    74 SH_DATETIME_FORMAT = _("%d/%m/%Y - %H:%M")
       
    75 
       
    76 EXT_DATE_FORMAT = _("on %d/%m/%Y")
       
    77 EXT_DATETIME_FORMAT = _("on %d/%m/%Y at %H:%M")
       
    78 
       
    79 
       
    80 def format_date(value, format=EXT_DATE_FORMAT, request=None):
       
    81     """Format given date with the given format"""
       
    82     if request is None:
       
    83         request = check_request()
       
    84     localizer = request.localizer
       
    85     return datetime.strftime(tztime(value), localizer.translate(format))
       
    86 
       
    87 
       
    88 def format_datetime(value, format=EXT_DATETIME_FORMAT, request=None):
       
    89     """Format given datetime with the given format"""
       
    90     return format_date(value, format, request)
       
    91 
       
    92 
       
    93 def get_age(value):
       
    94     """Get age of a given datetime (including timezone) compared to current datetime (in UTC)
       
    95     
       
    96     @param value: a datetime value, including timezone
       
    97     @type value: datetime
       
    98     @return: string representing value age
       
    99     @rtype: gettext translated string
       
   100     """
       
   101     request = check_request()
       
   102     translate = request.localizer.translate
       
   103     now = gmtime(datetime.utcnow())
       
   104     delta = now - value
       
   105     if delta.days > 60:
       
   106         return translate(_("%d months ago")) % int(round(delta.days * 1.0 / 30))
       
   107     elif delta.days > 10:
       
   108         return translate(_("%d weeks ago")) % int(round(delta.days * 1.0 / 7))
       
   109     elif delta.days > 2:
       
   110         return translate(_("%d days ago")) % delta.days
       
   111     elif delta.days == 2:
       
   112         return translate(_("the day before yesterday"))
       
   113     elif delta.days == 1:
       
   114         return translate(_("yesterday"))
       
   115     else:
       
   116         hours = int(round(delta.seconds * 1.0 / 3600))
       
   117         if hours > 1:
       
   118             return translate(_("%d hours ago")) % hours
       
   119         elif delta.seconds > 300:
       
   120             return translate(_("%d minutes ago")) % int(round(delta.seconds * 1.0 / 60))
       
   121         else:
       
   122             return translate(_("less than 5 minutes ago"))
       
   123 
       
   124 
       
   125 def get_duration(v1, v2=None, request=None):
       
   126     """Get delta as string between two dates
       
   127 
       
   128     >>> from datetime import datetime
       
   129     >>> from pyams_utils.date import get_duration
       
   130     >>> from pyramid.testing import DummyRequest
       
   131     >>> request = DummyRequest()
       
   132     >>> date1 = datetime(2015, 1, 1)
       
   133     >>> date2 = datetime(2014, 3, 1)
       
   134     >>> get_duration(date1, date2, request)
       
   135     '10 months'
       
   136 
       
   137     Dates order is not important:
       
   138     >>> get_duration(date2, date1, request)
       
   139     '10 months'
       
   140     >>> date2 = datetime(2014, 11, 10)
       
   141     >>> get_duration(date1, date2, request)
       
   142     '7 weeks'
       
   143     >>> date2 = datetime(2014, 12, 26)
       
   144     >>> get_duration(date1, date2, request)
       
   145     '6 days'
       
   146 
       
   147     For durations lower than 2 days, duration also display hours:
       
   148     >>> date1 = datetime(2015, 1, 1)
       
   149     >>> date2 = datetime(2015, 1, 2, 15, 10, 0)
       
   150     >>> get_duration(date1, date2, request)
       
   151     '1 day and 15 hours'
       
   152     >>> date2 = datetime(2015, 1, 2)
       
   153     >>> get_duration(date1, date2, request)
       
   154     '24 hours'
       
   155     >>> date2 = datetime(2015, 1, 1, 13, 12)
       
   156     >>> get_duration(date1, date2, request)
       
   157     '13 hours'
       
   158     >>> date2 = datetime(2015, 1, 1, 1, 15)
       
   159     >>> get_duration(date1, date2, request)
       
   160     '75 minutes'
       
   161     >>> date2 = datetime(2015, 1, 1, 0, 0, 15)
       
   162     >>> get_duration(date1, date2, request)
       
   163     '15 seconds'
       
   164     """
       
   165     if v2 is None:
       
   166         v2 = datetime.utcnow()
       
   167     assert isinstance(v1, datetime) and isinstance(v2, datetime)
       
   168     if request is None:
       
   169         request = check_request()
       
   170     translate = request.localizer.translate
       
   171     v1, v2 = min(v1, v2), max(v1, v2)
       
   172     delta = v2 - v1
       
   173     if delta.days > 60:
       
   174         return translate(_("%d months")) % int(round(delta.days * 1.0 / 30))
       
   175     elif delta.days > 10:
       
   176         return translate(_("%d weeks")) % int(round(delta.days * 1.0 / 7))
       
   177     elif delta.days >= 2:
       
   178         return translate(_("%d days")) % delta.days
       
   179     else:
       
   180         hours = int(round(delta.seconds * 1.0 / 3600))
       
   181         if delta.days == 1:
       
   182             if hours == 0:
       
   183                 return translate(_("24 hours"))
       
   184             else:
       
   185                 return translate(_("%d day and %d hours")) % (delta.days, hours)
       
   186         else:
       
   187             if hours > 2:
       
   188                 return translate(_("%d hours")) % hours
       
   189             else:
       
   190                 minutes = int(round(delta.seconds * 1.0 / 60))
       
   191                 if minutes > 2:
       
   192                     return translate(_("%d minutes")) % minutes
       
   193                 else:
       
   194                     return translate(_("%d seconds")) % delta.seconds