.Net2.0下获取世界各时区信息及夏令时信息

mac2022-06-30  62

在.Net 3.5下有一个TimeZoneInfo类,可以很方便的转换时区和进行时间转换.但是在.Net 2.0下,只能对当前服务器时区进行处理,十分不方便.特别系统是世界范围使用的,更需要考虑当地时区特别是夏令时的问题,不然时间就会错乱.如何解决这个问题,就要通过自己手动处理了.

其实Windows的时区信息都存放在Windows注册表的"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"下.只要读取相关信息出来.就能实现和TimeZoneInfo相同的功能.下边我们就通过一个小demo.读取世界时区信息,计算时区偏移量和夏令时偏移量.并根据用户选择的时区和输入时间,判断该时间是否属于该时区的夏令时范围.

 

首先,我们需要创建两个Struct来记录相关信息,一个是SytemTime,一个TimeZoneInformation.代码如下:

 

SystemTime Struct     [StructLayout(LayoutKind.Sequential)]    struct SYSTEMTIME    {        public ushort wYear;        public ushort wMonth;        public ushort wDayOfWeek;        public ushort wDay;        public ushort wHour;        public ushort wMinute;        public ushort wSecond;        public ushort wMilliseconds;        public void SetInfo(byte[] info)        {            if (info.Length != Marshal.SizeOf(this))            {                throw new ArgumentException("Information size is incorrect""info");            }            else            {                this.wYear = BitConverter.ToUInt16(info, 0);                this.wMonth = BitConverter.ToUInt16(info, 2);                this.wDayOfWeek = BitConverter.ToUInt16(info, 4);                this.wDay = BitConverter.ToUInt16(info, 6);                this.wHour = BitConverter.ToUInt16(info, 8);                this.wMinute = BitConverter.ToUInt16(info, 10);                this.wSecond = BitConverter.ToUInt16(info, 12);                this.wMilliseconds = BitConverter.ToUInt16(info, 14);            }        }        public override bool Equals(object obj)        {            if (this.GetType() == obj.GetType())            {                try                {                    SYSTEMTIME objSt = (SYSTEMTIME)obj;                    if (this.wYear != objSt.wYear                        || this.wMonth != objSt.wMonth                        || this.wDayOfWeek != objSt.wDayOfWeek                        || this.wDay != objSt.wDay                        || this.wHour != objSt.wHour                        || this.wMinute != objSt.wMinute                        || this.wSecond != objSt.wSecond                        || this.wMilliseconds != objSt.wMilliseconds)                        return false;                    else                        return true;                }                catch                {                    return false;                }            }            else                return false;        }        public override int GetHashCode()        {            return base.GetHashCode();        }    }

 

TimeZoneInformation Struct     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]    struct TimeZoneInformation    {        public int bias;        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]        public string standardName;        public SYSTEMTIME standardDate;        public int standardBias;        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]        public string daylightName;        public SYSTEMTIME daylightDate;        public int daylightBias;        public void SetBytes(byte[] info)        {            if (info.Length != 44)                throw new ArgumentException("Information size is incorrect""info");            else            {                this.bias = BitConverter.ToInt32(info, 0);                this.standardBias = BitConverter.ToInt32(info, 4);                this.daylightBias = BitConverter.ToInt32(info, 8);                byte[] helper = new byte[16];                Array.Copy(info, 12, helper, 016);                this.standardDate.SetInfo(helper);                Array.Copy(info, 28, helper, 016);                this.daylightDate.SetInfo(helper);            }        }        public override bool Equals(object obj)        {            if (this.GetType() != obj.GetType())            {                try                {                    TimeZoneInformation objTzi = (TimeZoneInformation)obj;                    if (this.bias != objTzi.bias                        || this.daylightBias != objTzi.daylightBias                        || this.daylightName != objTzi.daylightName                        || this.standardBias != objTzi.standardBias                        || this.standardName != objTzi.standardName                        || !this.daylightDate.Equals(objTzi.daylightDate)                        || !this.standardDate.Equals(objTzi.standardDate)                        )                        return false;                    else                        return true;                }                catch                {                    return false;                }            }            else                return false;        }        public override int GetHashCode()        {            return base.GetHashCode();        }    }

 

