10 from logilab.mtconverter import xml_escape |
10 from logilab.mtconverter import xml_escape |
11 |
11 |
12 import locale |
12 import locale |
13 import sys |
13 import sys |
14 import decimal |
14 import decimal |
15 import datetime as pydatetime |
15 import datetime |
16 from md5 import md5 |
16 from md5 import md5 |
17 from datetime import datetime, timedelta, date |
17 from time import time |
18 from time import time, mktime |
|
19 from random import randint, seed |
18 from random import randint, seed |
20 from calendar import monthrange |
|
21 import decimal |
19 import decimal |
|
20 |
|
21 from logilab.common.date import strptime, todate, next_month |
22 |
22 |
23 # initialize random seed from current time |
23 # initialize random seed from current time |
24 seed() |
24 seed() |
25 try: |
25 |
26 strptime = datetime.strptime |
26 # XXX should replace lgc.date.date_range implementation |
27 except AttributeError: # py < 2.5 |
|
28 from time import strptime as time_strptime |
|
29 def strptime(value, format): |
|
30 return datetime(*time_strptime(value, format)[:6]) |
|
31 |
|
32 def todate(somedate): |
|
33 """return a date from a date (leaving unchanged) or a datetime""" |
|
34 if isinstance(somedate, datetime): |
|
35 return date(somedate.year, somedate.month, somedate.day) |
|
36 assert isinstance(somedate, date), repr(somedate) |
|
37 return somedate |
|
38 |
|
39 def todatetime(somedate): |
|
40 """return a date from a date (leaving unchanged) or a datetime""" |
|
41 # take care, datetime is a subclass of date |
|
42 if isinstance(somedate, datetime): |
|
43 return somedate |
|
44 assert isinstance(somedate, date), repr(somedate) |
|
45 return datetime(somedate.year, somedate.month, somedate.day) |
|
46 |
|
47 def datetime2ticks(date): |
|
48 return mktime(date.timetuple()) * 1000 |
|
49 |
|
50 ONEDAY = timedelta(days=1) |
|
51 ONEWEEK = timedelta(days=7) |
|
52 |
|
53 def days_in_month(date_): |
|
54 return monthrange(date_.year, date_.month)[1] |
|
55 |
|
56 def days_in_year(date_): |
|
57 feb = pydatetime.date(date_.year, 2, 1) |
|
58 if days_in_month(feb) == 29: |
|
59 return 366 |
|
60 else: |
|
61 return 365 |
|
62 |
|
63 def previous_month(date_, nbmonth=1): |
|
64 while nbmonth: |
|
65 date_ = first_day(date_) - ONEDAY |
|
66 nbmonth -= 1 |
|
67 return date_ |
|
68 |
|
69 def next_month(date_, nbmonth=1): |
|
70 while nbmonth: |
|
71 date_ = last_day(date_) + ONEDAY |
|
72 nbmonth -= 1 |
|
73 return date_ |
|
74 |
|
75 def first_day(date_): |
|
76 return date(date_.year, date_.month, 1) |
|
77 |
|
78 def last_day(date_): |
|
79 return date(date_.year, date_.month, days_in_month(date_)) |
|
80 |
|
81 def date_range(begin, end, incday=None, incmonth=None): |
27 def date_range(begin, end, incday=None, incmonth=None): |
82 """yields each date between begin and end |
28 """yields each date between begin and end |
83 :param begin: the start date |
29 :param begin: the start date |
84 :param end: the end date |
30 :param end: the end date |
85 :param incr: the step to use to iterate over dates. Default is |
31 :param incr: the step to use to iterate over dates. Default is |
97 yield begin |
43 yield begin |
98 else: |
44 else: |
99 if not incday: |
45 if not incday: |
100 incr = ONEDAY |
46 incr = ONEDAY |
101 else: |
47 else: |
102 incr = timedelta(incday) |
48 incr = datetime.timedelta(incday) |
103 while begin <= end: |
49 while begin <= end: |
104 yield begin |
50 yield begin |
105 begin += incr |
51 begin += incr |
106 |
|
107 def ustrftime(date, fmt='%Y-%m-%d'): |
|
108 """like strftime, but returns a unicode string instead of an encoded |
|
109 string which' may be problematic with localized date. |
|
110 |
|
111 encoding is guessed by locale.getpreferredencoding() |
|
112 """ |
|
113 # date format may depend on the locale |
|
114 encoding = locale.getpreferredencoding(do_setlocale=False) or 'UTF-8' |
|
115 return unicode(date.strftime(str(fmt)), encoding) |
|
116 |
52 |
117 |
53 |
118 if sys.version_info[:2] < (2, 5): |
54 if sys.version_info[:2] < (2, 5): |
119 def make_uid(key): |
55 def make_uid(key): |
120 """forge a unique identifier |
56 """forge a unique identifier |
405 else: |
341 else: |
406 |
342 |
407 class CubicWebJsonEncoder(JSONEncoder): |
343 class CubicWebJsonEncoder(JSONEncoder): |
408 """define a simplejson encoder to be able to encode yams std types""" |
344 """define a simplejson encoder to be able to encode yams std types""" |
409 def default(self, obj): |
345 def default(self, obj): |
410 if isinstance(obj, pydatetime.datetime): |
346 if isinstance(obj, datetime.datetime): |
411 return obj.strftime('%Y/%m/%d %H:%M:%S') |
347 return obj.strftime('%Y/%m/%d %H:%M:%S') |
412 elif isinstance(obj, pydatetime.date): |
348 elif isinstance(obj, datetime.date): |
413 return obj.strftime('%Y/%m/%d') |
349 return obj.strftime('%Y/%m/%d') |
414 elif isinstance(obj, pydatetime.time): |
350 elif isinstance(obj, datetime.time): |
415 return obj.strftime('%H:%M:%S') |
351 return obj.strftime('%H:%M:%S') |
416 elif isinstance(obj, pydatetime.timedelta): |
352 elif isinstance(obj, datetime.timedelta): |
417 return (obj.days * 24 * 60 * 60) + obj.seconds |
353 return (obj.days * 24 * 60 * 60) + obj.seconds |
418 elif isinstance(obj, decimal.Decimal): |
354 elif isinstance(obj, decimal.Decimal): |
419 return float(obj) |
355 return float(obj) |
420 try: |
356 try: |
421 return JSONEncoder.default(self, obj) |
357 return JSONEncoder.default(self, obj) |