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

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

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

2008121813480713.jpg

 

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

 

ContractedBlock.gif ExpandedBlockStart.gif 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();
        }
    }

 

ContractedBlock.gif ExpandedBlockStart.gif 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后,我们就可以读取注册表了.先定义几个读取注册表的方法:

 

ContractedBlock.gif ExpandedBlockStart.gif 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信息

 

ContractedBlock.gif ExpandedBlockStart.gif 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:

 

ContractedBlock.gif ExpandedBlockStart.gif 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,在页面级别我们就可以简单用下面的方法来显示给用户选择:

 

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

 

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

 

ContractedBlock.gif ExpandedBlockStart.gif 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值