| Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date | |
| All threads index page 2 | |
I'm on a linux x86_64 box, using Qt4.3.2 - struggling with timestamps.
I have the following code:
long l = -710996400;
const time_t * t_t = &l;
char * res = ctime (t_t);
qDebug ("Res val: %s", res);
struct tm tmp;
gmtime_r (t_t, &tmp);
qDebug ("y: %i, m: %i, d: %i, h: %i, mm: %i, wt: %i", tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tmp.tm_hour, tmp.tm_min, tmp.tm_wday);
QDateTime tdt (QDate (1900 + tmp.tm_year, 1 + tmp.tm_mon, tmp.tm_mday), QTime (tmp.tm_hour, tmp.tm_min, tmp.tm_sec), Qt::UTC);
qDebug ("tdt: %s, local: %s", qPrintable (tdt.toString ()), qPrintable (tdt.toLocalTime ().toString ()));
struct tm tmp2;
localtime_r (t_t, &tmp2);
qDebug ("y: %i, m: %i, d: %i, h: %i, mm: %i, wt: %i", tmp2.tm_year, tmp2.tm_mon, tmp2.tm_mday, tmp2.tm_hour, tmp2.tm_min, tmp2.tm_wday);
QDateTime tdt2 (QDate (1900 + tmp2.tm_year, 1 + tmp2.tm_mon, tmp2.tm_mday), QTime (tmp2.tm_hour, tmp2.tm_min, tmp2.tm_sec), Qt::UTC);
qDebug ("tdt2: %s", qPrintable (tdt2.toString ()));
and this is the output:
Res val: Sun Jun 22 00:00:00 1947
y: 47, m: 5, d: 21, h: 21, mm: 0, wt: 6
tdt: Sat Jun 21 21:00:00 1947, local: Sat Jun 21 22:00:00 1947
y: 47, m: 5, d: 22, h: 0, mm: 0, wt: 0
tdt2: Sun Jun 22 00:00:00 1947
I would have expected QDateTime::toUTC and QDateTime::toLocalTime to return the same time diff as gmtime / localtime
Is this a bug - or where does this discrepancy come from?
Frank
--
[ signature omitted ]
Silly Question One: What is the timezone setting on your machine ?
Silly Question Two: Is there a reason you are messing about back in
1947 ?
On Apr 4, 2008, at 8:26 PM, Frank Hemer wrote:
> I'm on a linux x86_64 box, using Qt4.3.2 - struggling with timestamps.
>
> I have the following code:
>
> long l = -710996400;
> const time_t * t_t = &l;
> char * res = ctime (t_t);
> qDebug ("Res val: %s", res);
>
> struct tm tmp;
> gmtime_r (t_t, &tmp);
> qDebug ("y: %i, m: %i, d: %i, h: %i, mm: %i, wt: %i",
> tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tmp.tm_hour, tmp.tm_min,
> tmp.tm_wday);
> QDateTime tdt (QDate (1900 + tmp.tm_year, 1 + tmp.tm_mon,
> tmp.tm_mday), QTime (tmp.tm_hour, tmp.tm_min, tmp.tm_sec), Qt::UTC);
> qDebug ("tdt: %s, local: %s", qPrintable (tdt.toString ()),
> qPrintable (tdt.toLocalTime ().toString ()));
>
> struct tm tmp2;
> localtime_r (t_t, &tmp2);
> qDebug ("y: %i, m: %i, d: %i, h: %i, mm: %i, wt: %i",
> tmp2.tm_year, tmp2.tm_mon, tmp2.tm_mday, tmp2.tm_hour, tmp2.tm_min,
> tmp2.tm_wday);
> QDateTime tdt2 (QDate (1900 + tmp2.tm_year, 1 + tmp2.tm_mon,
> tmp2.tm_mday), QTime (tmp2.tm_hour, tmp2.tm_min, tmp2.tm_sec),
> Qt::UTC);
> qDebug ("tdt2: %s", qPrintable (tdt2.toString ()));
>
> and this is the output:
>
> Res val: Sun Jun 22 00:00:00 1947
> y: 47, m: 5, d: 21, h: 21, mm: 0, wt: 6
> tdt: Sat Jun 21 21:00:00 1947, local: Sat Jun 21 22:00:00 1947
> y: 47, m: 5, d: 22, h: 0, mm: 0, wt: 0
> tdt2: Sun Jun 22 00:00:00 1947
>
> I would have expected QDateTime::toUTC and QDateTime::toLocalTime
> to return the same time diff as gmtime / localtime
>
> Is this a bug - or where does this discrepancy come from?
>
> Frank
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
> with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
--
[ signature omitted ]
Dan White wrote: > Silly Question One: What is the timezone setting on your machine ? > Silly Question Two: Is there a reason you are messing about back in > 1947 ? It's a simulation program meant to model economic recovery in Europe after World War II? :) -- [ signature omitted ]
Frank Hemer wrote: >y: 47, m: 5, d: 21, h: 21, mm: 0, wt: 6 >tdt: Sat Jun 21 21:00:00 1947, local: Sat Jun 21 22:00:00 1947 >y: 47, m: 5, d: 22, h: 0, mm: 0, wt: 0 > >I would have expected QDateTime::toUTC and QDateTime::toLocalTime to > return the same time diff as gmtime / localtime It would have, if you did not have a negative date. QDateTime timezone rules depend on the Unix time_t, which starts in 1970. -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
On Saturday 05 April 2008 09:22:49 Thiago Macieira wrote: > Frank Hemer wrote: > >y: 47, m: 5, d: 21, h: 21, mm: 0, wt: 6 > >tdt: Sat Jun 21 21:00:00 1947, local: Sat Jun 21 22:00:00 1947 > >y: 47, m: 5, d: 22, h: 0, mm: 0, wt: 0 > > > >I would have expected QDateTime::toUTC and QDateTime::toLocalTime to > > return the same time diff as gmtime / localtime I didn't mention before: Timezone is Europe/Berlin I'm developing a medical app, transmitting date of birth from a java server to a qt rich client. Transmission format is a qint64 holding the milliseconds since Epoche (1970, 1, 1). > It would have, if you did not have a negative date. QDateTime timezone > rules depend on the Unix time_t, which starts in 1970. That would mean, QDateTime cannot be used for DateTimes before Epoche?? This is not mentioned in the docs. Well, so what chance do I have to convert the msecs to a valid date? time_t, as implemented in QDateTime doesn't help as it is only valid after the Epoche. Setting the value manually (QDateTime (QDate (y, m, d), QTime (h, m, s)), xxx) doesn't help either? Frank -- [ signature omitted ]
Frank Hemer wrote: >On Saturday 05 April 2008 09:22:49 Thiago Macieira wrote: >> Frank Hemer wrote: >> >y: 47, m: 5, d: 21, h: 21, mm: 0, wt: 6 >> >tdt: Sat Jun 21 21:00:00 1947, local: Sat Jun 21 22:00:00 1947 >> >y: 47, m: 5, d: 22, h: 0, mm: 0, wt: 0 >> > >> >I would have expected QDateTime::toUTC and QDateTime::toLocalTime to >> > return the same time diff as gmtime / localtime > >I didn't mention before: >Timezone is Europe/Berlin > >I'm developing a medical app, transmitting date of birth from a java > server to a qt rich client. Transmission format is a qint64 holding the > milliseconds since Epoche (1970, 1, 1). > >> It would have, if you did not have a negative date. QDateTime timezone >> rules depend on the Unix time_t, which starts in 1970. > >That would mean, QDateTime cannot be used for DateTimes before Epoche?? QDateTime can. The timezone database it uses can't. >This is not mentioned in the docs. > >Well, so what chance do I have to convert the msecs to a valid date? >time_t, as implemented in QDateTime doesn't help as it is only valid > after the Epoche. Setting the value manually (QDateTime (QDate (y, m, > d), QTime (h, m, s)), xxx) doesn't help either? Use a full QDateTime (year, month, day, hour, minute and second) or whatever makes sense to you. Dates of birth and timezones don't make sense together. -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
On Saturday 05 April 2008 14:54:19 Thiago Macieira wrote: > Frank Hemer wrote: > >On Saturday 05 April 2008 09:22:49 Thiago Macieira wrote: > >> Frank Hemer wrote: > >> >y: 47, m: 5, d: 21, h: 21, mm: 0, wt: 6 > >> >tdt: Sat Jun 21 21:00:00 1947, local: Sat Jun 21 22:00:00 1947 > >> >y: 47, m: 5, d: 22, h: 0, mm: 0, wt: 0 > >> > > >> >I would have expected QDateTime::toUTC and QDateTime::toLocalTime to > >> > return the same time diff as gmtime / localtime > > > >I didn't mention before: > >Timezone is Europe/Berlin > > > >I'm developing a medical app, transmitting date of birth from a java > > server to a qt rich client. Transmission format is a qint64 holding the > > milliseconds since Epoche (1970, 1, 1). > > > >> It would have, if you did not have a negative date. QDateTime timezone > >> rules depend on the Unix time_t, which starts in 1970. > > > >That would mean, QDateTime cannot be used for DateTimes before Epoche?? > > QDateTime can. The timezone database it uses can't. This would at least require a clear statement in the docs ... > >Well, so what chance do I have to convert the msecs to a valid date? > >time_t, as implemented in QDateTime doesn't help as it is only valid > > after the Epoche. Setting the value manually (QDateTime (QDate (y, m, > > d), QTime (h, m, s)), xxx) doesn't help either? > > Use a full QDateTime (year, month, day, hour, minute and second) or > whatever makes sense to you. Dates of birth and timezones don't make > sense together. First, date of birth was just an example, second, date of birth comes with full date _and_ time info from the database - timezone info included. Its a medical database and the time of birth is a required info. So I have to handle it properly. Other timestamps _before_ 1970 also are stored in the same manner, so I have to implement a clean solution. Probably I have to implement timezone handling myself across platforms. Still I think this should be handled by QDateTime ... Frank -- [ signature omitted ]
Frank Hemer wrote: >> >Well, so what chance do I have to convert the msecs to a valid date? >> >time_t, as implemented in QDateTime doesn't help as it is only valid >> > after the Epoche. Setting the value manually (QDateTime (QDate (y, >> > m, d), QTime (h, m, s)), xxx) doesn't help either? >> >> Use a full QDateTime (year, month, day, hour, minute and second) or >> whatever makes sense to you. Dates of birth and timezones don't make >> sense together. > >First, date of birth was just an example, second, date of birth comes > with full date _and_ time info from the database - timezone info > included. Its a medical database and the time of birth is a required > info. So I have to handle it properly. >Other timestamps _before_ 1970 also are stored in the same manner, so I > have to implement a clean solution. >Probably I have to implement timezone handling myself across platforms. > >Still I think this should be handled by QDateTime ... QDateTime handles only two timezones: Local and UTC. And it works fine under either. The conversion between them requires information from the timezone database. On Unix systems, that database contains historical information, so all past dates should be correct. Unfortunately, that database uses time_t, so it has to be a positive value because some Unix systems have an unsigned time_t. If a data falls outside the range of positive values in a 32-bit signed time_t, QDateTime will use the lowest or highest values (Jan 1st 1970 or Jan 19, 2038). The idea there is that we'll at least get the offset from GMT right, even if the DST information was lost. But, come to think of it, we can do better: use the same day and month, but the lowest or highest year (1970 or 2037). At least there's a higher chance of getting DST right. Anyways, that explains why you got different values: 1) QDateTime applied the rules for Jan 1st 1970 for your June 1947 date. 2) In January 1970, Berlin was most likely in Central European Time (GMT+1) 3) In June 1947, Berlin was likely in Summer Time. But you're seeing 3 hours ahead of GMT, which is either Double Summertime or Berlin was in a different timezone then. 4) you're assuming that the negative time_t worked with localtime(). -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
On Saturday 05 April 2008 17:28, Thiago Macieira wrote: > Frank Hemer wrote: > >> >Well, so what chance do I have to convert the msecs to a valid date? > >> >time_t, as implemented in QDateTime doesn't help as it is only valid > >> > after the Epoche. Setting the value manually (QDateTime (QDate (y, > >> > m, d), QTime (h, m, s)), xxx) doesn't help either? > >> > >> Use a full QDateTime (year, month, day, hour, minute and second) or > >> whatever makes sense to you. Dates of birth and timezones don't make > >> sense together. > > > >First, date of birth was just an example, second, date of birth comes > > with full date _and_ time info from the database - timezone info > > included. Its a medical database and the time of birth is a required > > info. So I have to handle it properly. > >Other timestamps _before_ 1970 also are stored in the same manner, so I > > have to implement a clean solution. > >Probably I have to implement timezone handling myself across platforms. > > > >Still I think this should be handled by QDateTime ... > > QDateTime handles only two timezones: Local and UTC. And it works fine > under either. > > The conversion between them requires information from the timezone > database. On Unix systems, that database contains historical information, > so all past dates should be correct. Unfortunately, that database uses > time_t, so it has to be a positive value because some Unix systems have > an unsigned time_t. > > If a data falls outside the range of positive values in a 32-bit signed > time_t, QDateTime will use the lowest or highest values (Jan 1st 1970 or > Jan 19, 2038). The idea there is that we'll at least get the offset from > GMT right, even if the DST information was lost. > > But, come to think of it, we can do better: use the same day and month, > but the lowest or highest year (1970 or 2037). At least there's a higher > chance of getting DST right. That would definitely be better. Still this is not a solution for critical applications like mine. > Anyways, that explains why you got different values: > 1) QDateTime applied the rules for Jan 1st 1970 for your June 1947 date. > > 2) In January 1970, Berlin was most likely in Central European Time > (GMT+1) > > 3) In June 1947, Berlin was likely in Summer Time. But you're seeing 3 > hours ahead of GMT, which is either Double Summertime or Berlin was in a > different timezone then. > > 4) you're assuming that the negative time_t worked with localtime(). I wonder how this is handled in qt jambi? You probably have to handle conversion between java.util.Date <-> QDateTime. The java date is UTC - and for now (and me) it seems its calculations are correct even prior to the Epoche. Frank -- [ signature omitted ]
On Sunday 06 April 2008 01:48:01 Frank Hemer wrote: > > But, come to think of it, we can do better: use the same day and month, > > but the lowest or highest year (1970 or 2037). At least there's a higher > > chance of getting DST right. > [...] > That would definitely be better. Still this is not a solution for critical > applications like mine. Well, for critical applications I would not trust any kind of timezone database. The only thing that sort-of-works is to fix a 0 and count "real" seconds from there. Any "translation" into "human readable form" using month, days and hours is bound to fail rather sooner then later - not to mention using such a format as "primary data". Recently there was this discussion on the Gregorian changes, which took 300 years to spread across Europe alone. No way to handle that reliably... > > Anyways, that explains why you got different values: > > 1) QDateTime applied the rules for Jan 1st 1970 for your June 1947 date. 1947... well, there was a time when part of Germany had Moscow time. Not sure this bites here, but it's not unlikely. Incidentally, that boundary between Moscow and (something like) Central European Time within Germany at that time did _not_ coincide with the later border between East and West Germany. So to get "proper" "time" you'd need not only need the GPS data of frontline Russian and American tanks around May 9, 1945 (give or take a few days, and kilometers, ...) but also take into account the speed and willingness of local commanders setting up townhall clocks ;-) Regards, Andre' -- [ signature omitted ]
On Monday 07 April 2008 10:24:15 Andrà PÃnitz wrote: > > > Anyways, that explains why you got different values: > > > 1) QDateTime applied the rules for Jan 1st 1970 for your June 1947 > > > date. > > 1947... well, there was a time when part of Germany had Moscow time. > Not sure this bites here, but it's not unlikely. I have reviewed the timezone database and there are really, really weird rules there. When they are able, the database keepers try to record historical information of the past, like double summer times observed in times of war. The database also contains the very useless local mean time of the city, as well as the leap second information. (December 31st, 23:59:60 and June 30th, 23:59:60, see wikipedia) In any case, there's one interesting rule: dates before 1970 and after 2037 are not keep strict. What matters is the 32-bit signed positive range of time_t. I'll be making the following changes to fix this bug: 1) when the dates fall outside the range of 1970-01-01 and 2037-12-31, change only the year to match the upper or lower limit, but keep the day and month intact. 2) add some information to the documentation of QDateTime, specifically about the Julian/Gregorian switch in 1582 and the fact that the timezone database isn't precise for any date that isn't between 1970 and the present. And then for Unix only, since Windows has no concept of timezone database. It's interesting to note that the choice of new year's day for calculating the GMT offset in QDateTime means there's a higher probability of being wrong than being right. The Northern Hemisphere spends more than half of the year in Summer Time and more than half of the world's population is in it. That means that, for a given date, there's a higher probability that DST rules should be applied instead of the official time. For the Southern Hemisphere, it's the opposite: it spends less than half of the year in Summer Time. But, of course, since New Year's Day is in Summer, the probability that the offset wanted was the official time (instead of the DST one) is greater. Timekeeping for past dates is very, very uncertain. The concept of organised timezones as we know today didn't exist more than 50 years ago. Many European countries before 1940 used local mean times: for example, the Netherlands' official time was 20 minutes ahead of GMT; in the UK, until 1900, the use of local mean time in each city was the rule. Not only that, there's also the problem of the Gregorian/Julian switch, which happened in different countries at different times. And there's the problem of some countries tinkering with their calendars, like when Sweden decided to have a February 30th in 1712. And you thought Y2K was complicated :-) -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
On Monday 07 April 2008 11:21, Thiago Macieira wrote: > On Monday 07 April 2008 10:24:15 Andrà PÃnitz wrote: > > > > Anyways, that explains why you got different values: > > > > 1) QDateTime applied the rules for Jan 1st 1970 for your June 1947 > > > > date. > > > > 1947... well, there was a time when part of Germany had Moscow time. > > Not sure this bites here, but it's not unlikely. > > I have reviewed the timezone database and there are really, really weird > rules there. > In any case, there's one interesting rule: dates before 1970 and after 2037 > are not keep strict. What matters is the 32-bit signed positive range of > time_t. Hmm - what about those systems that support the negative range, however precise or not that may be. Could qt support the negative range there too? It seems that the system I'm working on supports that range - at least with its system calls. And because the data is entered in local time, it might internally be converted into a invalid utc time but will be accessed in local time again, so this deviation will never appear on the users side. Java seems to work that way (not really sure though) - very likely because of all the reasons you have mentioned before. > I'll be making the following changes to fix this bug: > 1) when the dates fall outside the range of 1970-01-01 and 2037-12-31, > change only the year to match the upper or lower limit, but keep the day > and month intact. > > 2) add some information to the documentation of QDateTime, specifically > about the Julian/Gregorian switch in 1582 and the fact that the timezone > database isn't precise for any date that isn't between 1970 and the > present. And then for Unix only, since Windows has no concept of timezone > database. I see no clean way to transmit timestamps to a richclient other than in utc. Otherwise one could not support multiple clients in different timezones according to their individual setup. I had the impression, conversion on windows and unix up to now are only based on qts internal calculation - did I overlook sth? > > Timekeeping for past dates is very, very uncertain. > > The concept of organised timezones as we know today didn't exist more than > 50 years ago. Many European countries before 1940 used local mean times: > for example, the Netherlands' official time was 20 minutes ahead of GMT; in > the UK, until 1900, the use of local mean time in each city was the rule. > > Not only that, there's also the problem of the Gregorian/Julian switch, > which happened in different countries at different times. And there's the > problem of some countries tinkering with their calendars, like when Sweden > decided to have a February 30th in 1712. > > And you thought Y2K was complicated :-) Not really;-) Had some struggle with this timezone stuff before ... especially with the windows weird behavior. I wonder how others handle this - any thoughts here? Frank -- [ signature omitted ]
My first reaction would be that you might have to keep track of the time as a set of individual numbers (y, m, d/h, m, s) rather than a single number -- like ISO 8601 Date/Time notation <http://en.wikipedia.org/wiki/ISO_8601> The only other thing that comes to mind is the Julian Day system used by astronomers <http://en.wikipedia.org/wiki/Julian_day> I do not know if any of that will help, but they are possibilities. Good luck. On Apr 5, 2008, at 6:58 AM, Frank Hemer wrote: > On Saturday 05 April 2008 09:22:49 Thiago Macieira wrote: >> Frank Hemer wrote: >>> y: 47, m: 5, d: 21, h: 21, mm: 0, wt: 6 >>> tdt: Sat Jun 21 21:00:00 1947, local: Sat Jun 21 22:00:00 1947 >>> y: 47, m: 5, d: 22, h: 0, mm: 0, wt: 0 >>> >>> I would have expected QDateTime::toUTC and QDateTime::toLocalTime to >>> return the same time diff as gmtime / localtime > > I didn't mention before: > Timezone is Europe/Berlin > > I'm developing a medical app, transmitting date of birth from a > java server to a qt rich client. > Transmission format is a qint64 holding the milliseconds since > Epoche (1970, 1, 1). > >> It would have, if you did not have a negative date. QDateTime >> timezone >> rules depend on the Unix time_t, which starts in 1970. > > That would mean, QDateTime cannot be used for DateTimes before > Epoche?? > This is not mentioned in the docs. > > Well, so what chance do I have to convert the msecs to a valid date? > time_t, as implemented in QDateTime doesn't help as it is only > valid after the Epoche. > Setting the value manually (QDateTime (QDate (y, m, d), QTime (h, > m, s)), xxx) doesn't > help either? > > Frank > > -- > To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx > with "unsubscribe" in the subject or the body. > List archive and information: http://lists.trolltech.com/qt-interest/ > -- [ signature omitted ]