定义好相关Structs后,我们就可以读取注册表了.先定义几个读取注册表的方法:

 

RegistryKey Code private static RegistryKey GetTimeZoneRegistryKey(){    RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"false);    if (key == null)        throw new KeyNotFoundException(@"Cannot find the windows registry key (Time Zone).");    else        return key;}private static RegistryKey GetTimeZoneRegistrySubKey(string zoneId){    RegistryKey key = GetTimeZoneRegistryKey();    RegistryKey subKey = key.OpenSubKey(zoneId, false);    if (subKey == null)        throw new Exception("Unknown time zone.");    else        return subKey;}private static RegistryKey GetTimeZoneRegistryDynamicSubKey(TimeZoneInfo tzi){    RegistryKey subKey = GetTimeZoneRegistrySubKey(tzi._id);    return subKey.OpenSubKey("Dynamic DST"false);}

 

下边我们开始读取注册表各个TimeZone信息

 

TimeZones Code public static TimeZoneInfo[] GetTimeZones(){    List<TimeZoneInfo> tzInfos = new List<TimeZoneInfo>();    RegistryKey key = GetTimeZoneRegistryKey();    foreach (string zoneName in key.GetSubKeyNames())    {        TimeZoneInfo tzi = new TimeZoneInfo();        tzi._id = zoneName;        tzi.SetValues();        tzInfos.Add(tzi);    }    TimeZoneInfo.Sort(tzInfos);    return tzInfos.ToArray();}

 

可以看到上述代码是循环读取注册表里面的信息,通过SetVales方法放到一个List:

 

SetValues private void SetValues(){    RegistryKey subKey = GetTimeZoneRegistrySubKey(this._id);    this._displayName = subKey.GetValue("Display").ToString();    this._tzi.daylightName = subKey.GetValue("Dlt").ToString();    this._tzi.standardName = subKey.GetValue("Std").ToString();    this._tzi.SetBytes(subKey.GetValue("Tzi"as byte[]);}

 

通过简单的读取信息填入TimeZoneInfo List,在页面级别我们就可以简单用下面的方法来显示给用户选择:

 

UI1 TimeZoneInfo[] TimeZones = TimeZoneInfo.GetTimeZones();this.drpList.DataSource = TimeZones;this.drpList.DataTextField = "DisplayName";this.drpList.DataValueField = "Id";this.drpList.DataBind();

 

当用选择了某一个时区,我们就可以根据用户选择的时区和输入的日期显示相关时区信息:

 

UI2 if (tzi.DisplayName == this.drpList.SelectedItem.Text){    DateTime dtDate = DateTime.Parse(this.txtDate.Text.Trim());    this.lblInfo.Text += string.Format("<br />时区ID:  {0} ", tzi.Id);    this.lblInfo.Text += string.Format("<br />显示名称:  {0} ", tzi.DisplayName);    this.lblInfo.Text += string.Format("<br />标准名称:  {0} ", tzi.StandardName);    this.lblInfo.Text += string.Format("<br /><br />当前时间是否夏令时:  {0} ", tzi.IsDaylightSavingTime(dtDate).ToString());    this.lblInfo.Text += string.Format("<br />夏令时名称:  {0} ", tzi.DaylightName(dtDate));    this.lblInfo.Text += string.Format("<br />基本偏移量:  {0} ", tzi.StandardUtcOffset.ToString());    this.lblInfo.Text += string.Format("<br />当前偏移量:  {0} ", tzi.GetCurrentUtcOffset(dtDate).ToString());    DaylightTime dt = tzi.GetDaylightChanges(dtDate.Year);    this.lblInfo.Text += string.Format("<br />夏令时开始时间:  {0} ", dt.Start.ToString("yyyy-MM-dd HH:mm:ss"));    this.lblInfo.Text += string.Format("<br />夏令时结束时间:  {0} ", dt.End.ToString("yyyy-MM-dd HH:mm:ss"));    this.lblInfo.Text += string.Format("<br />夏令时增量:  {0} ", dt.Delta.ToString());}

 

更详细的东西就不废话了.附上完整的Demo给大家看吧:

下载Demo点击这里

转载于:https://www.cnblogs.com/KenBlove/archive/2008/12/18/1357493.html

相关资源:时区及夏令时检测(C#源码)
最新回复(0)