RE: [Evolution] time_add_day() problem

(Subtitled: fun with dates, continued.)

Damon Chaplin wrote:
I've been using it to calculate the start of each day for the calendar

I don't know of any groups that do start of day other than some hard,
measurable point. Like midnight, or sun-up, or 6am. Is there any reason
not to just hardcode this as a choosable time of day?

This code confuses me a bit:
This seems to say that if the dst flag has changed, then the new time_t
has to be adjusted.

Me too. Since I haven't looked at the code yet (T minus two weeks and
counting on my current project), I can't really say what's going on. There
was probably a good reason though :-).

Oh, wait, I bet I know what's going on. They're probably setting up the tm
struct by hand, and forgetting to set the tm_isdst to true if it's inside
daylight savings time. If you iterate your way through the year, this
won't be a problem. But setting

  tm.tm_mon=0; tm.tm_mday=180;

in a zeroed struct tm is really incomplete, as by the 180th day of the
year, it's currently DST. Setting the month, then day, then doing a
mktime() to set is_dst, then setting the hour and minute and doing a
mktime() will fix it up. For example:

 [ray ~]$ cat dst.c
 #include <stdio.h>
 #include <time.h>

 int main(int argc, char *argv[]) {
         struct tm tm;
         char buff[40];
         int i;

         for (i=0;i<1500;i+=60) {
                 memset(&tm,0,sizeof tm);
                 tm.tm_mon=atoi(argv[2])-1;  tm.tm_mday=atoi(argv[3]);
                 tm.tm_hour=0; tm.tm_min=i;
                 strftime(buff,sizeof buff, "%b %d %H:%M",&tm);
                 printf("%s%s\n",buff,tm.tm_isdst==1 ? " (DST)" : "");
 [ray ~]$ ./dst 2000 4 2
 Apr 02 00:00
 Apr 02 01:00
 Apr 02 03:00 (DST)
 Apr 02 04:00 (DST)
 Apr 02 05:00 (DST)
 Apr 02 06:00 (DST)
 Apr 02 07:00 (DST)
 Apr 02 08:00 (DST)
 Apr 02 09:00 (DST)
 Apr 02 10:00 (DST)
 Apr 02 11:00 (DST)
 Apr 02 12:00 (DST)
 Apr 02 13:00 (DST)
 Apr 02 14:00 (DST)
 Apr 02 15:00 (DST)
 Apr 02 16:00 (DST)
 Apr 02 17:00 (DST)
 Apr 02 18:00 (DST)
 Apr 02 19:00 (DST)
 Apr 02 20:00 (DST)
 Apr 02 21:00 (DST)
 Apr 02 22:00 (DST)
 Apr 02 23:00 (DST)
 Apr 03 00:00 (DST)
 Apr 03 01:00 (DST)
 [ray ~]$ ./dst 2000 10 29
 Oct 29 00:00 (DST)
 Oct 29 01:00 (DST)
 Oct 29 01:00
 Oct 29 02:00
 Oct 29 03:00
 Oct 29 04:00
 Oct 29 05:00
 Oct 29 06:00
 Oct 29 07:00
 Oct 29 08:00
 Oct 29 09:00
 Oct 29 10:00
 Oct 29 11:00
 Oct 29 12:00
 Oct 29 13:00
 Oct 29 14:00
 Oct 29 15:00
 Oct 29 16:00
 Oct 29 17:00
 Oct 29 18:00
 Oct 29 19:00
 Oct 29 20:00
 Oct 29 21:00
 Oct 29 22:00
 Oct 29 23:00
 [ray ~]$

(In production code that iterator would be written differently, but you
get the idea.)

Anyway, if you don't do it in the right order here, the c library tries
the best it can, which gives a start to the day of 1am. This is actually a
sane default because it corresponds to 24hours beyond the previous day, it
just may not be what you expect.

I've seen no scheduling or calendaring program that gets this right.
Outlook 2000, for example, doesn't even try to deal with daylight savings
time. It just shows 24 hours, labeled as usual.

But won't mktime() handle it correctly, just by adding on to tm_tmmday ?

Add one to tm_mday, mktime(), pick an hour, and you're at the next day. If
the std c library on your platform handles DST correctly, you should be
able to get the time_t types corresponding to the previous day and the
current day, do a difftime(), and see whether the previous day had 23
hours or 25. Or you can iterate through the day as above.

The only problem I can see is if clocks go forward and the hour + minute
that you wanted doesn't really exist. (Also, when clocks go
backward there may be 2 different time_t values representing the
same hour + minute - one with DST and one without.)

Right, which is why anyone who needs to deal with this sanely keeps times
in UTC. <mathspeak> Monotonic strictly-increasing sequences are your
friend. </mathspeak>

Ray Lee / ray madrabbit org ~ rblee impulse net

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]