summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/CurrentTimeZone.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/CurrentTimeZone.cs')
-rw-r--r--src/mscorlib/src/System/CurrentTimeZone.cs276
1 files changed, 90 insertions, 186 deletions
diff --git a/src/mscorlib/src/System/CurrentTimeZone.cs b/src/mscorlib/src/System/CurrentTimeZone.cs
index f015c05b33..804bbcccc4 100644
--- a/src/mscorlib/src/System/CurrentTimeZone.cs
+++ b/src/mscorlib/src/System/CurrentTimeZone.cs
@@ -21,36 +21,18 @@ namespace System {
using System;
using System.Diagnostics.Contracts;
using System.Text;
- using System.Threading;
using System.Collections;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
- //
- // Currently, this is the only supported timezone.
- // The values of the timezone is from the current system timezone setting in the
- // control panel.
- //
-#if FEATURE_CORECLR
[Obsolete("System.CurrentSystemTimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo.Local instead.")]
-#endif
[Serializable]
- internal class CurrentSystemTimeZone : TimeZone {
- // <BUGBUG>BUGBUG :
- // One problem is when user changes the current timezone. We
- // are not able to update currentStandardName/currentDaylightName/
- // currentDaylightChanges.
- // We need WM_TIMECHANGE to do this or use
- // RegNotifyChangeKeyValue() to monitor </BUGBUG>
- //
- private const long TicksPerMillisecond = 10000;
- private const long TicksPerSecond = TicksPerMillisecond * 1000;
- private const long TicksPerMinute = TicksPerSecond * 60;
-
+ internal class CurrentSystemTimeZone : TimeZone
+ {
// The per-year information is cached in in this instance value. As a result it can
// be cleaned up by CultureInfo.ClearCachedData, which will clear the instance of this object
- private Hashtable m_CachedDaylightChanges = new Hashtable();
+ private readonly Hashtable m_CachedDaylightChanges = new Hashtable();
// Standard offset in ticks to the Universal time if
// no daylight saving is in used.
@@ -60,43 +42,40 @@ namespace System {
private String m_standardName;
private String m_daylightName;
- [System.Security.SecuritySafeCritical] // auto-generated
- internal CurrentSystemTimeZone() {
- m_ticksOffset = nativeGetTimeZoneMinuteOffset() * TicksPerMinute;
- m_standardName = null;
- m_daylightName = null;
+ internal CurrentSystemTimeZone()
+ {
+ TimeZoneInfo local = TimeZoneInfo.Local;
+
+ m_ticksOffset = local.BaseUtcOffset.Ticks;
+ m_standardName = local.StandardName;
+ m_daylightName = local.DaylightName;
}
- public override String StandardName {
- [System.Security.SecuritySafeCritical] // auto-generated
- get {
- if (m_standardName == null) {
- m_standardName = nativeGetStandardName();
- }
- return (m_standardName);
+ public override String StandardName
+ {
+ get
+ {
+ return m_standardName;
}
}
- public override String DaylightName {
- [System.Security.SecuritySafeCritical] // auto-generated
- get {
- if (m_daylightName == null) {
- m_daylightName = nativeGetDaylightName();
- if (m_daylightName == null) {
- m_daylightName = this.StandardName;
- }
- }
- return (m_daylightName);
+ public override String DaylightName
+ {
+ get
+ {
+ return m_daylightName;
}
}
- internal long GetUtcOffsetFromUniversalTime(DateTime time, ref Boolean isAmbiguousLocalDst) {
+ internal long GetUtcOffsetFromUniversalTime(DateTime time, ref Boolean isAmbiguousLocalDst)
+ {
// Get the daylight changes for the year of the specified time.
TimeSpan offset = new TimeSpan(m_ticksOffset);
DaylightTime daylightTime = GetDaylightChanges(time.Year);
isAmbiguousLocalDst= false;
- if (daylightTime == null || daylightTime.Delta.Ticks == 0) {
+ if (daylightTime == null || daylightTime.Delta.Ticks == 0)
+ {
return offset.Ticks;
}
@@ -107,119 +86,109 @@ namespace System {
DateTime endTime = daylightTime.End - offset - daylightTime.Delta;
DateTime ambiguousStart;
DateTime ambiguousEnd;
- if (daylightTime.Delta.Ticks > 0) {
+
+ if (daylightTime.Delta.Ticks > 0)
+ {
ambiguousStart = endTime - daylightTime.Delta;
ambiguousEnd = endTime;
- } else {
+ }
+ else
+ {
ambiguousStart = startTime;
ambiguousEnd = startTime - daylightTime.Delta;
}
Boolean isDst = false;
- if (startTime > endTime) {
+ if (startTime > endTime)
+ {
// In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year.
// Note, the summer in the southern hemisphere begins late in the year.
isDst = (time < endTime || time >= startTime);
}
- else {
+ else
+ {
// In northern hemisphere, the daylight saving time starts in the middle of the year.
- isDst = (time>=startTime && time<endTime);
+ isDst = (time >= startTime && time < endTime);
}
- if (isDst) {
+
+ if (isDst)
+ {
offset += daylightTime.Delta;
// See if the resulting local time becomes ambiguous. This must be captured here or the
// DateTime will not be able to round-trip back to UTC accurately.
- if (time >= ambiguousStart && time < ambiguousEnd ) {
+ if (time >= ambiguousStart && time < ambiguousEnd )
+ {
isAmbiguousLocalDst = true;
}
}
return offset.Ticks;
}
- public override DateTime ToLocalTime(DateTime time) {
- if (time.Kind == DateTimeKind.Local) {
+ public override DateTime ToLocalTime(DateTime time)
+ {
+ if (time.Kind == DateTimeKind.Local)
+ {
return time;
}
Boolean isAmbiguousLocalDst = false;
Int64 offset = GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
long tick = time.Ticks + offset;
- if (tick>DateTime.MaxTicks) {
+ if (tick > DateTime.MaxTicks)
+ {
return new DateTime(DateTime.MaxTicks, DateTimeKind.Local);
}
- if (tick<DateTime.MinTicks) {
+ if (tick < DateTime.MinTicks)
+ {
return new DateTime(DateTime.MinTicks, DateTimeKind.Local);
}
- return new DateTime(tick, DateTimeKind.Local, isAmbiguousLocalDst);
- }
-
- // Private object for locking instead of locking on a public type for SQL reliability work.
- private static Object s_InternalSyncObject;
- private static Object InternalSyncObject {
- get {
- if (s_InternalSyncObject == null) {
- Object o = new Object();
- Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
- }
- return s_InternalSyncObject;
- }
+ return new DateTime(tick, DateTimeKind.Local, isAmbiguousLocalDst);
}
-
- [System.Security.SecuritySafeCritical] // auto-generated
- public override DaylightTime GetDaylightChanges(int year) {
- if (year < 1 || year > 9999) {
- throw new ArgumentOutOfRangeException("year", Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 9999));
+ public override DaylightTime GetDaylightChanges(int year)
+ {
+ if (year < 1 || year > 9999)
+ {
+ throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 9999));
}
Contract.EndContractBlock();
- Object objYear = (Object)year;
-
- if (!m_CachedDaylightChanges.Contains(objYear)) {
- lock (InternalSyncObject) {
+ Object objYear = (Object) year;
- if (!m_CachedDaylightChanges.Contains(objYear)) {
+ if (!m_CachedDaylightChanges.Contains(objYear))
+ {
+ DaylightTime currentDaylightChanges = null;
- //
- // rawData is an array of 17 short (16 bit) numbers.
- // The first 8 numbers contains the
- // year/month/day/dayOfWeek/hour/minute/second/millisecond for the starting time of daylight saving time.
- // The next 8 numbers contains the
- // year/month/day/dayOfWeek/hour/minute/second/millisecond for the ending time of daylight saving time.
- // The last short number is the delta to the standard offset in minutes.
- //
- short[] rawData = nativeGetDaylightChanges(year);
+ if (TimeZoneInfo.Local.SupportsDaylightSavingTime)
+ {
+ DateTime start;
+ DateTime end;
+ TimeSpan delta;
- if (rawData == null) {
- //
- // If rawData is null, it means that daylight saving time is not used
- // in this timezone. So keep currentDaylightChanges as the empty array.
- //
- m_CachedDaylightChanges.Add(objYear, new DaylightTime(DateTime.MinValue, DateTime.MinValue, TimeSpan.Zero));
- } else {
- DateTime start;
- DateTime end;
- TimeSpan delta;
+ foreach (var rule in TimeZoneInfo.Local.GetAdjustmentRules())
+ {
+ if (rule.DateStart.Year <= year && rule.DateEnd.Year >= year && rule.DaylightDelta != TimeSpan.Zero)
+ {
+ start = TimeZoneInfo.TransitionTimeToDateTime(year, rule.DaylightTransitionStart);
+ end = TimeZoneInfo.TransitionTimeToDateTime(year, rule.DaylightTransitionEnd);
+ delta = rule.DaylightDelta;
- //
- // Store the start of daylight saving time.
- //
-
- start = GetDayOfWeek(year, (rawData[0] != 0), rawData[1], rawData[2],
- rawData[3],
- rawData[4], rawData[5], rawData[6], rawData[7]);
+ currentDaylightChanges = new DaylightTime(start, end, delta);
+ break;
+ }
+ }
+ }
- //
- // Store the end of daylight saving time.
- //
- end = GetDayOfWeek(year, (rawData[8] != 0), rawData[9], rawData[10],
- rawData[11],
- rawData[12], rawData[13], rawData[14], rawData[15]);
+ if (currentDaylightChanges == null)
+ {
+ currentDaylightChanges = new DaylightTime(DateTime.MinValue, DateTime.MinValue, TimeSpan.Zero);
+ }
- delta = new TimeSpan(rawData[16] * TicksPerMinute);
- DaylightTime currentDaylightChanges = new DaylightTime(start, end, delta);
- m_CachedDaylightChanges.Add(objYear, currentDaylightChanges);
- }
+ lock (m_CachedDaylightChanges)
+ {
+ if (!m_CachedDaylightChanges.Contains(objYear))
+ {
+ m_CachedDaylightChanges.Add(objYear, currentDaylightChanges);
}
}
}
@@ -229,82 +198,17 @@ namespace System {
return result;
}
- public override TimeSpan GetUtcOffset(DateTime time) {
- if (time.Kind == DateTimeKind.Utc) {
+ public override TimeSpan GetUtcOffset(DateTime time)
+ {
+ if (time.Kind == DateTimeKind.Utc)
+ {
return TimeSpan.Zero;
}
- else {
+ else
+ {
return new TimeSpan(TimeZone.CalculateUtcOffset(time, GetDaylightChanges(time.Year)).Ticks + m_ticksOffset);
}
}
- //
- // Return the (numberOfSunday)th day of week in a particular year/month.
- //
- private static DateTime GetDayOfWeek(int year, bool fixedDate, int month, int targetDayOfWeek, int numberOfSunday, int hour, int minute, int second, int millisecond) {
- DateTime time;
-
- if (fixedDate) {
- //
- // Create a Fixed-Date transition time based on the supplied parameters
- // For Fixed-Dated transition times, the 'numberOfSunday' parameter actually
- // represents the day of the month.
- //
-
- // if the day is out of range for the month then use the last day of the month
- int day = DateTime.DaysInMonth(year, month);
-
- time = new DateTime(year, month, (day < numberOfSunday) ? day : numberOfSunday,
- hour, minute, second, millisecond, DateTimeKind.Local);
- }
- else if (numberOfSunday <= 4) {
- //
- // Get the (numberOfSunday)th Sunday.
- //
-
- time = new DateTime(year, month, 1, hour, minute, second, millisecond, DateTimeKind.Local);
-
- int dayOfWeek = (int)time.DayOfWeek;
- int delta = targetDayOfWeek - dayOfWeek;
- if (delta < 0) {
- delta += 7;
- }
- delta += 7 * (numberOfSunday - 1);
-
- if (delta > 0) {
- time = time.AddDays(delta);
- }
- } else {
- //
- // If numberOfSunday is greater than 4, we will get the last sunday.
- //
- Calendar cal = GregorianCalendar.GetDefaultInstance();
- time = new DateTime(year, month, cal.GetDaysInMonth(year, month), hour, minute, second, millisecond, DateTimeKind.Local);
- // This is the day of week for the last day of the month.
- int dayOfWeek = (int)time.DayOfWeek;
- int delta = dayOfWeek - targetDayOfWeek;
- if (delta < 0) {
- delta += 7;
- }
-
- if (delta > 0) {
- time = time.AddDays(-delta);
- }
- }
- return (time);
- }
-
- [System.Security.SecurityCritical] // auto-generated
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal extern static int nativeGetTimeZoneMinuteOffset();
- [System.Security.SecurityCritical] // auto-generated
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal extern static String nativeGetDaylightName();
- [System.Security.SecurityCritical] // auto-generated
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal extern static String nativeGetStandardName();
- [System.Security.SecurityCritical] // auto-generated
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal extern static short[] nativeGetDaylightChanges(int year);
} // class CurrentSystemTimeZone
}