From d62006bc11e16235170e37ff5bfa139e22ec1f92 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 1 Aug 2013 08:23:06 +0530 Subject: [PATCH] QDateTime->datetime faster and more robust Fix editing of book metadata failing when its timestamp is out of range for the system. Fixes #1191599 [Cannot edit simple ebook metadatas](https://bugs.launchpad.net/calibre/+bug/1191599) --- src/calibre/utils/date.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/calibre/utils/date.py b/src/calibre/utils/date.py index dc8adc6b97..a0c1c77a7a 100644 --- a/src/calibre/utils/date.py +++ b/src/calibre/utils/date.py @@ -7,7 +7,7 @@ __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' import re, time -from datetime import datetime, time as dtime, timedelta +from datetime import datetime, time as dtime, timedelta, MINYEAR, MAXYEAR from functools import partial from dateutil.tz import tzlocal, tzutc, EPOCHORDINAL @@ -141,14 +141,26 @@ def dt_factory(time_t, assume_utc=False, as_utc=True): dt = dt.replace(tzinfo=_utc_tz if assume_utc else _local_tz) return dt.astimezone(_utc_tz if as_utc else _local_tz) +safeyear = lambda x: min(max(x, MINYEAR), MAXYEAR) + def qt_to_dt(qdate_or_qdatetime, as_utc=True): - from PyQt4.Qt import Qt o = qdate_or_qdatetime if hasattr(o, 'toUTC'): # QDateTime - o = unicode(o.toUTC().toString(Qt.ISODate)) - return parse_date(o, assume_utc=True, as_utc=as_utc) - dt = datetime(o.year(), o.month(), o.day()).replace(tzinfo=_local_tz) + o = o.toUTC() + d, t = o.date(), o.time() + try: + ans = datetime(safeyear(d.year()), d.month(), d.day(), t.hour(), t.minute(), t.second(), t.msec()*1000, utc_tz) + except ValueError: + ans = datetime(safeyear(d.year()), d.month(), 1, t.hour(), t.minute(), t.second(), t.msec()*1000, utc_tz) + if not as_utc: + ans = ans.astimezone(local_tz) + return ans + + try: + dt = datetime(safeyear(o.year()), o.month(), o.day()).replace(tzinfo=_local_tz) + except ValueError: + dt = datetime(safeyear(o.year()), o.month(), 1).replace(tzinfo=_local_tz) return dt.astimezone(_utc_tz if as_utc else _local_tz) def fromtimestamp(ctime, as_utc=True):