Discussion:
[Interest] Relashionship between time_t and QDateTime
Calogero Mauceri
2013-08-26 15:42:58 UTC
Permalink
Hi all,

I'm facing the following problem when initializing a QDateTime with
time_t value.
I get the last modified timestamp of a file as time_t value

...
time_t mtime;
struct stat statbuf;
fstat(fd, &statbuf);
mtime = statbuf.st_mtime;
...

Then I use that mtime value to initialize a QDateTime as follows:

QDateTime myDateTime = QDateTime::fromTime_t(f_mtime);

The date time printed doing a myDateTime.toString() is

Wed Dec 5 12:36:18 2007


Retrieving the last modified information using QFileInfo, the result is
different

QFileInfo fi(filepath);
QDateTime myDateTime = fi.lastModified();

I get this result

Wed Dec 5 11:36:18 2007

That is there is one hour difference. I guess the difference is due to
the daylight saving management,
but I can not understand how that management is performed.

Note: if I look at the file properties on Windows dialog, the last
modified time is shown as

Wed Dec 5 12:36:18 2007



Thanks in advance for your help.
Calogero
--
Calogero Mauceri
Software Engineer

Applied Coherent Technology Corporation (ACT)
www.actgate.com
Thiago Macieira
2013-08-26 17:30:00 UTC
Permalink
Post by Calogero Mauceri
QDateTime myDateTime = QDateTime::fromTime_t(f_mtime);
The date time printed doing a myDateTime.toString() is
Wed Dec 5 12:36:18 2007
Retrieving the last modified information using QFileInfo, the result is
different
QFileInfo fi(filepath);
QDateTime myDateTime = fi.lastModified();
I get this result
Wed Dec 5 11:36:18 2007
That is there is one hour difference. I guess the difference is due to
the daylight saving management,
but I can not understand how that management is performed.
Note: if I look at the file properties on Windows dialog, the last
modified time is shown as
Wed Dec 5 12:36:18 2007
Ah, Windows...

The problem might be simply a matter of timezones. The timestamps on files on
Windows are not stored with time_t, but with some Windows-specific data. We get
a FILETIME back from Win32.

Anyway, up until Qt 5.2, you cannot trust the output of a QDateTime with
qDebug since it does not include the timezone. You have to ensure that the
dates you're comparing by text are in the same timezone:

qDebug() << dt.toUTC();
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Calogero Mauceri
2013-08-27 08:19:06 UTC
Permalink
Post by Thiago Macieira
Post by Calogero Mauceri
QDateTime myDateTime = QDateTime::fromTime_t(f_mtime);
The date time printed doing a myDateTime.toString() is
Wed Dec 5 12:36:18 2007
Retrieving the last modified information using QFileInfo, the result is
different
QFileInfo fi(filepath);
QDateTime myDateTime = fi.lastModified();
I get this result
Wed Dec 5 11:36:18 2007
That is there is one hour difference. I guess the difference is due to
the daylight saving management,
but I can not understand how that management is performed.
Note: if I look at the file properties on Windows dialog, the last
modified time is shown as
Wed Dec 5 12:36:18 2007
Ah, Windows...
The problem might be simply a matter of timezones. The timestamps on files on
Windows are not stored with time_t, but with some Windows-specific data. We get
a FILETIME back from Win32.
Anyway, up until Qt 5.2, you cannot trust the output of a QDateTime with
qDebug since it does not include the timezone. You have to ensure that the
qDebug() << dt.toUTC();
Thanks for your reply.

Unfortunately the problem is still there even if I force a toUTC()
conversion for both QDateTime, either the one initialized from time_t or
the one returned by QFileInfo :/.
Similarly

QDateTime dtFromTime_t = QDateTime::fromTime_t(mtime).toUTC();
QDateTime dtFromFileInfo = fi.lastModified().toUTC();
int sec = ABS(dtFromTime.secsTo(dtFromFileInfo)); // sec returned is 3600


