Skip to content

Instantly share code, notes, and snippets.

@clairernovotny
Created October 15, 2012 22:55
Show Gist options
  • Save clairernovotny/3896181 to your computer and use it in GitHub Desktop.
Save clairernovotny/3896181 to your computer and use it in GitHub Desktop.
TimeZone Conversion for NetCore - Obsolete - Use the WinRTTimeZones Nuget package for the latest
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
// OBSOLETE!!! Use the Nuget WinRTTimeZones package for the latest or
// get the code at https://github.com/onovotny/WinRTTimeZones
namespace TimeZoneUtils
{
public static class Utilities
{
private static DYNAMIC_TIME_ZONE_INFORMATION _eastern;
static Utilities()
{
_eastern = EnumerateSystemTimeZones().First(tz => tz.TimeZoneKeyName == "Eastern Standard Time");
}
public static DateTimeOffset ConvertDateToEastern(DateTimeOffset date)
{
var currentTime = new SYSTEMTIME(date.UtcDateTime);
TIME_ZONE_INFORMATION tzi;
if (SafeNativeMethods.GetTimeZoneInformationForYear(currentTime.Year, ref _eastern, out tzi))
{
SYSTEMTIME local;
if (SafeNativeMethods.SystemTimeToTzSpecificLocalTime(ref tzi, ref currentTime, out local))
{
var dt = new DateTime(local.Year, local.Month, local.Day, local.Hour, local.Minute, local.Second, local.Milliseconds,
DateTimeKind.Unspecified);
// calc offset = local hr/min - current hr/min
var hrs = local.Hour - currentTime.Hour;
var min = local.Minute - currentTime.Minute;
var dto = new DateTimeOffset(dt, new TimeSpan(hrs, min, 0));
return dto;
}
}
var error = Marshal.GetLastWin32Error();
Marshal.ThrowExceptionForHR(error);
return date;
}
internal static IEnumerable<DYNAMIC_TIME_ZONE_INFORMATION> EnumerateSystemTimeZones()
{
var i = 0;
while (true)
{
DYNAMIC_TIME_ZONE_INFORMATION tz;
var result = SafeNativeMethods.EnumDynamicTimeZoneInformation(i++, out tz);
if (result != 0)
yield break;
yield return tz;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct DYNAMIC_TIME_ZONE_INFORMATION
{
[MarshalAs(UnmanagedType.I4)]
public Int32 Bias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string StandardName;
public SYSTEMTIME StandardDate;
[MarshalAs(UnmanagedType.I4)]
public Int32 StandardBias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DaylightName;
public SYSTEMTIME DaylightDate;
[MarshalAs(UnmanagedType.I4)]
public Int32 DaylightBias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string TimeZoneKeyName;
[MarshalAs(UnmanagedType.I1)]
public bool DynamicDaylightTimeDisabled;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SYSTEMTIME
{
[MarshalAs(UnmanagedType.U2)]
public short Year;
[MarshalAs(UnmanagedType.U2)]
public short Month;
[MarshalAs(UnmanagedType.U2)]
public short DayOfWeek;
[MarshalAs(UnmanagedType.U2)]
public short Day;
[MarshalAs(UnmanagedType.U2)]
public short Hour;
[MarshalAs(UnmanagedType.U2)]
public short Minute;
[MarshalAs(UnmanagedType.U2)]
public short Second;
[MarshalAs(UnmanagedType.U2)]
public short Milliseconds;
public SYSTEMTIME(DateTime dt)
{
dt = dt.ToUniversalTime(); // SetSystemTime expects the SYSTEMTIME in UTC
Year = (short)dt.Year;
Month = (short)dt.Month;
DayOfWeek = (short)dt.DayOfWeek;
Day = (short)dt.Day;
Hour = (short)dt.Hour;
Minute = (short)dt.Minute;
Second = (short)dt.Second;
Milliseconds = (short)dt.Millisecond;
}
}
private static class SafeNativeMethods
{
[DllImport("kernel32.dll")]
internal static extern bool SystemTimeToTzSpecificLocalTime([In] ref TIME_ZONE_INFORMATION lpTimeZoneInformation,
[In] ref SYSTEMTIME lpUniversalTime,
out SYSTEMTIME lpLocalTime);
[DllImport("Advapi32.dll")]
internal static extern int EnumDynamicTimeZoneInformation([In] int dwIndex, out DYNAMIC_TIME_ZONE_INFORMATION lpTimeZoneInformation);
[DllImport("kernel32.dll")]
internal static extern bool GetTimeZoneInformationForYear([In] short wYear,
[In] ref DYNAMIC_TIME_ZONE_INFORMATION pdtzi,
out TIME_ZONE_INFORMATION ptzi);
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct TIME_ZONE_INFORMATION
{
[MarshalAs(UnmanagedType.I4)]
public Int32 Bias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string StandardName;
public SYSTEMTIME StandardDate;
[MarshalAs(UnmanagedType.I4)]
public Int32 StandardBias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DaylightName;
public SYSTEMTIME DaylightDate;
[MarshalAs(UnmanagedType.I4)]
public Int32 DaylightBias;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment