Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Unified Diff: third_party/logilab/logilab/common/date.py

Issue 1920403002: [content/test/gpu] Run pylint check of gpu tests in unittest instead of PRESUBMIT (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update path to LICENSE.txt of logilab/README.chromium Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/logilab/logilab/common/daemon.py ('k') | third_party/logilab/logilab/common/dbf.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/logilab/logilab/common/date.py
diff --git a/third_party/logilab/logilab/common/date.py b/third_party/logilab/logilab/common/date.py
new file mode 100644
index 0000000000000000000000000000000000000000..a093a8a9bbc8c1a69fa51db3c212a3162c115944
--- /dev/null
+++ b/third_party/logilab/logilab/common/date.py
@@ -0,0 +1,335 @@
+# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of logilab-common.
+#
+# logilab-common is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option) any
+# later version.
+#
+# logilab-common is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with logilab-common. If not, see <http://www.gnu.org/licenses/>.
+"""Date manipulation helper functions."""
+from __future__ import division
+
+__docformat__ = "restructuredtext en"
+
+import math
+import re
+import sys
+from locale import getlocale, LC_TIME
+from datetime import date, time, datetime, timedelta
+from time import strptime as time_strptime
+from calendar import monthrange, timegm
+
+from six.moves import range
+
+try:
+ from mx.DateTime import RelativeDateTime, Date, DateTimeType
+except ImportError:
+ endOfMonth = None
+ DateTimeType = datetime
+else:
+ endOfMonth = RelativeDateTime(months=1, day=-1)
+
+# NOTE: should we implement a compatibility layer between date representations
+# as we have in lgc.db ?
+
+FRENCH_FIXED_HOLIDAYS = {
+ 'jour_an': '%s-01-01',
+ 'fete_travail': '%s-05-01',
+ 'armistice1945': '%s-05-08',
+ 'fete_nat': '%s-07-14',
+ 'assomption': '%s-08-15',
+ 'toussaint': '%s-11-01',
+ 'armistice1918': '%s-11-11',
+ 'noel': '%s-12-25',
+ }
+
+FRENCH_MOBILE_HOLIDAYS = {
+ 'paques2004': '2004-04-12',
+ 'ascension2004': '2004-05-20',
+ 'pentecote2004': '2004-05-31',
+
+ 'paques2005': '2005-03-28',
+ 'ascension2005': '2005-05-05',
+ 'pentecote2005': '2005-05-16',
+
+ 'paques2006': '2006-04-17',
+ 'ascension2006': '2006-05-25',
+ 'pentecote2006': '2006-06-05',
+
+ 'paques2007': '2007-04-09',
+ 'ascension2007': '2007-05-17',
+ 'pentecote2007': '2007-05-28',
+
+ 'paques2008': '2008-03-24',
+ 'ascension2008': '2008-05-01',
+ 'pentecote2008': '2008-05-12',
+
+ 'paques2009': '2009-04-13',
+ 'ascension2009': '2009-05-21',
+ 'pentecote2009': '2009-06-01',
+
+ 'paques2010': '2010-04-05',
+ 'ascension2010': '2010-05-13',
+ 'pentecote2010': '2010-05-24',
+
+ 'paques2011': '2011-04-25',
+ 'ascension2011': '2011-06-02',
+ 'pentecote2011': '2011-06-13',
+
+ 'paques2012': '2012-04-09',
+ 'ascension2012': '2012-05-17',
+ 'pentecote2012': '2012-05-28',
+ }
+
+# XXX this implementation cries for multimethod dispatching
+
+def get_step(dateobj, nbdays=1):
+ # assume date is either a python datetime or a mx.DateTime object
+ if isinstance(dateobj, date):
+ return ONEDAY * nbdays
+ return nbdays # mx.DateTime is ok with integers
+
+def datefactory(year, month, day, sampledate):
+ # assume date is either a python datetime or a mx.DateTime object
+ if isinstance(sampledate, datetime):
+ return datetime(year, month, day)
+ if isinstance(sampledate, date):
+ return date(year, month, day)
+ return Date(year, month, day)
+
+def weekday(dateobj):
+ # assume date is either a python datetime or a mx.DateTime object
+ if isinstance(dateobj, date):
+ return dateobj.weekday()
+ return dateobj.day_of_week
+
+def str2date(datestr, sampledate):
+ # NOTE: datetime.strptime is not an option until we drop py2.4 compat
+ year, month, day = [int(chunk) for chunk in datestr.split('-')]
+ return datefactory(year, month, day, sampledate)
+
+def days_between(start, end):
+ if isinstance(start, date):
+ delta = end - start
+ # datetime.timedelta.days is always an integer (floored)
+ if delta.seconds:
+ return delta.days + 1
+ return delta.days
+ else:
+ return int(math.ceil((end - start).days))
+
+def get_national_holidays(begin, end):
+ """return french national days off between begin and end"""
+ begin = datefactory(begin.year, begin.month, begin.day, begin)
+ end = datefactory(end.year, end.month, end.day, end)
+ holidays = [str2date(datestr, begin)
+ for datestr in FRENCH_MOBILE_HOLIDAYS.values()]
+ for year in range(begin.year, end.year+1):
+ for datestr in FRENCH_FIXED_HOLIDAYS.values():
+ date = str2date(datestr % year, begin)
+ if date not in holidays:
+ holidays.append(date)
+ return [day for day in holidays if begin <= day < end]
+
+def add_days_worked(start, days):
+ """adds date but try to only take days worked into account"""
+ step = get_step(start)
+ weeks, plus = divmod(days, 5)
+ end = start + ((weeks * 7) + plus) * step
+ if weekday(end) >= 5: # saturday or sunday
+ end += (2 * step)
+ end += len([x for x in get_national_holidays(start, end + step)
+ if weekday(x) < 5]) * step
+ if weekday(end) >= 5: # saturday or sunday
+ end += (2 * step)
+ return end
+
+def nb_open_days(start, end):
+ assert start <= end
+ step = get_step(start)
+ days = days_between(start, end)
+ weeks, plus = divmod(days, 7)
+ if weekday(start) > weekday(end):
+ plus -= 2
+ elif weekday(end) == 6:
+ plus -= 1
+ open_days = weeks * 5 + plus
+ nb_week_holidays = len([x for x in get_national_holidays(start, end+step)
+ if weekday(x) < 5 and x < end])
+ open_days -= nb_week_holidays
+ if open_days < 0:
+ return 0
+ return open_days
+
+def date_range(begin, end, incday=None, incmonth=None):
+ """yields each date between begin and end
+
+ :param begin: the start date
+ :param end: the end date
+ :param incr: the step to use to iterate over dates. Default is
+ one day.
+ :param include: None (means no exclusion) or a function taking a
+ date as parameter, and returning True if the date
+ should be included.
+
+ When using mx datetime, you should *NOT* use incmonth argument, use instead
+ oneDay, oneHour, oneMinute, oneSecond, oneWeek or endOfMonth (to enumerate
+ months) as `incday` argument
+ """
+ assert not (incday and incmonth)
+ begin = todate(begin)
+ end = todate(end)
+ if incmonth:
+ while begin < end:
+ yield begin
+ begin = next_month(begin, incmonth)
+ else:
+ incr = get_step(begin, incday or 1)
+ while begin < end:
+ yield begin
+ begin += incr
+
+# makes py datetime usable #####################################################
+
+ONEDAY = timedelta(days=1)
+ONEWEEK = timedelta(days=7)
+
+try:
+ strptime = datetime.strptime
+except AttributeError: # py < 2.5
+ from time import strptime as time_strptime
+ def strptime(value, format):
+ return datetime(*time_strptime(value, format)[:6])
+
+def strptime_time(value, format='%H:%M'):
+ return time(*time_strptime(value, format)[3:6])
+
+def todate(somedate):
+ """return a date from a date (leaving unchanged) or a datetime"""
+ if isinstance(somedate, datetime):
+ return date(somedate.year, somedate.month, somedate.day)
+ assert isinstance(somedate, (date, DateTimeType)), repr(somedate)
+ return somedate
+
+def totime(somedate):
+ """return a time from a time (leaving unchanged), date or datetime"""
+ # XXX mx compat
+ if not isinstance(somedate, time):
+ return time(somedate.hour, somedate.minute, somedate.second)
+ assert isinstance(somedate, (time)), repr(somedate)
+ return somedate
+
+def todatetime(somedate):
+ """return a date from a date (leaving unchanged) or a datetime"""
+ # take care, datetime is a subclass of date
+ if isinstance(somedate, datetime):
+ return somedate
+ assert isinstance(somedate, (date, DateTimeType)), repr(somedate)
+ return datetime(somedate.year, somedate.month, somedate.day)
+
+def datetime2ticks(somedate):
+ return timegm(somedate.timetuple()) * 1000
+
+def ticks2datetime(ticks):
+ miliseconds, microseconds = divmod(ticks, 1000)
+ try:
+ return datetime.fromtimestamp(miliseconds)
+ except (ValueError, OverflowError):
+ epoch = datetime.fromtimestamp(0)
+ nb_days, seconds = divmod(int(miliseconds), 86400)
+ delta = timedelta(nb_days, seconds=seconds, microseconds=microseconds)
+ try:
+ return epoch + delta
+ except (ValueError, OverflowError):
+ raise
+
+def days_in_month(somedate):
+ return monthrange(somedate.year, somedate.month)[1]
+
+def days_in_year(somedate):
+ feb = date(somedate.year, 2, 1)
+ if days_in_month(feb) == 29:
+ return 366
+ else:
+ return 365
+
+def previous_month(somedate, nbmonth=1):
+ while nbmonth:
+ somedate = first_day(somedate) - ONEDAY
+ nbmonth -= 1
+ return somedate
+
+def next_month(somedate, nbmonth=1):
+ while nbmonth:
+ somedate = last_day(somedate) + ONEDAY
+ nbmonth -= 1
+ return somedate
+
+def first_day(somedate):
+ return date(somedate.year, somedate.month, 1)
+
+def last_day(somedate):
+ return date(somedate.year, somedate.month, days_in_month(somedate))
+
+def ustrftime(somedate, fmt='%Y-%m-%d'):
+ """like strftime, but returns a unicode string instead of an encoded
+ string which may be problematic with localized date.
+ """
+ if sys.version_info >= (3, 3):
+ # datetime.date.strftime() supports dates since year 1 in Python >=3.3.
+ return somedate.strftime(fmt)
+ else:
+ try:
+ if sys.version_info < (3, 0):
+ encoding = getlocale(LC_TIME)[1] or 'ascii'
+ return unicode(somedate.strftime(str(fmt)), encoding)
+ else:
+ return somedate.strftime(fmt)
+ except ValueError:
+ if somedate.year >= 1900:
+ raise
+ # datetime is not happy with dates before 1900
+ # we try to work around this, assuming a simple
+ # format string
+ fields = {'Y': somedate.year,
+ 'm': somedate.month,
+ 'd': somedate.day,
+ }
+ if isinstance(somedate, datetime):
+ fields.update({'H': somedate.hour,
+ 'M': somedate.minute,
+ 'S': somedate.second})
+ fmt = re.sub('%([YmdHMS])', r'%(\1)02d', fmt)
+ return unicode(fmt) % fields
+
+def utcdatetime(dt):
+ if dt.tzinfo is None:
+ return dt
+ return (dt.replace(tzinfo=None) - dt.utcoffset())
+
+def utctime(dt):
+ if dt.tzinfo is None:
+ return dt
+ return (dt + dt.utcoffset() + dt.dst()).replace(tzinfo=None)
+
+def datetime_to_seconds(date):
+ """return the number of seconds since the begining of the day for that date
+ """
+ return date.second+60*date.minute + 3600*date.hour
+
+def timedelta_to_days(delta):
+ """return the time delta as a number of seconds"""
+ return delta.days + delta.seconds / (3600*24)
+
+def timedelta_to_seconds(delta):
+ """return the time delta as a fraction of days"""
+ return delta.days*(3600*24) + delta.seconds
« no previous file with comments | « third_party/logilab/logilab/common/daemon.py ('k') | third_party/logilab/logilab/common/dbf.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698