[Mono-dev] DateTime.Now gives a wrong time

Robert Jordan robertj at gmx.net
Wed Oct 12 16:58:49 EDT 2011


On 12.10.2011 22:05, k0l0b0k.void at gmail.com wrote:
> Hello guys, thanks for your replies. I think, I've understand the situation.
> Some weeks ago, Ukraine and Belarus has timezone changes by law, and now we
> are FET timezone (GMT+3, without DST). As Robert pointed, I've look into
> TimeZone.* methods, and their native implementations, and found, that wrong
> GMT offset brings by glibc's mktime function. But, it is not mktime bug
> (however, I'm not sure), it is mono issue - code from icall.c:5931:
>
>      memset (&start, 0, sizeof (start));
>
>      start.tm_mday = 1;
>      start.tm_year = year-1900;
>
>      t = mktime (&start);
>
> I've found, that setting only tm_year in start struct is insufficiently. At
> least tm_mon must be set too, to avoid this issue. Simple test:
>
> #include<stdio.h>
> #include<time.h>
> #include<memory.h>
>
> int main(int argc, char *argv[])
> {
>      struct tm t;
>      memset(&t, 0, sizeof(t));
>      t.tm_year = 111; // 2011
>      t.tm_mon = 10;   // wrong tm_gmtoff will received if comment out this line

tm_mon = 0 means January 1st 2011. Back then, the offset was GMT+2,
Eastern Europe Time, so the call is correct.

The problem is not tm_mon = 0, because Mono does it on purpose
to get the first day of the year:

https://github.com/mono/mono/blob/master/mono/metadata/icall.c#L6013

Then it starts looping to find out when the GMT offset is changing:

https://github.com/mono/mono/blob/master/mono/metadata/icall.c#L6038

This probably happened at some date in March:

https://github.com/mono/mono/blob/master/mono/metadata/icall.c#L6063

Then it loops further to find out when the GMT offset changes again.
But this second change is never happening, because FET remains
forever at GTM+3 => Mono thinks it's still on DST for the rest of
the year.


I believe the fix is to remove the if-statement at

https://github.com/mono/mono/blob/master/mono/metadata/icall.c#L6076

because the code inside the if-statement must be executed
regardless of is_daylight's value.

Robert



More information about the Mono-devel-list mailing list