Merge pull request #1696 from esdrubal/tzrefactor
[mono.git] / mono / metadata / icall.c
index 62040ceb6d928807e6769975538f9e9400d2c25f..6ac14185a1b611f007ed9488ef245e6c9dcdb8ba 100644 (file)
@@ -5613,257 +5613,6 @@ ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
        this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
 }
 
-/*
- * Magic number to convert a time which is relative to
- * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
- */
-#define        EPOCH_ADJUST    ((guint64)62135596800LL)
-
-/*
- * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
- */
-#define FILETIME_ADJUST ((guint64)504911232000000000LL)
-
-#ifdef HOST_WIN32
-/* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
-static void
-convert_to_absolute_date(SYSTEMTIME *date)
-{
-#define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
-       static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-       static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-       /* from the calendar FAQ */
-       int a = (14 - date->wMonth) / 12;
-       int y = date->wYear - a;
-       int m = date->wMonth + 12 * a - 2;
-       int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
-
-       /* d is now the day of the week for the first of the month (0 == Sunday) */
-
-       int day_of_week = date->wDayOfWeek;
-
-       /* set day_in_month to the first day in the month which falls on day_of_week */    
-       int day_in_month = 1 + (day_of_week - d);
-       if (day_in_month <= 0)
-               day_in_month += 7;
-
-       /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
-       date->wDay = day_in_month + (date->wDay - 1) * 7;
-       if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
-               date->wDay -= 7;
-}
-#endif
-
-#ifndef HOST_WIN32
-/*
- * Return's the offset from GMT of a local time.
- * 
- *  tm is a local time
- *  t  is the same local time as seconds.
- */
-static int 
-gmt_offset(struct tm *tm, time_t t)
-{
-#if defined (HAVE_TM_GMTOFF)
-       return tm->tm_gmtoff;
-#else
-       struct tm g;
-       time_t t2;
-       g = *gmtime(&t);
-       g.tm_isdst = tm->tm_isdst;
-       t2 = mktime(&g);
-       return (int)difftime(t, t2);
-#endif
-}
-#endif
-/*
- * This is heavily based on zdump.c from glibc 2.2.
- *
- *  * data[0]:  start of daylight saving time (in DateTime ticks).
- *  * data[1]:  end of daylight saving time (in DateTime ticks).
- *  * data[2]:  utcoffset (in TimeSpan ticks).
- *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
- *  * name[0]:  name of this timezone when not daylight saving.
- *  * name[1]:  name of this timezone when daylight saving.
- *
- *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
- *         the class library allows years between 1 and 9999.
- *
- *  Returns true on success and zero on failure.
- */
-ICALL_EXPORT guint32
-ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
-{
-#ifndef HOST_WIN32
-       MonoDomain *domain = mono_domain_get ();
-       struct tm start, tt;
-       time_t t;
-
-       long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
-       int day, transitioned;
-       char tzone [64];
-
-       gmtoff_st = gmtoff_ds = transitioned = 0;
-
-       MONO_CHECK_ARG_NULL (data, 0);
-       MONO_CHECK_ARG_NULL (names, 0);
-
-       mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
-       mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
-
-       /* 
-        * no info is better than crashing: we'll need our own tz data
-        * to make this work properly, anyway. The range is probably
-        * reduced to 1970 .. 2037 because that is what mktime is
-        * guaranteed to support (we get into an infinite loop
-        * otherwise).
-        */
-
-       memset (&start, 0, sizeof (start));
-
-       start.tm_mday = 1;
-       start.tm_year = year-1900;
-
-       t = mktime (&start);
-
-       if ((year < 1970) || (year > 2037) || (t == -1)) {
-               t = time (NULL);
-               tt = *localtime (&t);
-               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));
-               return 1;
-       }
-
-       gmtoff = gmt_offset (&start, t);
-
-       /* For each day of the year, calculate the tm_gmtoff. */
-       for (day = 0; day < 365 && transitioned < 2; day++) {
-
-               t += 3600*24;
-               tt = *localtime (&t);
-
-        gmtoff_after = gmt_offset(&tt, t);
-
-               /* Daylight saving starts or ends here. */
-               if (gmtoff_after != gmtoff) {
-                       struct tm tt1;
-                       time_t t1;
-
-                       /* Try to find the exact hour when daylight saving starts/ends. */
-                       t1 = t;
-                       do {
-                               t1 -= 3600;
-                               tt1 = *localtime (&t1);
-                       } while (gmt_offset (&tt1, t1) != gmtoff);
-
-                       /* Try to find the exact minute when daylight saving starts/ends. */
-                       do {
-                               t1 += 60;
-                               tt1 = *localtime (&t1);
-                       } while (gmt_offset (&tt1, t1) == gmtoff);
-                       t1+=gmtoff;
-                       strftime (tzone, sizeof (tzone), "%Z", &tt);
-                       
-                       /* Write data, if we're already in daylight saving, we're done. */
-                       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 {
-                               mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
-                               mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
-                               if (gmtoff_ds == 0) {
-                                       gmtoff_st = gmtoff_after;
-                                       gmtoff_ds = gmtoff;
-                               }
-                               transitioned++;
-                       }
-
-                       /* This is only set once when we enter daylight saving. */
-                       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 (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));
-               mono_array_set ((*data), gint64, 0, 0);
-               mono_array_set ((*data), gint64, 1, 0);
-               mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
-               mono_array_set ((*data), gint64, 3, 0);
-       }
-
-       return 1;
-#else
-       MonoDomain *domain = mono_domain_get ();
-       TIME_ZONE_INFORMATION tz_info;
-       FILETIME ft;
-       int i;
-       int err, tz_id;
-
-       tz_id = GetTimeZoneInformation (&tz_info);
-       if (tz_id == TIME_ZONE_ID_INVALID)
-               return 0;
-
-       MONO_CHECK_ARG_NULL (data, 0);
-       MONO_CHECK_ARG_NULL (names, 0);
-
-       mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
-       mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
-
-       for (i = 0; i < 32; ++i)
-               if (!tz_info.DaylightName [i])
-                       break;
-       mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
-       for (i = 0; i < 32; ++i)
-               if (!tz_info.StandardName [i])
-                       break;
-       mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
-
-       if ((year <= 1601) || (year > 30827)) {
-               /*
-                * According to MSDN, the MS time functions can't handle dates outside
-                * this interval.
-                */
-               return 1;
-       }
-
-       /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
-       if (tz_id != TIME_ZONE_ID_UNKNOWN) {
-               tz_info.StandardDate.wYear = year;
-               convert_to_absolute_date(&tz_info.StandardDate);
-               err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
-               //g_assert(err);
-               if (err == 0)
-                       return 0;
-               
-               mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
-               tz_info.DaylightDate.wYear = year;
-               convert_to_absolute_date(&tz_info.DaylightDate);
-               err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
-               //g_assert(err);
-               if (err == 0)
-                       return 0;
-               
-               mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
-       }
-       mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
-       mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
-
-       return 1;
-#endif
-}
-
 /* System.Buffer */
 
 static inline gint32