Calogero
--
Calogero Mauceri
Software Engineer

Applied Coherent Technology Corporation (ACT)
www.actgate.com
Frank Hemer
2013-08-27 09:55:42 UTC
Permalink
Post by Calogero Mauceri
Post by Thiago Macieira
Post by Calogero Mauceri
QDateTime myDateTime = QDateTime::fromTime_t(f_mtime);
The date time printed doing a myDateTime.toString() is
Wed Dec 5 12:36:18 2007
Retrieving the last modified information using QFileInfo, the result is
different
QFileInfo fi(filepath);
QDateTime myDateTime = fi.lastModified();
I get this result
Wed Dec 5 11:36:18 2007
That is there is one hour difference. I guess the difference is due to
the daylight saving management,
but I can not understand how that management is performed.
Note: if I look at the file properties on Windows dialog, the last
modified time is shown as
Wed Dec 5 12:36:18 2007
Ah, Windows...
The problem might be simply a matter of timezones. The timestamps on files
on Windows are not stored with time_t, but with some Windows-specific
data. We get a FILETIME back from Win32.
Anyway, up until Qt 5.2, you cannot trust the output of a QDateTime with
qDebug since it does not include the timezone. You have to ensure that the
qDebug() << dt.toUTC();
Thanks for your reply.
Unfortunately the problem is still there even if I force a toUTC()
conversion for both QDateTime, either the one initialized from time_t or
the one returned by QFileInfo :/.
Similarly
QDateTime dtFromTime_t = QDateTime::fromTime_t(mtime).toUTC();
QDateTime dtFromFileInfo = fi.lastModified().toUTC();
int sec = ABS(dtFromTime.secsTo(dtFromFileInfo)); // sec returned is 3600
Daylight savings handling in windows is somehow 'weird'.
The timestamps of files change when switching the system time from summer time
to winter time and vice versa.

Frank
Constantin Makshin
2013-08-27 17:40:29 UTC
Permalink
When converting time from UTC to local time, Windows uses the *current*
state of daylight saving, not one that was active at the time the
original timestamp is "pointing" to.
Post by Frank Hemer
Post by Calogero Mauceri
Post by Thiago Macieira
Post by Calogero Mauceri
QDateTime myDateTime = QDateTime::fromTime_t(f_mtime);
The date time printed doing a myDateTime.toString() is
Wed Dec 5 12:36:18 2007
Retrieving the last modified information using QFileInfo, the result is
different
QFileInfo fi(filepath);
QDateTime myDateTime = fi.lastModified();
I get this result
Wed Dec 5 11:36:18 2007
That is there is one hour difference. I guess the difference is due to
the daylight saving management,
but I can not understand how that management is performed.
Note: if I look at the file properties on Windows dialog, the last
modified time is shown as
Wed Dec 5 12:36:18 2007
Ah, Windows...
The problem might be simply a matter of timezones. The timestamps on files
on Windows are not stored with time_t, but with some Windows-specific
data. We get a FILETIME back from Win32.
Anyway, up until Qt 5.2, you cannot trust the output of a QDateTime with
qDebug since it does not include the timezone. You have to ensure that the
qDebug() << dt.toUTC();
Thanks for your reply.
Unfortunately the problem is still there even if I force a toUTC()
conversion for both QDateTime, either the one initialized from time_t or
the one returned by QFileInfo :/.
Similarly
QDateTime dtFromTime_t = QDateTime::fromTime_t(mtime).toUTC();
QDateTime dtFromFileInfo = fi.lastModified().toUTC();
int sec = ABS(dtFromTime.secsTo(dtFromFileInfo)); // sec returned is 3600
Daylight savings handling in windows is somehow 'weird'.
The timestamps of files change when switching the system time from summer time
to winter time and vice versa.
Frank
Thiago Macieira
2013-08-27 17:57:32 UTC
Permalink
Post by Constantin Makshin
When converting time from UTC to local time, Windows uses the *current*
state of daylight saving, not one that was active at the time the
original timestamp is "pointing" to.
Hmm... we have two versions of the code: FileTimeToSystemTime and gmtime. Are
you saying that gmtime is broken and does not apply the correct historical
daylight saving settings?

