[Development] QtCS - QDateTime changes

Knoll Lars Lars.Knoll at digia.com
Wed Aug 7 09:50:33 CEST 2013

On 06.08.13 23:44, "John Layt" <jlayt at kde.org> wrote:

>On Monday 05 Aug 2013 08:32:00 Knoll Lars wrote:
>> On 26.07.13 22:26, "John Layt" <jlayt at kde.org> wrote:
>> >It has been discussed to re-write QDateTime to internally store as an
>> >absolute msecs since epoch which would inherently fix these issues and
>> >greatly simplify the maths and conversion code, but this would
>> >radically change the behaviour of QDateTime which currently treats the
>> >ymd/hms values as ┬│fixed┬▓ and the time spec is used to interpret that
>> >value. This would mostly affect the default Qt::LocalTime spec where
>> >the system time zone can change underneath QDateTime causing the
>> >absolute UTC value to change. There is also the behaviour that you can
>> >store an invalid date but valid time in QDateTime, and later fix the
>> >date to be valid.  Considerable special case code could be required to
>> >keep consistent with the current behaviour.
>> If we'd write this class now, storing the date time as ms since epoch is
>> what I'd prefer. It would be nice if we can change to that. Maybe it
>> work if you in addition have two boolean flags indicating invalid dates
>> and times.
>OK, I've had a re-think, and I think I now have a plan to do this cleanly
>no regressions that I'll try this weekend.  I'm not sure how much I can
>it up into small parts though, it may be one big commit.
>I was thinking that LocalTime could always be stored as if it was UTC,
>without actally converting it first, allowing us to always know the exact
>date/time value that it represents without worrying what the system tz
>says or 
>if it changes.  We'd still validate at init, and convert to UTC proper
>doing date maths and Spec conversions  Time maths won't need conversion.
>has the advantage of not calling mktime every time just to retrieve the
>date/time values, we just use the short UTC formula like the other Specs.
> If 
>the system tz does change we don't mind, we still have the original
>values and 
>just revalidate them against the new tz.  All other TimeSpec's will be
>in "real" UTC msecs.
>This means QDateTimePrivate will store the following data:
>qint64 m_msecsSinceEpoch;           // Replaces QDate/QTime
>Qt::TimeSpec m_spec;                // replaces QDateTimePrivate::TimeSpec
>QDateTimePrivate::Status m_status;  // New, see below
>int m_offsetFromUtc;
>So effectively no change in the memory used, the int saved from QTime
>gets used 
>for the Status enum.
>The new private Status enum will have values like:
>Invalid dates/times will be encoded as UTC dates/times and the Status
>used to 
>interpret them, i.e. ignore the bit that's invalid.
>We will have to keep the old QDateTimePrivate::TimeSpec defined for
>compatible serialise/de-serialise, but we'll calculate it on the fly.
>I could split the change to TimeSpec and Status out as a spearate commit
>the change to msecs, but I'm not sure how much sense that would make as
>bits would be broken in the interim.

Sounds good to me. This would hopefully also fix some broken corner cases
with QDateTime that Simon and myself have been finding lately when
converting JS date objects to QDateTime and back (see tst_qjsengine in
>> I don't think the corner cases where the time zone changes while the Qt
>> app is running is a problem. I would actually expect that having QDT
>> stored as ms since epoch would fix bugs here in 90% of the cases.
>I was more concerned about the serialise/de-serialise scenario where the
>values written out must be read back the same regardless of the tz, but
>my solution above would cover this.

For the old format that is true. I think we should however bump our data
stream version going forward and write out the date time with timezone in
the future.
>> >* Would reduce the historic supported date range, but QDateTime is
>> >only promised to be useful from 1970 onwards anyway
>> Why? The int64 should be plenty to store all historic dates.
>QDate currently is a qint64 for storing Julian Days on it's own, so a
>range of 
>about +/- 2 billion years.  Using a qint64 for msecs will lose some of
>that extreme date range, allowing "only" about +/- 292 million years :-)

No problems with that restriction... :)


>The 1970 documented useful range is because LocalTime uses POSIX
>that only take a time_t, i.e. a uint allowing 1970 to 2037, and fudges
>outside that range using adjustDate().  The docs say we don't apply
>Time outside the range, but that's not actually what the code does, it
>the year number to be 1970 or 2037 so effectively applies the rule from
>year, but not very accurately.  I'll fix that.  For QTimeZone we won't
>this issue, the code properly calculates before 1970 and after 2037 using
>appropriate rule from the system database.
>Development mailing list
>Development at qt-project.org

More information about the Development mailing list