2 # This file is part of my.gpodder.org.
4 # my.gpodder.org is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or (at your
7 # option) any later version.
9 # my.gpodder.org is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
12 # License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
18 from datetime
import datetime
, timedelta
21 def daterange(from_date
, to_date
=datetime
.now(), leap
=timedelta(days
=1)):
23 >>> from_d = datetime(2010, 01, 01)
24 >>> to_d = datetime(2010, 01, 05)
25 >>> list(daterange(from_d, to_d))
26 [datetime.datetime(2010, 1, 1, 0, 0), datetime.datetime(2010, 1, 2, 0, 0), datetime.datetime(2010, 1, 3, 0, 0), datetime.datetime(2010, 1, 4, 0, 0), datetime.datetime(2010, 1, 5, 0, 0)]
28 while from_date
<= to_date
:
30 from_date
= from_date
+ leap
33 def format_time(value
):
34 """Format an offset (in seconds) to a string
36 The offset should be an integer or float value.
44 >>> format_time(10921)
47 dt
= datetime
.utcfromtimestamp(value
)
50 return dt
.strftime('%M:%S')
52 return dt
.strftime('%H:%M:%S')
54 def parse_time(value
):
59 >>> parse_time('05:10') #5*60+10
62 >>> parse_time('1:05:10') #60*60+5*60+10
66 raise ValueError('None value in parse_time')
68 if isinstance(value
, int):
69 # Don't need to parse already-converted time value
73 raise ValueError('Empty valueing in parse_time')
75 for format
in ('%H:%M:%S', '%M:%S'):
77 t
= time
.strptime(value
, format
)
78 return t
.tm_hour
* 60*60 + t
.tm_min
* 60 + t
.tm_sec
87 >>> parse_bool('True')
90 >>> parse_bool('true')
96 if isinstance(val
, bool):
98 if val
.lower() == 'true':
103 def iterate_together(l1
, l2
, compare
=lambda x
, y
: cmp(x
, y
)):
105 takes two ordered, possible sparse, lists l1 and l2 with similar items
106 (some items have a corresponding item in the other list, some don't).
108 It then yield tuples of corresponding items, where one element is None is
109 there is no corresponding entry in one of the lists.
111 Tuples where both elements are None are skipped.
113 compare is a method for comparing items from both lists; it defaults
116 >>> list(iterate_together(range(1, 3), range(1, 4, 2)))
117 [(1, 1), (2, None), (None, 3)]
119 >>> list(iterate_together([], []))
122 >>> list(iterate_together(range(1, 3), range(3, 5)))
123 [(1, None), (2, None), (None, 3), (None, 4)]
125 >>> list(iterate_together(range(1, 3), []))
126 [(1, None), (2, None)]
128 >>> list(iterate_together([1, None, 3], [None, None, 3]))
141 except StopIteration:
144 i1
, more1
= _take(l1
)
145 i2
, more2
= _take(l2
)
147 while more1
or more2
:
148 if not more2
or (i1
!= None and compare(i1
, i2
) < 0):
150 i1
, more1
= _take(l1
)
152 elif not more1
or (i2
!= None and compare(i1
, i2
) > 0):
154 i2
, more2
= _take(l2
)
156 elif compare(i1
, i2
) == 0:
158 i1
, more1
= _take(l1
)
159 i2
, more2
= _take(l2
)
162 def progress(val
, max_val
, status_str
='', max_width
=50):
164 print '[ %s ] %s / %s | %s' % (
165 '#'*int(float(val
)/max_val
*max_width
) +
166 ' ' * (max_width
-(int(float(val
)/max_val
*max_width
))),