1.1 --- a/imiptools/dates.py Sat Aug 15 22:56:51 2015 +0200
1.2 +++ b/imiptools/dates.py Sat Aug 15 22:57:17 2015 +0200
1.3 @@ -19,6 +19,7 @@
1.4 this program. If not, see <http://www.gnu.org/licenses/>.
1.5 """
1.6
1.7 +from bisect import bisect_left
1.8 from datetime import date, datetime, timedelta
1.9 from os.path import exists
1.10 from pytz import timezone, UnknownTimeZoneError
1.11 @@ -470,4 +471,72 @@
1.12
1.13 return to_utc_datetime(get_datetime(recurrenceid), tzid)
1.14
1.15 +# Time corrections.
1.16 +
1.17 +def correct_datetime(dt, resolution):
1.18 +
1.19 + "Correct 'dt' using the given 'resolution' details."
1.20 +
1.21 + carry, hour, minute, second = correct_value((dt.hour, dt.minute, dt.second), resolution)
1.22 + return datetime(dt.year, dt.month, dt.day, hour, minute, second, dt.microsecond, dt.tzinfo) + \
1.23 + (carry and timedelta(1) or timedelta(0))
1.24 +
1.25 +def correct_value(value, resolution):
1.26 +
1.27 + """
1.28 + Correct the given (hour, minute, second) tuple 'value' according to the
1.29 + 'resolution' details.
1.30 + """
1.31 +
1.32 + limits = 23, 59, 59
1.33 +
1.34 + corrected = []
1.35 + reset = False
1.36 +
1.37 + # Find invalid values and reset all following values.
1.38 +
1.39 + for v, values, limit in zip(value, resolution, limits):
1.40 + if reset:
1.41 + if values:
1.42 + v = values[0]
1.43 + else:
1.44 + v = 0
1.45 +
1.46 + elif values and v not in values:
1.47 + reset = True
1.48 +
1.49 + corrected.append(v)
1.50 +
1.51 + value = corrected
1.52 + corrected = []
1.53 + carry = 0
1.54 +
1.55 + # Find invalid values and update them to the next valid value, updating more
1.56 + # significant values if the next valid value is the first in the appropriate
1.57 + # series.
1.58 +
1.59 + for v, values, limit in zip(value, resolution, limits)[::-1]:
1.60 + if carry:
1.61 + v += 1
1.62 + if v > limit:
1.63 + if values:
1.64 + v = values[0]
1.65 + else:
1.66 + v = 0
1.67 + corrected.append(v)
1.68 + continue
1.69 + else:
1.70 + carry = 0
1.71 +
1.72 + i = bisect_left(values, v)
1.73 + if i < len(values):
1.74 + v = values[i]
1.75 + else:
1.76 + v = values[0]
1.77 + carry = 1
1.78 +
1.79 + corrected.append(v)
1.80 +
1.81 + return [carry] + corrected[::-1]
1.82 +
1.83 # vim: tabstop=4 expandtab shiftwidth=4