[Mono-dev] why does DateTime.Now.IsDaylightSavingTime() returns false when it should be true.

Alistair Bush alistair.bush at gmail.com
Thu Nov 7 09:07:35 UTC 2013


Hi guys,

Please note that I have cleaned this up and bit and submitted a pull request

https://github.com/mono/mono/pull/800

Feedback welcome.

On Wed, Oct 30, 2013 at 11:51 PM, Alistair Bush <alistair.bush at gmail.com> wrote:
> Ok so firstly this is like the MOST C ive ever written in my life..
> and it looks ugly and ive only vagely checked that it doesn't break
> the northern hemisphere.
>
> But isn't this a better patch of the method?
> (https://github.com/alistair/mono/commit/6912202aab5a424e98bc44d7b988c2791f9cccc1)
>
> Any help turning this into an acceptable pull request would be really
> appreciated.
>
> diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c
> index 618e4da..7f47624 100644
> --- a/mono/metadata/icall.c
> +++ b/mono/metadata/icall.c
> @@ -5930,10 +5930,12 @@
> ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year,
> MonoArray
>   struct tm start, tt;
>   time_t t;
>
> - long int gmtoff;
> - int is_daylight = 0, day;
> + long int gmtoff, gmtoff_st, gmtoff_ds;
> + int day, transitioned;
>   char tzone [64];
>
> + gmtoff_st = gmtoff_ds = transitioned = 0;
> +
>   MONO_ARCH_SAVE_REGS;
>
>   MONO_CHECK_ARG_NULL (data);
> @@ -5974,8 +5976,10 @@
> ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year,
> MonoArray
>   t += 3600*24;
>   tt = *localtime (&t);
>
> +        long int gmtoff_after = gmt_offset(&tt, t);
> +
>   /* Daylight saving starts or ends here. */
> - if (gmt_offset (&tt, t) != gmtoff) {
> + if (gmtoff_after != gmtoff) {
>   struct tm tt1;
>   time_t t1;
>
> @@ -5995,36 +5999,37 @@
> ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year,
> MonoArray
>   strftime (tzone, sizeof (tzone), "%Z", &tt);
>
>   /* Write data, if we're already in daylight saving, we're done. */
> - if (is_daylight) {
> - mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
> - mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
> - return 1;
> + if (tt.tm_isdst) {
> + mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
> + mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
> + if (gmtoff_ds == 0) {
> + gmtoff_st = gmtoff;
> + gmtoff_ds = gmtoff_after;
> + }
> + transitioned++;
>   } else {
> - struct tm end;
>   time_t te;
> + te = mktime (&tt);
>
> - memset (&end, 0, sizeof (end));
> - end.tm_year = year-1900 + 1;
> - end.tm_mday = 1;
> -
> - te = mktime (&end);
> -
> - mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
> - mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
>   mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
>   mono_array_set ((*data), gint64, 1, ((gint64)te + EPOCH_ADJUST) * 10000000L);
> - is_daylight = 1;
> + if (gmtoff_ds == 0) {
> + gmtoff_st = gmtoff_after;
> + gmtoff_ds = gmtoff;
> + }
> + transitioned++;
>   }
>
>   /* This is only set once when we enter daylight saving. */
> - mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
> - mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) -
> gmtoff) * 10000000L);
> -
> + if (tt1.tm_isdst) {
> + mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
> + mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st)
> * 10000000L);
> + }
>   gmtoff = gmt_offset (&tt, t);
>   }
>   }
>
> - if (!is_daylight) {
> + if (transitioned < 2) {
>   strftime (tzone, sizeof (tzone), "%Z", &tt);
>   mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
>   mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
>
> On Tue, Oct 29, 2013 at 9:13 AM, Alistair Bush <alistair.bush at gmail.com> wrote:
>> Well that certainly sucks.
>>
>>
>> On Tue, Oct 29, 2013 at 3:03 AM, Robert Jordan <robertj at gmx.net> wrote:
>>>
>>> On 28.10.2013 07:35, Alistair Bush wrote:
>>>>
>>>> I am trying to figure out why exactly running
>>>> DateTime.Now.IsDaylightSavingTIme() returns false.
>>>> I live in the Auckland/Pacific timezone and pretty much everywhere I
>>>> look it confirms that yes it is daylight saving time.
>>>
>>>
>>> Unfortunately, I don't remember the details, but I'm pretty
>>> sure that ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData
>>> has a bug w/ respect to the Southern Hemisphere.
>>>
>>> The code assumes that a year always begins outside a DST zone,
>>> and this is obviously incorrect for the Southern Hemisphere.
>>>
>>> To fix this, the local var "is_daylight" must be properly
>>> initialized. Currently, it's always 0 at start, but it must
>>> be initialized with 1 when January, 1st is inside a DST
>>> zone.
>>>
>>> Maybe this:
>>>
>>>         is_daylight = start.tm_isdst > 0;
>>>
>>> just before
>>>
>>>         /* For each day of the year, calculate the tm_gmtoff. */
>>>         for (day = 0; day < 365; day++) {
>>>
>>> Robert
>>>
>>>
>>> _______________________________________________
>>> Mono-devel-list mailing list
>>> Mono-devel-list at lists.ximian.com
>>> http://lists.ximian.com/mailman/listinfo/mono-devel-list
>>
>>


More information about the Mono-devel-list mailing list