|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Dealing with TimezonesIn .Net 2.0, I can get the standard name of the current timezone by:
System.TimeZone.CurrentTimeZone.StandardName The problem I'm having is that I have datetimes that are serialized as a UTC time, with a named timezone. I keep looking for a way to say: System.TimeZone tz = new TimeZone("PST"); tz.ConvertToLocalTime(utcTime); Problem is there doesn't seem to way to do this. Anyone got any suggesting for dealing with TimeZones? Does this solve your porblem:
System.TimeZone tz = new TimeZone("PST"); tz.ToLocalTime(utcTime); Pål wrote:
> Does this solve your porblem: This won't work:> > System.TimeZone tz = new TimeZone("PST"); > tz.ToLocalTime(utcTime); 1. There's no TimeZone constructor that takes a timezone identifier. 2. System.TimeZone is abstract. Interestingly, in the java support libraries for J#, there's another TimeZone class which does have a constructor taking a time zone identifier. It doesn't provide a toLocalTime() function, but it does expose the timezone's offset from GMT as a property. -cd "Pål" <pal.***@home.no> wrote: That sure does solve my problem.> Does this solve your porblem: > > System.TimeZone tz = new TimeZone("PST"); > tz.ToLocalTime(utcTime); .... only problem is that it doesn't work. TimeZone is an abstract class. Never could figure out why they did not include such a needed thing. Until
then, here is a class I did that will convert between timezones, etc. It uses standard names (long) because that is how windows indexes them. If you can figure out the "standard" 3 char abbrev for each timezone and post here or send to me, I can update to also take abbreviations. But the standard names are pretty easy to work with also as shown below. Sample -------------------------- private void button4_Click(object sender, EventArgs e) { // List all supported timezones (w/ standard names). foreach (TimeZoneInformation tz in TimeZoneInformation.TimeZones) { Console.WriteLine(tz.ToString()); } Console.WriteLine(); // Convert a utc to a local time in the supplied time zone respecting daylight savings of target timezone. Console.WriteLine("EST:{0}", DateTime.Now); DateTime pst = TimeZoneInformation.ToLocalTime(DateTime.UtcNow, "pacific standard time"); Console.WriteLine("PST:{0}", pst.ToString()); Console.WriteLine("\nCurrent TimeZone:"); TimeZoneInformation tzi = TimeZoneInformation.CurrentTimeZone; Console.WriteLine("DisName:{0}\nStdName:{1}\nStdOffset:{2}\nDayLightName:{3}", tzi.DisplayName, tzi.StandardName, tzi.StandardOffset, tzi.DaylightName); // Simply convert a local time to another local time in the target timezone. DateTime dt = TimeZoneInformation.ToLocalTime("eastern standard time", DateTime.Now, "central standard time"); Console.WriteLine("EST:{0}", DateTime.Now); Console.WriteLine("CST:{0}", dt.ToString()); } The Class -------------------------- /// <summary> /// Date: 12/4/2005 /// Created By: William Stacey, MVP /// Used to convert to/from utc times and local times and respect DST. /// Can also covert between two local time zones. /// Information about a time zone containing methods to convert local times to and from UTC and /// between local time zones. /// </summary> [Serializable] public class TimeZoneInformation { #region Fields private TZI tzi; // Current time zone information. private string displayName; // Current time zone display name. private string standardName; // Current time zone standard name (non-DST). private string daylightName; // Current time zone daylight name (DST). private static readonly List<TimeZoneInformation> timeZones; // List of all time zones on machine. #endregion #region Constructors private TimeZoneInformation() { } static TimeZoneInformation() { timeZones = new List<TimeZoneInformation>(); using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones")) { string[] zoneNames = key.GetSubKeyNames(); foreach (string zoneName in zoneNames) { using (RegistryKey subKey = key.OpenSubKey(zoneName)) { TimeZoneInformation tzi = new TimeZoneInformation(); tzi.displayName = (string)subKey.GetValue("Display"); tzi.standardName = (string)subKey.GetValue("Std"); tzi.daylightName = (string)subKey.GetValue("Dlt"); tzi.InitTzi((byte[])subKey.GetValue("Tzi")); timeZones.Add(tzi); } } } } #endregion #region Public Properties /// <summary> /// Gets list of all time zones defined on the current computer system. /// </summary> public static List<TimeZoneInformation> TimeZones { get { // Return a copy of the list. List<TimeZoneInformation> nList = new List<TimeZoneInformation>(timeZones); return nList; } } /// <summary> /// Gets the time zone information of the current computer system. /// </summary> public static TimeZoneInformation CurrentTimeZone { get { string tzn = TimeZone.CurrentTimeZone.StandardName; TimeZoneInformation tzi = TimeZoneInformation.GetTimeZone(tzn); return tzi; } } /// <summary> /// The time zone's name during 'standard' time (i.e. not daylight savings). /// </summary> public string StandardName { get { return standardName; } } /// <summary> /// The time zone's name during daylight savings time (DST). /// </summary> public string DaylightName { get { return daylightName; } } /// <summary> /// The time zone's display name (e.g. "(GMT-05:00) Eastern Time (US and Canada)"). /// </summary> public string DisplayName { get { return displayName; } } /// <summary> /// Gets the standard offset from UTC as a TimeSpan. /// </summary> public TimeSpan StandardOffset { get { return TimeSpan.FromMinutes(StandardBias); } } /// <summary> /// Gets the daylight offset from UTC as a TimeSpan. /// </summary> public TimeSpan DaylightOffset { get { return TimeSpan.FromMinutes(DaylightBias); } } /// <summary> /// Gets the difference, in minutes, between UTC and local time. /// UTC = local time + bias. /// </summary> public int StandardBias { get { return -(tzi.bias + tzi.standardBias); } } /// <summary> /// Gets the difference, in minutes, between UTC and local time (in daylight savings time). /// UTC = local time + bias. /// </summary> public int DaylightBias { get { return -(tzi.bias + tzi.daylightBias); } } #endregion #region Public Methods /// <summary> /// Returns standard name of this time zone instance. /// </summary> /// <returns>Time zone standard name.</returns> public override string ToString() { return this.standardName; } /// <summary> /// Returns a TimeZoneInformation instance for the time zone with supplied standard name. /// </summary> /// <param name="standardTimeZoneName">Standard name of the time zone.</param> /// <returns>TimeZoneInformation instance.</returns> /// <exception cref="ArgumentException">Thrown if name not found.</exception> public static TimeZoneInformation GetTimeZone(string standardTimeZoneName) { if (standardTimeZoneName == null) standardTimeZoneName = "."; if (standardTimeZoneName == ".") standardTimeZoneName = TimeZone.CurrentTimeZone.StandardName; foreach (TimeZoneInformation tzi in TimeZoneInformation.TimeZones) { if (tzi.StandardName.Equals(standardTimeZoneName, StringComparison.OrdinalIgnoreCase)) return tzi; } throw new ArgumentException("standardTimeZoneName not found."); } /// <summary> /// Converts the value of the utc time to a local time in this time zone. /// </summary> /// <param name="utc">The UTC time to convert.</param> /// <returns>The local time.</returns> public DateTime ToLocalTime(DateTime utc) { // Convert to SYSTEMTIME SYSTEMTIME stUTC = DateTimeToSystemTime(utc); // Set up the TIME_ZONE_INFORMATION TIME_ZONE_INFORMATION tziNative = TziNative(); SYSTEMTIME stLocal; NativeMethods.SystemTimeToTzSpecificLocalTime(ref tziNative, ref stUTC, out stLocal); // Convert back to DateTime return SystemTimeToDateTime(ref stLocal); } /// <summary> /// Converts the value of the utc time to local time in supplied time zone. /// </summary> /// <param name="utc">The time to convert.</param> /// <param name="targetTimeZoneName">The standard name of the time zone.</param> /// <returns>The local time.</returns> /// <exception cref="ArgumentException">Thrown if time zone not found.</exception> public static DateTime ToLocalTime(DateTime utc, string targetTimeZoneName) { TimeZoneInformation tzi = TimeZoneInformation.GetTimeZone(targetTimeZoneName); return tzi.ToLocalTime(utc); } /// <summary> /// Converts a localTime from a source time zone to a target time zone, adjusting for DST as needed. /// The localTime must be a local time in the sourceTimeZoneName time zone. /// </summary> /// <param name="sourceTimeZoneName">Time zone name which represents localTime.</param> /// <param name="localTime">The source local time.</param> /// <param name="targetTimeZoneName">The time zone name which to convert the localTime.</param> /// <returns>The local time for targetTimeZoneName.</returns> public static DateTime ToLocalTime(string sourceTimeZoneName, DateTime localTime, string targetTimeZoneName) { DateTime utc = TimeZoneInformation.ToUniversalTime(sourceTimeZoneName, localTime); DateTime lt = TimeZoneInformation.ToLocalTime(utc, targetTimeZoneName); return lt; } /// <summary> /// Converts the value of the local time to UTC time. /// Note that there may be different possible interpretations at the daylight time boundaries. /// </summary> /// <param name="local">The local time to convert.</param> /// <returns>The UTC DateTime.</returns> /// <exception cref="NotSupportedException">Thrown if the method failed due to missing platform support.</exception> public DateTime ToUniversalTime(DateTime local) { SYSTEMTIME stLocal = DateTimeToSystemTime(local); TIME_ZONE_INFORMATION tziNative = TziNative(); SYSTEMTIME stUTC; try { NativeMethods.TzSpecificLocalTimeToSystemTime(ref tziNative, ref stLocal, out stUTC); return SystemTimeToDateTime(ref stUTC); } catch (EntryPointNotFoundException e) { throw new NotSupportedException("This method is not supported on this operating system", e); } } /// <summary> /// Converts a local time in specified time zone to UTC time. /// </summary> /// <param name="standardTimeZoneName">The standard time zone name.</param> /// <param name="local">The local time to convert.</param> /// <returns>The UTC time.</returns> /// <exception cref="ArgumentException">Thrown if time zone name not found.</exception> /// <exception cref="NotSupportedException">Thrown if the method failed due to missing platform support.</exception> public static DateTime ToUniversalTime(string standardTimeZoneName, DateTime local) { TimeZoneInformation tzi = TimeZoneInformation.GetTimeZone(standardTimeZoneName); return tzi.ToUniversalTime(local); } #endregion #region Private Methods private static SYSTEMTIME DateTimeToSystemTime(DateTime dt) { SYSTEMTIME st; FILETIME ft = new FILETIME(); ft.dwHighDateTime = (int)(dt.Ticks >> 32); ft.dwLowDateTime = (int)(dt.Ticks & 0xFFFFFFFFL); NativeMethods.FileTimeToSystemTime(ref ft, out st); return st; } private static DateTime SystemTimeToDateTime(ref SYSTEMTIME st) { FILETIME ft = new FILETIME(); NativeMethods.SystemTimeToFileTime(ref st, out ft); DateTime dt = new DateTime((((long)ft.dwHighDateTime) << 32) | (uint)ft.dwLowDateTime); return dt; } private TIME_ZONE_INFORMATION TziNative() { TIME_ZONE_INFORMATION tziNative = new TIME_ZONE_INFORMATION(); tziNative.Bias = tzi.bias; tziNative.StandardDate = tzi.standardDate; tziNative.StandardBias = tzi.standardBias; tziNative.DaylightDate = tzi.daylightDate; tziNative.DaylightBias = tzi.daylightBias; return tziNative; } /// <summary> /// The standard Windows SYSTEMTIME structure. /// </summary> [StructLayout(LayoutKind.Sequential)] private struct SYSTEMTIME { public UInt16 wYear; public UInt16 wMonth; public UInt16 wDayOfWeek; public UInt16 wDay; public UInt16 wHour; public UInt16 wMinute; public UInt16 wSecond; public UInt16 wMilliseconds; } // FILETIME is already declared in System.Runtime.InteropServices. /// <summary> /// The layout of the Tzi value in the registry. /// </summary> [StructLayout(LayoutKind.Sequential)] private struct TZI { public int bias; public int standardBias; public int daylightBias; public SYSTEMTIME standardDate; public SYSTEMTIME daylightDate; } /// <summary> /// The standard Win32 TIME_ZONE_INFORMATION structure. /// Thanks to www.pinvoke.net. /// </summary> [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private 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; } /// <summary> /// A container for P/Invoke declarations. /// </summary> private struct NativeMethods { private const string KERNEL32 = "kernel32.dll"; [DllImport(KERNEL32)] public static extern uint GetTimeZoneInformation(out TIME_ZONE_INFORMATION lpTimeZoneInformation); [DllImport(KERNEL32)] public static extern bool SystemTimeToTzSpecificLocalTime( [In] ref TIME_ZONE_INFORMATION lpTimeZone, [In] ref SYSTEMTIME lpUniversalTime, out SYSTEMTIME lpLocalTime); [DllImport(KERNEL32)] public static extern bool SystemTimeToFileTime( [In] ref SYSTEMTIME lpSystemTime, out FILETIME lpFileTime); [DllImport(KERNEL32)] public static extern bool FileTimeToSystemTime( [In] ref FILETIME lpFileTime, out SYSTEMTIME lpSystemTime); /// <summary> /// Convert a local time to UTC, using the supplied time zone information. /// Windows XP and Server 2003 and later only. /// </summary> /// <param name="lpTimeZone">The time zone to use.</param> /// <param name="lpLocalTime">The local time to convert.</param> /// <param name="lpUniversalTime">The resultant time in UTC.</param> /// <returns>true if successful, false otherwise.</returns> [DllImport(KERNEL32)] public static extern bool TzSpecificLocalTimeToSystemTime( [In] ref TIME_ZONE_INFORMATION lpTimeZone, [In] ref SYSTEMTIME lpLocalTime, out SYSTEMTIME lpUniversalTime); } /// <summary> /// Initialise the m_tzi member. /// </summary> /// <param name="info">The Tzi data from the registry.</param> private void InitTzi(byte[] info) { if (info.Length != Marshal.SizeOf(tzi)) throw new ArgumentException("Information size is incorrect", "info"); // Could have sworn there's a Marshal operation to pack bytes into // a structure, but I can't see it. Do it manually. GCHandle h = GCHandle.Alloc(info, GCHandleType.Pinned); try { tzi = (TZI)Marshal.PtrToStructure(h.AddrOfPinnedObject(), typeof(TZI)); } finally { h.Free(); } } #endregion } -- Show quoteWilliam Stacey [MVP] "Chris Mullins" <cmull***@yahoo.com> wrote in message news:uNlyJ%23%23xGHA.1268@TK2MSFTNGP02.phx.gbl... | In .Net 2.0, I can get the standard name of the current timezone by: | System.TimeZone.CurrentTimeZone.StandardName | | The problem I'm having is that I have datetimes that are serialized as a UTC | time, with a named timezone. I keep looking for a way to say: | | System.TimeZone tz = new TimeZone("PST"); | tz.ConvertToLocalTime(utcTime); | | Problem is there doesn't seem to way to do this. Anyone got any suggesting | for dealing with TimeZones? | | | | -- | Chris Mullins MCSD.Net, MCPD Enterprise | http://www.coversant.net/blogs/cmullins | | "William Stacey [MVP]" <william.sta***@gmail.com> wrote: [Lack of TimeZone Classes in .Net 1.1 and 2.0]> Never could figure out why they did not include such a needed thing. That makes two of us.> Until then, here is a class I did that will convert between [Snip Class]> timezones, etc. Thanks. That'll do the trick. The only problem now is that I'm working with an ancient extension to the XMPP Instant Messaging protocol (RFC 3920/3921), specifically JEP 0090, http://www.jabber.org/jeps/jep-0090.html. That JEP defines a mechanism by which two clients can exchange time information in a request/response format. That JEP defines a TimeZone string, which may be coming from other operating systems. <xs:sequence minOccurs='0'> <xs:element name='utc' type='xs:string' minOccurs='1'/> <xs:element name='tz' type='xs:string' minOccurs='0'/> <xs:element name='display' type='xs:string' minOccurs='0'/> </xs:sequence>I think I'm going to recommend this old format (it's probably from 2000) be replaced with a more current one that includes a standard XML datetime format. -- Chris Mullins Yes. I would transfer *all dates in UTC with the Z format and put the
string result to your class before xml serializer. IIRC, xml serializer has some issue with dates, so I just do them myself in utc. -- Show quoteWilliam Stacey [MVP] "Chris Mullins" <cmull***@yahoo.com> wrote in message news:O1WTO2GyGHA.4976@TK2MSFTNGP04.phx.gbl... | "William Stacey [MVP]" <william.sta***@gmail.com> wrote: | | [Lack of TimeZone Classes in .Net 1.1 and 2.0] | > Never could figure out why they did not include such a needed thing. | | That makes two of us. | | > Until then, here is a class I did that will convert between | > timezones, etc. | | [Snip Class] | | Thanks. That'll do the trick. | | The only problem now is that I'm working with an ancient extension to the | XMPP Instant Messaging protocol (RFC 3920/3921), specifically JEP 0090, | http://www.jabber.org/jeps/jep-0090.html. That JEP defines a mechanism by | which two clients can exchange time information in a request/response | format. | | That JEP defines a TimeZone string, which may be coming from other operating | systems. | <xs:sequence minOccurs='0'> | <xs:element name='utc' type='xs:string' minOccurs='1'/> | <xs:element name='tz' type='xs:string' minOccurs='0'/> | <xs:element name='display' type='xs:string' minOccurs='0'/> | </xs:sequence>I think I'm going to recommend this old format (it's probably | from 2000) be replaced with a more current one that includes a standard XML | datetime format. | | -- | Chris Mullins | | >In .Net 2.0, I can get the standard name of the current timezone by: CodeProject's your friend! :-)>System.TimeZone.CurrentTimeZone.StandardName >The problem I'm having is that I have datetimes that are serialized as a UTC >time, with a named timezone. I keep looking for a way to say: World Clock and the TimeZoneInformation class http://www.codeproject.com/dotnet/WorldClock.asp This should handle just about anything you need to do with timezones in .NET - also, check out more Timezone-related stuff on CodeProject: Convert between UTC (Universal Co-ordinated Time) and local time http://www.codeproject.com/csharp/timezoneconversions.asp Display the current time across any time zone via custom clocks on your desktop http://www.codeproject.com/smartclient/TimePiece.asp I'm sure you'll find more if you do a thorough search! HTH Marc |
|||||||||||||||||||||||