//
// Author: Duncan Mak (duncan@ximian.com)
// Ajay Kumar Dwivedi (adwiv@yahoo.com)
+// Martin Baulig (martin@gnome.org)
//
// (C) Ximian, Inc.
//
using System.Collections;
using System.Globalization;
+using System.Runtime.CompilerServices;
namespace System {
public virtual bool IsDaylightSavingTime (DateTime time)
{
- int currentYear = CultureInfo.CurrentCulture.Calendar.GetYear (time);
- DaylightTime daylight = GetDaylightChanges (currentYear);
-
- return IsDaylightSavingTime (time, daylight);
+ return IsDaylightSavingTime (time, GetDaylightChanges (time.Year));
}
- public virtual bool IsDaylightSavingTime (DateTime time, DaylightTime daylightTimes)
- {
+ public static bool IsDaylightSavingTime (DateTime time, DaylightTime daylightTimes)
+ {
if (daylightTimes == null)
- throw new ArgumentNullException ("daylightTimes is null.");
-
- if (daylightTimes.Delta == TimeSpan.Zero)
- return false;
-
- if ((daylightTimes.Start <= time) && (time < daylightTimes.End))
- return true;
- else // time doesn't not fall in the span of daylightTimes
- return false;
- }
+ throw new ArgumentNullException ("daylightTimes");
+
+ // If Start == End, then DST is off
+ if (daylightTimes.Start.Ticks == daylightTimes.End.Ticks)
+ return false;
+
+ //We are in the northern hemisphere.
+ if (daylightTimes.Start.Ticks < daylightTimes.End.Ticks) {
+ if (daylightTimes.Start.Ticks < time.Ticks
+ && daylightTimes.End.Ticks > time.Ticks)
+ return true; // time lies between Start and End
+
+ } else { // We are in the southern hemisphere.
+ if (time.Year == daylightTimes.Start.Year && time.Year == daylightTimes.End.Year)
+ if (time.Ticks < daylightTimes.End.Ticks
+ || time.Ticks > daylightTimes.Start.Ticks)
+ return true; // time is less than End OR more than Start
+ }
+ return false;
+ }
+
public virtual DateTime ToLocalTime (DateTime time)
{
return time + GetUtcOffset (time);
// the offset when daylightsaving is on.
private static TimeSpan utcOffsetWithDLS;
+ internal enum TimeZoneData {
+ DaylightSavingStartIdx,
+ DaylightSavingEndIdx,
+ UtcOffsetIdx,
+ AdditionalDaylightOffsetIdx
+ };
+
+ internal enum TimeZoneNames {
+ StandardNameIdx,
+ DaylightNameIdx
+ };
+
+ // Internal method to get timezone data.
+ // 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.
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool GetTimeZoneData (int year,
+ out Int64[] data,
+ out string[] names);
+
// Constructor
- [MonoTODO ("Add internal calls to initialize the fields")]
internal CurrentTimeZone ()
: base ()
{
+ Int64[] data;
+ string[] names;
+
+ DateTime now = new DateTime(DateTime.GetNow ());
+ if (!GetTimeZoneData (now.Year, out data, out names))
+ throw new NotSupportedException (Locale.GetText ("Can't get timezone name"));
+
+ standardName = Locale.GetText (names[(int)TimeZoneNames.StandardNameIdx]);
+ daylightName = Locale.GetText (names[(int)TimeZoneNames.DaylightNameIdx]);
+
+ utcOffsetWithOutDLS = new TimeSpan (data[(int)TimeZoneData.UtcOffsetIdx]);
+ utcOffsetWithDLS = new TimeSpan (data[(int)TimeZoneData.UtcOffsetIdx] + data[(int)TimeZoneData.AdditionalDaylightOffsetIdx]);
}
// Properties
throw new ArgumentOutOfRangeException (year + " is not in a range between 1 and 9999.");
if (daylightCache [year] == null) {
- //TODO: do something and put the DaylightTime corresponding to the time in cache.
- DaylightTime dlt = new DaylightTime (new DateTime (0),
- new DateTime (0), new TimeSpan (0));
+ Int64[] data;
+ string[] names;
+
+ if (!GetTimeZoneData (year, out data, out names))
+ throw new ArgumentException (Locale.GetText ("Can't get timezone data for " + year));
+
+ DaylightTime dlt = new DaylightTime (new DateTime (data[(int)TimeZoneData.DaylightSavingStartIdx]),
+ new DateTime (data[(int)TimeZoneData.DaylightSavingEndIdx]),
+ new TimeSpan (data[(int)TimeZoneData.AdditionalDaylightOffsetIdx]));
daylightCache.Add (year, dlt);
}
return (DaylightTime) daylightCache [year];
}
- public override TimeSpan GetUtcOffset(DateTime time)
+ public override TimeSpan GetUtcOffset (DateTime time)
{
if (IsDaylightSavingTime (time))
return utcOffsetWithDLS;