mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-01-11 19:44:55 +00:00
feat: Add IcdTimeZoneInfo
This commit is contained in:
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
- Added a method for getting the total number of seconds in a date
|
||||
- Added extensions to raise events with common event args using the data directly
|
||||
- Added property to IcdEnvironment to determine whether SSL communication is enabled
|
||||
- Added IcdTimeZoneInfo, a very light implementation of System.TimeZoneInfo for the .NET Compact Framework
|
||||
|
||||
### Changed
|
||||
- Repeater changed to use configured callbacks instead of a dumb event
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
<None Update="CultureInfo.sqlite">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="TimeZones.sqlite">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -110,6 +110,7 @@
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Compile Include="Extensions\CollectionExtensions.cs" />
|
||||
<Compile Include="TimeZoneInfo\IcdTimeZoneInfo.cs" />
|
||||
<Compile Include="ObfuscationSettings.cs" />
|
||||
<Compile Include="Extensions\BoolExtensions.cs" />
|
||||
<Compile Include="Extensions\ByteExtensions.cs" />
|
||||
@@ -222,6 +223,8 @@
|
||||
<Compile Include="Timers\IcdTimer.cs" />
|
||||
<Compile Include="Timers\Repeater.cs" />
|
||||
<Compile Include="Timers\SafeTimer.cs" />
|
||||
<Compile Include="TimeZoneInfo\IcdTimeZoneInfoAdjustmentRule.cs" />
|
||||
<Compile Include="TimeZoneInfo\IcdTimeZoneInfoTransitionTime.cs" />
|
||||
<Compile Include="TryUtils.cs" />
|
||||
<Compile Include="UriQueryBuilder.cs" />
|
||||
<Compile Include="UriUtils.cs" />
|
||||
@@ -238,6 +241,9 @@
|
||||
<Compile Include="Xml\XmlReaderExtensions.cs" />
|
||||
<Compile Include="Xml\XmlUtils.cs" />
|
||||
<None Include="Properties\ControlSystem.cfg" />
|
||||
<None Include="TimeZones.sqlite">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -40,6 +40,11 @@ namespace ICD.Common.Utils.Sqlite
|
||||
return m_Reader.GetInt32(ordinal);
|
||||
}
|
||||
|
||||
public long GetInt64(int ordinal)
|
||||
{
|
||||
return m_Reader.GetInt64(ordinal);
|
||||
}
|
||||
|
||||
public bool GetBoolean(int ordinal)
|
||||
{
|
||||
return m_Reader.GetBoolean(ordinal);
|
||||
|
||||
455
ICD.Common.Utils/TimeZoneInfo/IcdTimeZoneInfo.cs
Normal file
455
ICD.Common.Utils/TimeZoneInfo/IcdTimeZoneInfo.cs
Normal file
@@ -0,0 +1,455 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
#if SIMPLSHARP
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
#else
|
||||
using System.IO;
|
||||
#endif
|
||||
using ICD.Common.Utils.IO;
|
||||
using ICD.Common.Utils.Sqlite;
|
||||
|
||||
namespace ICD.Common.Utils.TimeZoneInfo
|
||||
{
|
||||
public sealed class IcdTimeZoneInfo
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private const string SQL_LOCAL_DATABASE_FILE = "TimeZones.sqlite";
|
||||
private const string SQL_CONNECTION_STRING_FORMAT =
|
||||
#if SIMPLSHARP
|
||||
"Data Source={0};Version=3;ReadOnly=True";
|
||||
#else
|
||||
"Data Source={0}";
|
||||
#endif
|
||||
|
||||
private static readonly Dictionary<string, IcdTimeZoneInfo> s_Cache;
|
||||
|
||||
private IcdTimeZoneInfoAdjustmentRule[] m_AdjustmentRules;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public string StandardName { get; private set; }
|
||||
|
||||
public TimeSpan BaseUtcOffset { get; private set; }
|
||||
|
||||
public bool SupportsDaylightSavingTime { get; private set; }
|
||||
|
||||
public IcdTimeZoneInfoAdjustmentRule[] GetAdjustmentRules()
|
||||
{
|
||||
return m_AdjustmentRules.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
static IcdTimeZoneInfo()
|
||||
{
|
||||
s_Cache = new Dictionary<string, IcdTimeZoneInfo>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
try
|
||||
{
|
||||
PopulateCache();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
IcdErrorLog.Exception(e, "Error populating IcdTimeZoneInfo cache - {0}", e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static IcdTimeZoneInfo FindSystemTimeZoneById(string timeZoneId)
|
||||
{
|
||||
return s_Cache[timeZoneId];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cache Building
|
||||
|
||||
private static void PopulateCache()
|
||||
{
|
||||
string databasePath = IcdPath.Combine(PathUtils.ProgramPath, SQL_LOCAL_DATABASE_FILE);
|
||||
if (!IcdFile.Exists(databasePath))
|
||||
throw new FileNotFoundException("Failed to find database at path " + databasePath);
|
||||
|
||||
string sqlConnectionString = string.Format(SQL_CONNECTION_STRING_FORMAT, databasePath);
|
||||
|
||||
using (IcdSqliteConnection sQLiteConnection = new IcdSqliteConnection(sqlConnectionString))
|
||||
{
|
||||
sQLiteConnection.Open();
|
||||
|
||||
foreach (IcdTimeZoneInfo info in ReadTimeZoneInfos(sQLiteConnection))
|
||||
s_Cache.Add(info.StandardName, info);
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<IcdTimeZoneInfo> ReadTimeZoneInfos(IcdSqliteConnection sQLiteConnection)
|
||||
{
|
||||
const string command = "select id, name, baseOffsetTicks, hasDstRule from timeZones";
|
||||
|
||||
using (IcdSqliteCommand cmd = new IcdSqliteCommand(command, sQLiteConnection))
|
||||
{
|
||||
using (IcdSqliteDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
int id = reader.GetInt32(0);
|
||||
string name = reader.GetString(1);
|
||||
long offset = reader.GetInt64(2);
|
||||
bool hasRule = reader.GetBoolean(3);
|
||||
|
||||
IcdTimeZoneInfoAdjustmentRule[] adjustmentRules = LoadAdjustmentRules(id, sQLiteConnection).ToArray();
|
||||
|
||||
IcdTimeZoneInfo info = new IcdTimeZoneInfo
|
||||
{
|
||||
StandardName = name,
|
||||
BaseUtcOffset = TimeSpan.FromTicks(offset),
|
||||
SupportsDaylightSavingTime = hasRule,
|
||||
m_AdjustmentRules = adjustmentRules
|
||||
};
|
||||
|
||||
yield return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<IcdTimeZoneInfoAdjustmentRule> LoadAdjustmentRules(int timeZoneId, IcdSqliteConnection sQLiteConnection)
|
||||
{
|
||||
string command = string.Format("select id, timeZone, deltaTicks, ruleStart, ruleEnd from rules where timeZone = {0}", timeZoneId);
|
||||
|
||||
using (IcdSqliteCommand cmd = new IcdSqliteCommand(command, sQLiteConnection))
|
||||
{
|
||||
using (IcdSqliteDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
int id = reader.GetInt32(0);
|
||||
long delta = reader.GetInt64(2);
|
||||
string ruleStart = reader.GetString(3);
|
||||
string ruleEnd = reader.GetString(4);
|
||||
IcdTimeZoneInfoTransitionTime transitionTimeStart = LoadTransitionTimeStart(id, sQLiteConnection);
|
||||
IcdTimeZoneInfoTransitionTime transitionTimeEnd = LoadTransitionTimeEnd(id, sQLiteConnection);
|
||||
|
||||
IcdTimeZoneInfoAdjustmentRule rule = new IcdTimeZoneInfoAdjustmentRule
|
||||
{
|
||||
DaylightDelta = TimeSpan.FromTicks(delta),
|
||||
DateStart = DateTime.Parse(ruleStart),
|
||||
DateEnd = DateTime.Parse(ruleEnd),
|
||||
DaylightTransitionStart = transitionTimeStart,
|
||||
DaylightTransitionEnd = transitionTimeEnd
|
||||
};
|
||||
|
||||
yield return rule;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IcdTimeZoneInfoTransitionTime LoadTransitionTimeStart(int ruleId, IcdSqliteConnection sQLiteConnection)
|
||||
{
|
||||
string command =
|
||||
string.Format("select rule, isTransitionStart, isFixedRule, timeOfDay, dayOfWeek, day, week, month " +
|
||||
"from ruleTransitions " +
|
||||
"where rule = {0} and isTransitionStart = true",
|
||||
ruleId);
|
||||
|
||||
using (IcdSqliteCommand cmd = new IcdSqliteCommand(command, sQLiteConnection))
|
||||
{
|
||||
using (IcdSqliteDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
bool isFixed = reader.GetBoolean(2);
|
||||
string timeOfDay = reader.GetString(3);
|
||||
int dayOfWeek = reader.GetInt32(4);
|
||||
int day = reader.GetInt32(5);
|
||||
int week = reader.GetInt32(6);
|
||||
int month = reader.GetInt32(7);
|
||||
|
||||
return new IcdTimeZoneInfoTransitionTime
|
||||
{
|
||||
IsFixedDateRule = isFixed,
|
||||
TimeOfDay = DateTime.Parse(timeOfDay),
|
||||
DayOfWeek = (DayOfWeek)dayOfWeek,
|
||||
Day = day,
|
||||
Week = week,
|
||||
Month = month
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException("ruleId", "There was no TransitionTime for the specified rule");
|
||||
}
|
||||
|
||||
private static IcdTimeZoneInfoTransitionTime LoadTransitionTimeEnd(int ruleId, IcdSqliteConnection sQLiteConnection)
|
||||
{
|
||||
string command =
|
||||
string.Format("select rule, isTransitionStart, isFixedRule, timeOfDay, dayOfWeek, day, week, month " +
|
||||
"from ruleTransitions " +
|
||||
"where rule = {0} and isTransitionStart = false",
|
||||
ruleId);
|
||||
|
||||
using (IcdSqliteCommand cmd = new IcdSqliteCommand(command, sQLiteConnection))
|
||||
{
|
||||
using (IcdSqliteDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
bool isFixed = reader.GetBoolean(2);
|
||||
string timeOfDay = reader.GetString(3);
|
||||
int dayOfWeek = reader.GetInt32(4);
|
||||
int day = reader.GetInt32(5);
|
||||
int week = reader.GetInt32(6);
|
||||
int month = reader.GetInt32(7);
|
||||
|
||||
return new IcdTimeZoneInfoTransitionTime
|
||||
{
|
||||
IsFixedDateRule = isFixed,
|
||||
TimeOfDay = DateTime.Parse(timeOfDay),
|
||||
DayOfWeek = (DayOfWeek)dayOfWeek,
|
||||
Day = day,
|
||||
Week = week,
|
||||
Month = month
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException("ruleId", "There was no TransitionTime for the specified rule");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public DateTime ConvertToUtc(DateTime time)
|
||||
{
|
||||
return time.Kind == DateTimeKind.Utc ? time : ConvertToUtc(time, this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private static DateTime ConvertToUtc(DateTime dateTime, IcdTimeZoneInfo sourceTimeZone)
|
||||
{
|
||||
if (sourceTimeZone == null)
|
||||
throw new ArgumentNullException("sourceTimeZone");
|
||||
|
||||
IcdTimeZoneInfoAdjustmentRule sourceRule = sourceTimeZone.GetAdjustmentRuleForTime(dateTime);
|
||||
TimeSpan sourceOffset = sourceTimeZone.BaseUtcOffset;
|
||||
|
||||
if (sourceRule != null)
|
||||
{
|
||||
if (sourceTimeZone.SupportsDaylightSavingTime)
|
||||
{
|
||||
DaylightTime sourceDaylightTime = GetDaylightTime(dateTime.Year, sourceRule);
|
||||
|
||||
bool sourceIsDaylightSavings = GetIsDaylightSavings(dateTime, sourceRule, sourceDaylightTime);
|
||||
|
||||
// adjust the sourceOffset according to the Adjustment Rule / Daylight Saving Rule
|
||||
sourceOffset += (sourceIsDaylightSavings ? sourceRule.DaylightDelta : TimeSpan.Zero
|
||||
/*FUTURE: sourceRule.StandardDelta*/);
|
||||
}
|
||||
}
|
||||
|
||||
const DateTimeKind targetKind = DateTimeKind.Utc;
|
||||
|
||||
long utcTicks = dateTime.Ticks - sourceOffset.Ticks;
|
||||
return new DateTime(utcTicks, targetKind);
|
||||
}
|
||||
|
||||
// assumes dateTime is in the current time zone's time
|
||||
private IcdTimeZoneInfoAdjustmentRule GetAdjustmentRuleForTime(DateTime dateTime)
|
||||
{
|
||||
if (m_AdjustmentRules == null || m_AdjustmentRules.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only check the whole-date portion of the dateTime -
|
||||
// This is because the AdjustmentRule DateStart & DateEnd are stored as
|
||||
// Date-only values {4/2/2006 - 10/28/2006} but actually represent the
|
||||
// time span {4/2/2006@00:00:00.00000 - 10/28/2006@23:59:59.99999}
|
||||
DateTime date = dateTime.Date;
|
||||
|
||||
return m_AdjustmentRules.FirstOrDefault(t => t.DateStart <= date && t.DateEnd >= date);
|
||||
}
|
||||
|
||||
//
|
||||
// GetDaylightTime -
|
||||
//
|
||||
// Helper function that returns a DaylightTime from a year and AdjustmentRule
|
||||
//
|
||||
private static DaylightTime GetDaylightTime(int year, IcdTimeZoneInfoAdjustmentRule rule)
|
||||
{
|
||||
TimeSpan delta = rule.DaylightDelta;
|
||||
DateTime startTime = TransitionTimeToDateTime(year, rule.DaylightTransitionStart);
|
||||
DateTime endTime = TransitionTimeToDateTime(year, rule.DaylightTransitionEnd);
|
||||
return new DaylightTime(startTime, endTime, delta);
|
||||
}
|
||||
|
||||
//
|
||||
// TransitionTimeToDateTime -
|
||||
//
|
||||
// Helper function that converts a year and TransitionTime into a DateTime
|
||||
//
|
||||
private static DateTime TransitionTimeToDateTime(int year, IcdTimeZoneInfoTransitionTime transitionTime)
|
||||
{
|
||||
DateTime value;
|
||||
DateTime timeOfDay = transitionTime.TimeOfDay;
|
||||
|
||||
if (transitionTime.IsFixedDateRule)
|
||||
{
|
||||
// create a DateTime from the passed in year and the properties on the transitionTime
|
||||
|
||||
// if the day is out of range for the month then use the last day of the month
|
||||
int day = DateTime.DaysInMonth(year, transitionTime.Month);
|
||||
|
||||
value = new DateTime(year, transitionTime.Month, (day < transitionTime.Day) ? day : transitionTime.Day,
|
||||
timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transitionTime.Week <= 4)
|
||||
{
|
||||
//
|
||||
// Get the (transitionTime.Week)th Sunday.
|
||||
//
|
||||
value = new DateTime(year, transitionTime.Month, 1,
|
||||
timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
|
||||
|
||||
int dayOfWeek = (int)value.DayOfWeek;
|
||||
int delta = (int)transitionTime.DayOfWeek - dayOfWeek;
|
||||
if (delta < 0)
|
||||
{
|
||||
delta += 7;
|
||||
}
|
||||
delta += 7 * (transitionTime.Week - 1);
|
||||
|
||||
if (delta > 0)
|
||||
{
|
||||
value = value.AddDays(delta);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// If TransitionWeek is greater than 4, we will get the last week.
|
||||
//
|
||||
Int32 daysInMonth = DateTime.DaysInMonth(year, transitionTime.Month);
|
||||
value = new DateTime(year, transitionTime.Month, daysInMonth,
|
||||
timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
|
||||
|
||||
// This is the day of week for the last day of the month.
|
||||
int dayOfWeek = (int)value.DayOfWeek;
|
||||
int delta = dayOfWeek - (int)transitionTime.DayOfWeek;
|
||||
if (delta < 0)
|
||||
{
|
||||
delta += 7;
|
||||
}
|
||||
|
||||
if (delta > 0)
|
||||
{
|
||||
value = value.AddDays(-delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
//
|
||||
// GetIsDaylightSavings -
|
||||
//
|
||||
// Helper function that checks if a given dateTime is in Daylight Saving Time (DST)
|
||||
// This function assumes the dateTime and AdjustmentRule are both in the same time zone
|
||||
//
|
||||
static private bool GetIsDaylightSavings(DateTime time, IcdTimeZoneInfoAdjustmentRule rule, DaylightTime daylightTime)
|
||||
{
|
||||
if (rule == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DateTime startTime;
|
||||
DateTime endTime;
|
||||
|
||||
if (time.Kind == DateTimeKind.Local)
|
||||
{
|
||||
// startTime and endTime represent the period from either the start of DST to the end and ***includes*** the
|
||||
// potentially overlapped times
|
||||
startTime = rule.IsStartDateMarkerForBeginningOfYear() ? new DateTime(daylightTime.Start.Year, 1, 1, 0, 0, 0) : daylightTime.Start + daylightTime.Delta;
|
||||
endTime = rule.IsEndDateMarkerForEndOfYear() ? new DateTime(daylightTime.End.Year + 1, 1, 1, 0, 0, 0).AddTicks(-1) : daylightTime.End;
|
||||
}
|
||||
else
|
||||
{
|
||||
// startTime and endTime represent the period from either the start of DST to the end and
|
||||
// ***does not include*** the potentially overlapped times
|
||||
//
|
||||
// -=-=-=-=-=- Pacific Standard Time -=-=-=-=-=-=-
|
||||
// April 2, 2006 October 29, 2006
|
||||
// 2AM 3AM 1AM 2AM
|
||||
// | +1 hr | | -1 hr |
|
||||
// | <invalid time> | | <ambiguous time> |
|
||||
// [========== DST ========>)
|
||||
//
|
||||
// -=-=-=-=-=- Some Weird Time Zone -=-=-=-=-=-=-
|
||||
// April 2, 2006 October 29, 2006
|
||||
// 1AM 2AM 2AM 3AM
|
||||
// | -1 hr | | +1 hr |
|
||||
// | <ambiguous time> | | <invalid time> |
|
||||
// [======== DST ========>)
|
||||
//
|
||||
bool invalidAtStart = rule.DaylightDelta > TimeSpan.Zero;
|
||||
startTime = rule.IsStartDateMarkerForBeginningOfYear() ? new DateTime(daylightTime.Start.Year, 1, 1, 0, 0, 0) : daylightTime.Start + (invalidAtStart ? rule.DaylightDelta : TimeSpan.Zero); /* FUTURE: - rule.StandardDelta; */
|
||||
endTime = rule.IsEndDateMarkerForEndOfYear() ? new DateTime(daylightTime.End.Year + 1, 1, 1, 0, 0, 0).AddTicks(-1) : daylightTime.End + (invalidAtStart ? -rule.DaylightDelta : TimeSpan.Zero);
|
||||
}
|
||||
|
||||
return CheckIsDst(startTime, time, endTime, false);
|
||||
}
|
||||
|
||||
private static bool CheckIsDst(DateTime startTime, DateTime time, DateTime endTime, bool ignoreYearAdjustment)
|
||||
{
|
||||
bool isDst;
|
||||
|
||||
if (!ignoreYearAdjustment)
|
||||
{
|
||||
int startTimeYear = startTime.Year;
|
||||
int endTimeYear = endTime.Year;
|
||||
|
||||
if (startTimeYear != endTimeYear)
|
||||
{
|
||||
endTime = endTime.AddYears(startTimeYear - endTimeYear);
|
||||
}
|
||||
|
||||
int timeYear = time.Year;
|
||||
|
||||
if (startTimeYear != timeYear)
|
||||
{
|
||||
time = time.AddYears(startTimeYear - timeYear);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
// In northern hemisphere, the daylight saving time starts in the middle of the year.
|
||||
isDst = (time >= startTime && time < endTime);
|
||||
}
|
||||
return isDst;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
|
||||
namespace ICD.Common.Utils.TimeZoneInfo
|
||||
{
|
||||
public sealed class IcdTimeZoneInfoAdjustmentRule
|
||||
{
|
||||
public DateTime DateStart { get; set; }
|
||||
|
||||
public DateTime DateEnd { get; set; }
|
||||
|
||||
public TimeSpan DaylightDelta { get; set; }
|
||||
|
||||
public IcdTimeZoneInfoTransitionTime DaylightTransitionStart { get; set; }
|
||||
|
||||
public IcdTimeZoneInfoTransitionTime DaylightTransitionEnd { get; set; }
|
||||
|
||||
// ----- SECTION: internal utility methods ----------------*
|
||||
|
||||
//
|
||||
// When Windows sets the daylight transition start Jan 1st at 12:00 AM, it means the year starts with the daylight saving on.
|
||||
// We have to special case this value and not adjust it when checking if any date is in the daylight saving period.
|
||||
//
|
||||
public bool IsStartDateMarkerForBeginningOfYear()
|
||||
{
|
||||
return DaylightTransitionStart.Month == 1 && DaylightTransitionStart.Day == 1 && DaylightTransitionStart.TimeOfDay.Hour == 0 &&
|
||||
DaylightTransitionStart.TimeOfDay.Minute == 0 && DaylightTransitionStart.TimeOfDay.Second == 0 &&
|
||||
DateStart.Year == DateEnd.Year;
|
||||
}
|
||||
|
||||
//
|
||||
// When Windows sets the daylight transition end Jan 1st at 12:00 AM, it means the year ends with the daylight saving on.
|
||||
// We have to special case this value and not adjust it when checking if any date is in the daylight saving period.
|
||||
//
|
||||
public bool IsEndDateMarkerForEndOfYear()
|
||||
{
|
||||
return DaylightTransitionEnd.Month == 1 && DaylightTransitionEnd.Day == 1 && DaylightTransitionEnd.TimeOfDay.Hour == 0 &&
|
||||
DaylightTransitionEnd.TimeOfDay.Minute == 0 && DaylightTransitionEnd.TimeOfDay.Second == 0 &&
|
||||
DateStart.Year == DateEnd.Year;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace ICD.Common.Utils.TimeZoneInfo
|
||||
{
|
||||
public sealed class IcdTimeZoneInfoTransitionTime
|
||||
{
|
||||
public bool IsFixedDateRule { get; set; }
|
||||
|
||||
public DateTime TimeOfDay { get; set; }
|
||||
|
||||
public DayOfWeek DayOfWeek { get; set; }
|
||||
|
||||
public int Day { get; set; }
|
||||
|
||||
public int Week { get; set; }
|
||||
|
||||
public int Month { get; set; }
|
||||
}
|
||||
}
|
||||
BIN
ICD.Common.Utils/TimeZones.sqlite
Normal file
BIN
ICD.Common.Utils/TimeZones.sqlite
Normal file
Binary file not shown.
Reference in New Issue
Block a user