Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Sat, 23 Mar 2024 20:40:50 +0000
From: Alexander Weps <exander77@...me>
To: musl@...ts.openwall.com
Cc: Markus Wichmann <nullplan@....net>
Subject: Re: Broken mktime calculations when crossing DST boundary

Yes, the behavior is the same here glibc and musl and it can't reliably determine start of the day etc. Which is I assume expected.

That's why there is tm_isdst = -1.

I don't see any reliable way to determine beginning of the day without it.

If I want to get beginning of the day I do it this way:

before: 2010-10-31 14:00:00 CET
tm_sec: 0
tm_min: 0
tm_hour: 14
tm_mday: 31
tm_mon: 9
tm_year: 110
tm_wday: 0
tm_yday: 303
tm_isdst: 0
tm_gmtoff: 3600
tm_zone: CET

tm.tm_isdst = -1; <-- setting tm_isdst = -1
tm.tm_hour = 0;
mktime(&tm);

after: 2010-10-31 00:00:00 CEST
tm_sec: 0
tm_min: 0
tm_hour: 0
tm_mday: 31
tm_mon: 9
tm_year: 110
tm_wday: 0
tm_yday: 303
tm_isdst: 1
tm_gmtoff: 7200
tm_zone: CEST

Is there a way, how to reliable get beginning of day etc. without tm_isdst = -1.

AW


On Saturday, March 23rd, 2024 at 21:18, Rich Felker <dalias@...c.org> wrote:

> On Sat, Mar 23, 2024 at 06:57:21PM +0000, Alexander Weps wrote:
>
> > So, in the meantime, I was debugging with not setting tm_isdst = -1;
> >
> > This causes pretty annoying behavior:
> >
> > before: 2010-10-31 14:00:00
> >
> > tm_sec: 0
> > tm_min: 0
> > tm_hour: 14
> > tm_mday: 31
> > tm_mon: 9
> > tm_year: 110
> > tm_wday: 0
> > tm_yday: 0
> > tm_isdst: 0
> > tm_gmtoff: 3600
> > tm_zone: CET
> >
> > tm->tm_hour = 0; <-- reset hour field
> > mktime(&tm);
> >
> > after: 2010-10-31 01:00:00 CEST <-- 10:00:00 instead of 00:00:00
>
>
> I guess you meant 01:00:00 not 10:00:00. This is expected. You asked
> mktime to normalize a time expressed in standard (non-DST, CET) time
> but referring to a time at which DST is in effect. After
> normalization, it expresses that time in DST (CEST). Since there is no
> tm_isdst<0 (the only source of arbitrary implementation choices)
> involved, you will find glibc and all other implementations do exactly
> the same thing here.
>
> > tm_sec: 0
> > tm_min: 0
> > tm_hour: 1
> > tm_mday: 31
> > tm_mon: 9
> > tm_year: 110
> > tm_wday: 0
> > tm_yday: 303
> > tm_isdst: 1
> > tm_gmtoff: 7200
> > tm_zone: CEST
> >
> > tm->tm_hour = 0;
> > mktime(&tm);
> >
> > after: 2010-10-31 00:00:00 CEST <-- second run gives a correct value
> > tm_sec: 0
> > tm_min: 0
> > tm_hour: 0
> > tm_mday: 31
> > tm_mon: 9
> > tm_year: 110
> > tm_wday: 0
> > tm_yday: 303
> > tm_isdst: 1
> > tm_gmtoff: 7200
> > tm_zone: CEST
> >
> > This basically means that setting field twice produces different
> > value each time:
>
>
> No it does not. After the first time, tm_isdst is 1. Now when you
> change the hour to 0, you are giving it a time expressed in DST. Since
> DST is in effect at this time, it's already normalized, and you get
> back what you put in.
>
> Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.