#if defined(Q_OS_WINCE)
tm res;
FILETIME localTime = time_tToFt(secsSince1Jan1970UTC);
SYSTEMTIME sysTime;
FileTimeToSystemTime(&localTime, &sysTime);
FILETIME resultTime;
LocalFileTimeToFileTime(&localTime , &resultTime);
FileTimeToSystemTime(&resultTime , &sysTime);
res.tm_sec = sysTime.wSecond;
res.tm_min = sysTime.wMinute;
res.tm_hour = sysTime.wHour;
res.tm_mday = sysTime.wDay;
res.tm_mon = sysTime.wMonth - 1;
res.tm_year = sysTime.wYear - 1900;
res.tm_isdst = (int)isdst;
brokenDown = &res;
#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
// use the reentrant version of gmtime() where available
tm res;
brokenDown = gmtime_r(&secsSince1Jan1970UTC, &res);
#elif defined(_MSC_VER) && _MSC_VER >= 1400
tm res;
if (!_gmtime64_s(&res, &secsSince1Jan1970UTC))
brokenDown = &res;
#else
brokenDown = gmtime(&secsSince1Jan1970UTC);
#endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Constantin Makshin
2013-08-27 18:17:07 UTC
Permalink
In MSVC's runtime library — yes, gmtime() is broken.
Return Value
...
tm_isdst
Always 0 for gmtime.
That's for gmtime(), but the same applies to gmtime_s()
(http://msdn.microsoft.com/en-us/library/vstudio/3stkd9be.aspx) as all
these *_s() functions are simply a result of Microsoft's NIH syndrome
and share the [general] behavior with their standard counterparts.
Post by Constantin Makshin
When converting time from UTC to local time, Windows uses the *current*
state of daylight saving, not one that was active at the time the
original timestamp is "pointing" to.
Hmm... we have two versions of the code: FileTimeToSystemTime and gmtime. Are
you saying that gmtime is broken and does not apply the correct historical
daylight saving settings?
#if defined(Q_OS_WINCE)
tm res;
FILETIME localTime = time_tToFt(secsSince1Jan1970UTC);
SYSTEMTIME sysTime;
FileTimeToSystemTime(&localTime, &sysTime);
FILETIME resultTime;
LocalFileTimeToFileTime(&localTime , &resultTime);
FileTimeToSystemTime(&resultTime , &sysTime);
res.tm_sec = sysTime.wSecond;
res.tm_min = sysTime.wMinute;
res.tm_hour = sysTime.wHour;
res.tm_mday = sysTime.wDay;
res.tm_mon = sysTime.wMonth - 1;
res.tm_year = sysTime.wYear - 1900;
res.tm_isdst = (int)isdst;
brokenDown = &res;
#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
// use the reentrant version of gmtime() where available
tm res;
brokenDown = gmtime_r(&secsSince1Jan1970UTC, &res);
#elif defined(_MSC_VER) && _MSC_VER >= 1400
tm res;
if (!_gmtime64_s(&res, &secsSince1Jan1970UTC))
brokenDown = &res;
#else
brokenDown = gmtime(&secsSince1Jan1970UTC);
#endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
Thiago Macieira
2013-08-27 19:38:46 UTC
Permalink
Post by Constantin Makshin
In MSVC's runtime library — yes, gmtime() is broken.
Daniel Bowen
2013-08-27 18:27:03 UTC
Permalink
Thiago Macieira
2013-08-27 16:01:08 UTC
Permalink
Post by Calogero Mauceri
Unfortunately the problem is still there even if I force a toUTC()
conversion for both QDateTime, either the one initialized from time_t or
the one returned by QFileInfo :/.
Similarly
QDateTime dtFromTime_t = QDateTime::fromTime_t(mtime).toUTC();
QDateTime dtFromFileInfo = fi.lastModified().toUTC();
int sec = ABS(dtFromTime.secsTo(dtFromFileInfo)); // sec
returned is 3600
Does this happen to all files?

Does this happen in Qt 5?

What is the difference between the UTC time and the Windows file dialog?

And what timezone is your computer configured to?
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Constantin Makshin
2013-08-26 17:32:29 UTC
Permalink
As far as I understand the description of QDateTime::fromTime_t(), it
automatically converts the passed value from UTC to local time. On the
other hand, QFileInfo::lastModified() may immediately return the value
retrieved from the system without any transformations.
Post by Calogero Mauceri
Hi all,
I'm facing the following problem when initializing a QDateTime with time_t
value.
I get the last modified timestamp of a file as time_t value
...
time_t mtime;
struct stat statbuf;
fstat(fd, &statbuf);
mtime = statbuf.st_mtime;
...
QDateTime myDateTime = QDateTime::fromTime_t(f_mtime);
The date time printed doing a myDateTime.toString() is
Wed Dec 5 12:36:18 2007
Retrieving the last modified information using QFileInfo, the result is
different
QFileInfo fi(filepath);
QDateTime myDateTime = fi.lastModified();
I get this result
Wed Dec 5 11:36:18 2007
That is there is one hour difference. I guess the difference is due to the
daylight saving management,
but I can not understand how that management is performed.
Note: if I look at the file properties on Windows dialog, the last
modified time is shown as
Wed Dec 5 12:36:18 2007
Thanks in advance for your help.
Calogero
--
Calogero Mauceri
Software Engineer
Applied Coherent Technology Corporation (ACT)www.actgate.com
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
interest-bounces+qtmailinglist1= = [mailto:interest-bounces+qtmailinglist1=] = On Behalf Of Constantin Makshin
1970-01-01 00:00:00 UTC
Permalink
The MSDN library states:

"
To account for daylight saving time when converting a file time to a =
local time, use the following sequence of functions instead of using =
FileTimeToLocalFileTime:
FileTimeToSystemTime
SystemTimeToTzSpecificLocalTime
SystemTimeToFileTime
"

For example:
(incoming fileTimeUtc)
FILETIME fileTimeLocal;
SYSTEMTIME systemTimeUtc =3D {0}, systemTimeLocal =3D {0};
::FileTimeToSystemTime(&fileTimeUtc, &systemTimeUtc);
::SystemTimeToTzSpecificLocalTime(NULL, &systemTimeUtc, =
&systemTimeLocal);
::SystemTimeToFileTime(&systemTimeLocal, &fileTimeLocal);
// SYSTEMTIME will lose accuracy less than a millisecond. We'll tack =
that back on.
fileTimeLocal +=3D (fileTimeUtc % Millisecond);

If this is on Windows and before Vista, then past timezones might not be =
correct if the rules are different than the current set of daylight =
savings transition rules (only Vista and later has the dynamic timezone =
stuff that tracks timezone transition changes in years past). In the =
QDateTime docs I see "On Windows and Windows CE, where the system =
doesn't support historical DST data, historical accuracy is not =
maintained with respect to DST." I don't believe that's quite true - =
Windows support historical DST data if you use the calls above, and its =
on Vista or later. You can also use calls like =
GetDynamicTimeZoneInformation and GetTimeZoneInformationForYear on Vista =
and later for more explicit historical timezone info.


The thing to remember is that time_t and FILETIME and QDateTime (at =
least <=3D5.1) all represent a moment in time without regard for =
timezone. Like 2013-08-27T11:50:00. It's up to you to track which =
timezone the time_t or FILETIME you have belongs to. (i.e., =
2013-08-27T11:50:00-06:00)

I think the best way to track things if timezones are in the mix is to =
track the date/time as one thing, and separately track the timezone =
offset for that date/time. Then you can convert reliably between =
different local times or UTC. We ended up with our own class for =
tracking time that does that. (Kind of like the .NET DateTimeOffset =
compared to the DateTime class).


-Daniel

-----Original Message-----
From: interest-bounces+qtmailinglist1=***@qt-project.org =
[mailto:interest-bounces+qtmailinglist1=***@qt-project.org] =
On Behalf Of Constantin Makshin
Sent: Tuesday, August 27, 2013 11:40 AM
To: Qt Interest
Subject: Re: [Interest] Relashionship between time_t and QDateTime

When converting time from UTC to local time, Windows uses the *current* =
state of daylight saving, not one that was active at the time the =
original timestamp is "pointing" to.
Post by Frank Hemer
Post by Calogero Mauceri
On segunda-feira, 26 de agosto de 2013 17:42:58, Calogero Mauceri =
QDateTime myDateTime =3D QDateTime::fromTime_t(f_mtime);
The date time printed doing a myDateTime.toString() is
Wed Dec 5 12:36:18 2007
Retrieving the last modified information using QFileInfo, the=20
result is different
QFileInfo fi(filepath);
QDateTime myDateTime =3D fi.lastModified();
I get this result
Wed Dec 5 11:36:18 2007
That is there is one hour difference. I guess the difference is due =
to the daylight saving management, but I can not understand how=20
that management is performed.
Note: if I look at the file properties on Windows dialog, the last=20
modified time is shown as
Wed Dec 5 12:36:18 2007
Ah, Windows...
The problem might be simply a matter of timezones. The timestamps on =
files on Windows are not stored with time_t, but with some=20
Windows-specific data. We get a FILETIME back from Win32.
Anyway, up until Qt 5.2, you cannot trust the output of a QDateTime=20
with qDebug since it does not include the timezone. You have to=20
ensure that the
qDebug() << dt.toUTC();
Thanks for your reply.
Unfortunately the problem is still there even if I force a toUTC()=20
conversion for both QDateTime, either the one initialized from time_t =
or the one returned by QFileInfo :/.
Similarly
QDateTime dtFromTime_t =3D QDateTime::fromTime_t(mtime).toUTC();
QDateTime dtFromFileInfo =3D fi.lastModified().toUTC();
int sec =3D ABS(dtFromTime.secsTo(dtFromFileInfo)); // sec returned =
is 3600
Post by Frank Hemer
=20
Daylight savings handling in windows is somehow 'weird'.
The timestamps of files change when switching the system time from=20
summer time to winter time and vice versa.
=20
Frank
Constantin Makshin
2013-08-27 18:59:44 UTC
Permalink
(re-sending to the list, sorry for the mistake)

One key is in the "Remarks" section of
SystemTimeToTzSpecificLocalTime()'s documentation
- *The time zone uses a different UTC offset for the old and new years*.
- The UTC time to be converted and the calculated local time are in different years.
Another key is in the description of the DYNAMIC_TIME_ZONE_INFORMATION
structure
Dynamic daylight saving time provides support for time zones whose boundaries for daylight saving time change from year to year. ... After the time zone has been updated, *the current time zone setting is applied to all time operations, even when the time in question occurred before the time zone changed*.
Windows can store information about daylight saving transitions for past
years, but always uses one for the current year. And since daylight
saving transition dates and time tend to slightly drift from year to
year, there's absolutely no guarantees of getting correct time
conversion results; in general case 1-hour error is nearly inevitable.
If you're on Windows, either calculate and apply DST yourself or forget
about correct "UTC <-> local time" conversions.

On 08/27/2013 10:27 PM, Daniel Bowen wrote:
Thiago Macieira
2013-08-27 19:42:09 UTC
Permalink
Post by Constantin Makshin
Windows can store information about daylight saving transitions for past
years, but always uses one for the current year. And since daylight
saving transition dates and time tend to slightly drift from year to
year, there's absolutely no guarantees of getting correct time
conversion results; in general case 1-hour error is nearly inevitable.
If you're on Windows, either calculate and apply DST yourself or forget
about correct "UTC <-> local time" conversions.
This is not about the corner case of a file that was created in the hour of the
transition, or even in the week that shifted between non-DST in one year to
DST in another (or vice-versa).
Daniel Bowen
2013-08-27 20:32:44 UTC
Permalink
And since daylight saving transition dates and time tend to slightly drift
from
year to year, there's absolutely no guarantees of getting correct time
conversion results; in general case 1-hour error is nearly inevitable.
The timezone structure on Windows tracks the ST->DT and DT->ST rules for the
transition, not an absolute date - like 02:00 on the first Sunday in April
(http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).a
spx). So, if the rules haven't changed, but the absolute dates have from
one year to the next, I think you'll still get the right answer if you use
SystemTimeToTzSpecificLocalTime. But, when the rules change, like they did
in the US in 2007 (http://aa.usno.navy.mil/faq/docs/daylight_time.php),
that's when it would be wrong to calculate the local time using the current
year's rules for some range of dates, and you'd need
SystemTimeToTzSpecificLocalTimeEx.

So, to test, you could use a UTC FILETIME for a date/time on March 31, 2006,
have your system set to one of the timezones in the US that follows daylight
savings, then try to convert that to local time. If it's following the
current rules, the conversion will be an hour too early. If it's
historically accurate, it will be correct.

-Daniel
Constantin Makshin
2013-08-27 21:01:55 UTC
Permalink
The original Calogero's message mentioned a file from December 2007, a
date outside of DST (unless there's a country that uses DST during
winter). Now it's August, so the DST is active and during "UTC -> local
time" conversion Windows adds that 1 hour Calogero is seeing. DST gets
incorrectly applied because it's active at the moment of conversion,
although it wasn't used at the moment the original timestamp represents.

I bet that the problem will go away when DST ends [again]. :)
Post by Thiago Macieira
Post by Constantin Makshin
Windows can store information about daylight saving transitions for past
years, but always uses one for the current year. And since daylight
saving transition dates and time tend to slightly drift from year to
year, there's absolutely no guarantees of getting correct time
conversion results; in general case 1-hour error is nearly inevitable.
If you're on Windows, either calculate and apply DST yourself or forget
about correct "UTC <-> local time" conversions.
This is not about the corner case of a file that was created in the hour of the
transition, or even in the week that shifted between non-DST in one year to
DST in another (or vice-versa).
Thiago Macieira
2013-08-27 22:53:23 UTC
Permalink
Post by Constantin Makshin
The original Calogero's message mentioned a file from December 2007, a
date outside of DST (unless there's a country that uses DST during
winter). Now it's August, so the DST is active and during "UTC -> local
time" conversion Windows adds that 1 hour Calogero is seeing. DST gets
incorrectly applied because it's active at the moment of conversion,
although it wasn't used at the moment the original timestamp represents.
That would support the theory that gmtime is broken on Windows, that it
doesn't apply the DST rules at all.

