mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
More fixes for conversion to/from QDateTime and datetime objects
Fixes #2043943 [problems with dates not completely fixed](https://bugs.launchpad.net/calibre/+bug/2043943)
This commit is contained in:
parent
b36475fdae
commit
db33abeea9
@ -6,12 +6,12 @@ __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import re
|
||||
from datetime import datetime, time as dtime, timedelta, MINYEAR, MAXYEAR
|
||||
from datetime import MAXYEAR, MINYEAR, datetime, time as dtime, timedelta
|
||||
from functools import partial
|
||||
|
||||
from calibre import strftime
|
||||
from calibre.constants import iswindows, ismacos, preferred_encoding
|
||||
from calibre.utils.iso8601 import utc_tz, local_tz, UNDEFINED_DATE
|
||||
from calibre.constants import ismacos, iswindows, preferred_encoding
|
||||
from calibre.utils.iso8601 import UNDEFINED_DATE, local_tz, utc_tz
|
||||
from calibre.utils.localization import lcdata
|
||||
from polyglot.builtins import native_string_type
|
||||
|
||||
@ -152,24 +152,33 @@ def dt_factory(time_t, assume_utc=False, as_utc=True):
|
||||
|
||||
|
||||
def safeyear(x):
|
||||
return min(max(x, MINYEAR), MAXYEAR)
|
||||
return min(max(MINYEAR, x), MAXYEAR)
|
||||
|
||||
|
||||
def qt_to_dt(qdate_or_qdatetime, as_utc=True):
|
||||
from qt.core import Qt, QDateTime
|
||||
o = qdate_or_qdatetime
|
||||
if o is None:
|
||||
return UNDEFINED_DATE
|
||||
if hasattr(o, 'toUTC'):
|
||||
# QDateTime
|
||||
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
|
||||
if hasattr(o, 'toUTC'): # QDateTime
|
||||
def c(o: QDateTime, tz=utc_tz):
|
||||
d, t = o.date(), o.time()
|
||||
try:
|
||||
return datetime(safeyear(d.year()), d.month(), d.day(), t.hour(), t.minute(), t.second(), t.msec()*1000, tz)
|
||||
except ValueError:
|
||||
return datetime(safeyear(d.year()), d.month(), 1, t.hour(), t.minute(), t.second(), t.msec()*1000, tz)
|
||||
|
||||
# DST causes differences in how python and Qt convert automatically from local to UTC, so convert explicitly ourselves
|
||||
# QDateTime::toUTC() and datetime.astimezone(utc_tz) give
|
||||
# different results for datetimes in the local_tz when DST is involved. Sigh.
|
||||
spec = o.timeSpec()
|
||||
if spec == Qt.TimeSpec.LocalTime:
|
||||
ans = c(o, local_tz)
|
||||
elif spec == Qt.TimeSpec.UTC:
|
||||
ans = c(o, utc_tz)
|
||||
else:
|
||||
ans = c(o.toUTC(), utc_tz)
|
||||
return ans.astimezone(utc_tz if as_utc else local_tz)
|
||||
|
||||
try:
|
||||
dt = datetime(safeyear(o.year()), o.month(), o.day()).replace(tzinfo=_local_tz)
|
||||
@ -178,14 +187,16 @@ def qt_to_dt(qdate_or_qdatetime, as_utc=True):
|
||||
return dt.astimezone(_utc_tz if as_utc else _local_tz)
|
||||
|
||||
|
||||
def qt_from_dt(d, as_utc=False, assume_utc=False):
|
||||
from qt.core import QDateTime, QTimeZone
|
||||
def qt_from_dt(d: datetime, as_utc=False, assume_utc=False):
|
||||
from qt.core import QDate, QDateTime, QTime, QTimeZone
|
||||
if d.tzinfo is None:
|
||||
d = d.replace(tzinfo=utc_tz if assume_utc else local_tz)
|
||||
d = d.astimezone(utc_tz)
|
||||
ans = QDateTime.fromMSecsSinceEpoch(int(d.timestamp() * 1000), QTimeZone.utc())
|
||||
if not as_utc:
|
||||
ans = ans.toLocalTime()
|
||||
if as_utc:
|
||||
d = d.astimezone(utc_tz)
|
||||
ans = QDateTime.fromMSecsSinceEpoch(int(d.timestamp() * 1000), QTimeZone.utc())
|
||||
else:
|
||||
d = d.astimezone(local_tz)
|
||||
ans = QDateTime(QDate(d.year, d.month, d.day), QTime(d.hour, d.minute, d.second, int(d.microsecond / 1000)))
|
||||
return ans
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user