I don't have time to do further testing on this, so if someone can, it would
be appreciated. Also, please report the issue in the Qt issue tracker
(http://bugreports.qt-project.org) so it doesn't get forgotten.

PS: I don't know of any country that does DST in Winter. I do know of
countries that have Summer in December, though, and I know of regions that do
reverse DST during Winter.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Constantin Makshin
2013-08-28 04:51:46 UTC
Permalink
Well, after some thoughts and looking at Qt 4.8 source code (Gitorious,
at least its web interface, was closed for maintenance yesterday in the
evening) my guess is that the problem is caused by Microsoft's
implementation of localtime() (QDateTime::fromTime_t() ends up in
utcToLocal() which on desktop systems uses localtime() or its variations
to get broken down timestamp representation) not applying/providing DST
information. But SystemTimeToTzSpecificLocalTime(), used internally by
QFileInfo time retrieval methods, adjusts its output according to the
current state of daylight saving, leading to that 1-hour difference
Calogero is experiencing.

I'll probably test this theory in a few hours when I get to a Windows
machine.
Post by Thiago Macieira
Post by Constantin Makshin
The original Calogero's message mentioned a file from December 2007, a
date outside of DST (unless there's a country that uses DST during
winter). Now it's August, so the DST is active and during "UTC -> local
time" conversion Windows adds that 1 hour Calogero is seeing. DST gets
incorrectly applied because it's active at the moment of conversion,
although it wasn't used at the moment the original timestamp represents.
That would support the theory that gmtime is broken on Windows, that it
doesn't apply the DST rules at all.
I don't have time to do further testing on this, so if someone can, it would
be appreciated. Also, please report the issue in the Qt issue tracker
(http://bugreports.qt-project.org) so it doesn't get forgotten.
PS: I don't know of any country that does DST in Winter. I do know of
countries that have Summer in December, though, and I know of regions that do
reverse DST during Winter.
Constantin Makshin
2013-08-28 05:20:30 UTC
Permalink
Damn, I just realized that I won't be able to test MSVC's localtime()
because Russia isn't using DST transitions since 2011, making it impossible
to distinguish "DST is not used for past years" from "localtime()
completely ignores daylight saving information".

Someone else has to do it.
Post by Constantin Makshin
Well, after some thoughts and looking at Qt 4.8 source code (Gitorious,
at least its web interface, was closed for maintenance yesterday in the
evening) my guess is that the problem is caused by Microsoft's
implementation of localtime() (QDateTime::fromTime_t() ends up in
utcToLocal() which on desktop systems uses localtime() or its variations
to get broken down timestamp representation) not applying/providing DST
information. But SystemTimeToTzSpecificLocalTime(), used internally by
QFileInfo time retrieval methods, adjusts its output according to the
current state of daylight saving, leading to that 1-hour difference
Calogero is experiencing.
I'll probably test this theory in a few hours when I get to a Windows
machine.
Post by Thiago Macieira
Post by Constantin Makshin
The original Calogero's message mentioned a file from December 2007, a
date outside of DST (unless there's a country that uses DST during
winter). Now it's August, so the DST is active and during "UTC -> local
time" conversion Windows adds that 1 hour Calogero is seeing. DST gets
incorrectly applied because it's active at the moment of conversion,
although it wasn't used at the moment the original timestamp represents.
That would support the theory that gmtime is broken on Windows, that it
doesn't apply the DST rules at all.
I don't have time to do further testing on this, so if someone can, it
would
Post by Thiago Macieira
be appreciated. Also, please report the issue in the Qt issue tracker
(http://bugreports.qt-project.org) so it doesn't get forgotten.
PS: I don't know of any country that does DST in Winter. I do know of
countries that have Summer in December, though, and I know of regions
that do
Post by Thiago Macieira
reverse DST during Winter.
Thiago Macieira
2013-08-28 05:39:55 UTC
Permalink
Post by Constantin Makshin
Damn, I just realized that I won't be able to test MSVC's localtime()
because Russia isn't using DST transitions since 2011, making it impossible
to distinguish "DST is not used for past years" from "localtime()
completely ignores daylight saving information".
Well, you can at least check whether historical rules are applied. If the
historical rules are applied, we're reasonably sure that this year's rules are
applied.

You can also change your timezone settings, can't you? :-)
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Constantin Makshin
2013-08-28 08:28:01 UTC
Permalink
I looked at the MSVC 2012 runtime library sources and it appears that
localtime() is not as bad as I thought. It applies the DST offset if
daylight saving is found to be active. It also tries some dark magic to
calculate historical DST transitions (I'm not sure I'm allowed to post
fragments of this code, so people with MSVC can take a look themselves --
the most important/interesting files in this case are "localtim.c" and
"tzset.c").

So it looks like this problem has to be solved by running the application
under debugger and stepping through Qt code to see what every function,
system or not, returns.
Post by Constantin Makshin
Post by Constantin Makshin
Damn, I just realized that I won't be able to test MSVC's localtime()
because Russia isn't using DST transitions since 2011, making it
impossible
Post by Constantin Makshin
to distinguish "DST is not used for past years" from "localtime()
completely ignores daylight saving information".
Well, you can at least check whether historical rules are applied. If the
historical rules are applied, we're reasonably sure that this year's rules are
applied.
You can also change your timezone settings, can't you? :-)
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Thiago Macieira
2013-08-28 05:21:15 UTC
Permalink
Post by Constantin Makshin
Well, after some thoughts and looking at Qt 4.8 source code (Gitorious,
at least its web interface, was closed for maintenance yesterday in the
evening
A better browser:
http://code.woboq.org/qt5/qtbase/src/corelib/tools/qdatetime.cpp.html#_ZL10localToUtcR5QDateR5QTimei

Now, they don't have Qt 4.8, but then again it's extremely unlikely we'd
change behaviour of QDateTime in Qt 4.8.6 now :-)
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Calogero Mauceri
2013-08-28 08:22:40 UTC
Permalink
Post by Constantin Makshin
The original Calogero's message mentioned a file from December 2007, a
date outside of DST (unless there's a country that uses DST during
winter). Now it's August, so the DST is active and during "UTC -> local
time" conversion Windows adds that 1 hour Calogero is seeing. DST gets
incorrectly applied because it's active at the moment of conversion,
although it wasn't used at the moment the original timestamp represents.
I bet that the problem will go away when DST ends [again]. :)
I think Constantin's analysis is correct.

Just for your information, I'm using Qt 4.8.4. The machine where I
noticed the problem is running Microsoft Windows Server 2003.
The Time Zone is set to (GMT-05:00) Eastern Time (US & Canada), in DST
currently.

Let me know if you need any additional information
Calogero
Post by Constantin Makshin
Post by Thiago Macieira
Post by Constantin Makshin
Windows can store information about daylight saving transitions for past
years, but always uses one for the current year. And since daylight
saving transition dates and time tend to slightly drift from year to
year, there's absolutely no guarantees of getting correct time
conversion results; in general case 1-hour error is nearly inevitable.
If you're on Windows, either calculate and apply DST yourself or forget
about correct "UTC <-> local time" conversions.
This is not about the corner case of a file that was created in the hour of the
transition, or even in the week that shifted between non-DST in one year to
DST in another (or vice-versa).
Daniel Bowen
2013-08-27 19:58:09 UTC
Permalink
Post by Constantin Makshin
One key is in the "Remarks" section of
SystemTimeToTzSpecificLocalTime()'s documentation
- *The time zone uses a different UTC offset for the old and new years*.
- The UTC time to be converted and the calculated local time are in different years.
Thanks for that. It looks like for Windows 7 and later, there's now a SystemTimeToTzSpecificLocalTimeEx (and TzSpecificLocalTimeToSystemTimeEx) which use the dynamic time zone structure. It doesn't list the caveats that SystemTimeToTzSpecificLocalTime mentions, so perhaps its historical accuracy is better (for when DST has changed the rules for the timezone in the past).

It is a little more cumbersome to have those functions only in later versions of Windows - you'd need to LoadLibrary/GetProcAddress to be able to call SystemTimeToTzSpecificLocalTimeEx if you detect Windows 7 or later, and use SystemTimeToTzSpecificLocalTime otherwise (if you try to early bind and just call the function in an "if" statement, you'd get "entry point not found" on older operating systems).

Thanks,
-Daniel
Loading...