• 用C#设置系统时间和本地时间


    前些日子在工作中遇到一个在原子交易中用C#设置系统时间的问题,虽是一个小问题,却因为C#本身没有这种函数而耽误了一些时间,C#要设置系统时间必须要调用Win32的API,而其中相关的函数就是SetSystemTime(), GetSystemTimer(), SetLocalTime(), GetLocalTime(), 这似乎是用VC写的函数,在VC++中是可以直接调用的。MSDN上面对这几个函数解释得不是很详细,网上可以找到不少这样的程序,但我个人感觉对这些函数的功能和注意点说得也不够透彻,包括那个所谓经过测试的。这里把自己所用到的一些功能和体会给出来,至少要把SetSystemTIme()和SetLocalTime()这两个函数的区别搞清楚。

    对于这两个函数,其输入参数必须是一个下面这样的结构体,其成员变量类型必须是ushort,成员变量不能改变顺序。

        [StructLayout(LayoutKind.Sequential)]
     public 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 wMiliseconds;
     }

    调用Win32的API,根据需要选用:

     public class Win32
     
    {
      [DllImport(
    "Kernel32.dll")]
      
    public static extern bool SetSystemTime(ref SystemTime sysTime );
      [DllImport(
    "Kernel32.dll")]
      
    public static extern bool SetLocalTime(ref SystemTime sysTime);
      [DllImport(
    "Kernel32.dll")]
      
    public static extern void GetSystemTime(ref SystemTime sysTime);
      [DllImport(
    "Kernel32.dll")]
      
    public static extern void GetLocalTime(ref SystemTime sysTime);
     }

    下面是SetLocalTime的调用,SetLocalTime的功能就是设置本地系统时间。因为我的工作中要用到的是根据XML文件中的节点内容字符串通过解析后来设置系统时间,所以我做了一个通过输入字符串参数设置本地系统时间的函数,其中调用了SetLocalTime()函数。

            public static bool SetLocalTimeByStr(string timestr)
            {
                
    bool flag=false;
                SystemTime sysTime 
    =new SystemTime();
                
                
    string SysTime=timestr.Trim();   //此步骤多余,为方便程序而用直接用timestr即可
                sysTime.wYear = Convert.ToUInt16(SysTime.Substring(0,4));
                sysTime.wMonth 
    = Convert.ToUInt16(SysTime.Substring(4,2));
                sysTime.wDay
    =Convert.ToUInt16(SysTime.Substring(6,2));
                sysTime.wHour
    =Convert.ToUInt16(SysTime.Substring(8,2));
                sysTime.wMinute 
    = Convert.ToUInt16(SysTime.Substring(10,2));
                sysTime.wSecond 
    = Convert.ToUInt16(SysTime.Substring(12,2));
               
    //注意:
                
    //结构体的wDayOfWeek属性一般不用赋值,函数会自动计算,写了如果不对应反而会出错
                
    //wMiliseconds属性默认值为一,可以赋值
                try
                {
                    flag
    =Win32.SetLocalTime(ref sysTime);
                }
                
    //由于不是C#本身的函数,很多异常无法捕获
               
    //函数执行成功则返回true,函数执行失败返回false
               
    //经常不返回异常,不提示错误,但是函数返回false,给查找错误带来了一定的困难
                catch(Exception ex1)
                {
                    Console.WriteLine(
    "SetLocalTime函数执行异常"+ex1.Message);
                }

                
    return flag;
            }

    如果不是以字符串来赋值,而以int甚至ushort类型数来赋值将会更加简单,不多说了。

    程序执行之后本地系统时间将会如期改变。

    那么SetLocalTime()和SetSystemTime()又有什么区别呢?大家可以把上述函数的“flag=Win32.SetLocalTime(ref sysTime);”部分换成“flag=Win32.SetSystemTime(ref sysTime);”试试,你将会发现这样一个结果:

    执行后系统时间也会改变,但总是比预期的有些偏差,中国的朋友估计都会多出8个小时来。

    这是时区的设置造成的,SetSystemTime()默认设置的为UTC时间,当系统设置时间的时候还会按照时区加上一个偏差。而我们的用的北京时间也就是东八区时间,刚好比UTC多了8个小时。这回了解二者的区别了吧。

            这个偏差是不是可以补回来呢?比如对于北京时间,设置完之后减去8个小时就可以了吗?是这么回事,但是具体做起来要有些麻烦,因为要考虑到天,月甚至年都有可能会造成改变,还要考虑到不同的月份。虽然有了SetLocalTime,再来考虑这个有些多此一举,或者也可以直接从时区的方法上入手,但是我偏偏不服,做了一个这样的方法,只是小试一下,没有自己审核,可能会有bug,给大家参考:

     

            //从字符串设置系统时间
            public bool SetSysTimeByStr(string timestr)
            
    {
                
    int temp=0;
                SystemTime sysTime 
    =new SystemTime();
                
    //给sysTIme初始赋值
                Win32.GetSystemTime(ref sysTime);
                
    string SysTime=timestr;
                sysTime.wYear 
    = Convert.ToUInt16(SysTime.Substring(0,4));
                sysTime.wMonth 
    = Convert.ToUInt16(SysTime.Substring(4,2));
                sysTime.wDay
    =Convert.ToUInt16(SysTime.Substring(6,2));
                sysTime.wHour
    =Convert.ToUInt16(SysTime.Substring(8,2));

                
    //为抵消北京时间+8而进行的操作
                temp=Convert.ToInt16(SysTime.Substring(8,2))-8;
                
    if(temp<0)
                
    {
                    sysTime.wHour 
    =Convert.ToUInt16(temp+24);//Convert.ToUInt16(SysTime.Substring(8,2))-Convert.ToInt16(8);
                    sysTime.wDay=Convert.ToUInt16(sysTime.wDay-1);
                    
    if(sysTime.wDay==0)
                    
    {
                        
    if(sysTime.wMonth==5|sysTime.wMonth==7|sysTime.wMonth==8|sysTime.wMonth==10|sysTime.wMonth==12)
                        
    {
                            sysTime.wMonth
    =Convert.ToUInt16(sysTime.wMonth-1);
                            sysTime.wDay
    =Convert.ToUInt16(30);
                        }

                        
    else if(sysTime.wMonth==1)
                        
    {
                            sysTime.wMonth
    =Convert.ToUInt16(12);
                            sysTime.wDay
    =Convert.ToUInt16(31);
                            sysTime.wYear
    =Convert.ToUInt16(sysTime.wYear-1);
                        }

                        
    else if(sysTime.wMonth==3)
                        
    {
                            sysTime.wMonth
    =Convert.ToUInt16(2);
                            
    if(sysTime.wYear%4==0&&sysTime.wYear%100!=0)
                                sysTime.wDay
    =Convert.ToUInt16(29);
                            
    else
                                sysTime.wDay
    =Convert.ToUInt16(28);
                        }

                        
    else
                        
    {
                            sysTime.wMonth
    =Convert.ToUInt16(sysTime.wMonth-1);
                            sysTime.wDay
    =Convert.ToUInt16(31);
                        }


                    }

                }

                
    else
                
    {
                    sysTime.wHour
    =Convert.ToUInt16(temp);
                }


                sysTime.wMinute 
    = Convert.ToUInt16(SysTime.Substring(10,2));
                sysTime.wSecond 
    = Convert.ToUInt16(SysTime.Substring(12,2));
                    bool flag=Win32.SetSystemTime(ref sysTime);

                    
    return flag;
            }

    而对于那两个Get的方法GetSystemTimer(),和GetLocalTime()的使用,相信不成什么问题,就不多说了。

    另外,在此过程中发现一个问题,就是Visual Studio.net 2003在调式这个程序的时候经常会遇到程序不执行的情况,也不报错误,我用单步调试也是毫无反应,而关掉重新开就一点毛病都没有了,在多台电脑上都出现过。可能是Visual Studio的一个bug吧。

  • 相关阅读:
    POJ3159 Candies —— 差分约束 spfa
    POJ1511 Invitation Cards —— 最短路spfa
    POJ1860 Currency Exchange —— spfa求正环
    POJ3259 Wormholes —— spfa求负环
    POJ3660 Cow Contest —— Floyd 传递闭包
    POJ3268 Silver Cow Party —— 最短路
    POJ1797 Heavy Transportation —— 最短路变形
    POJ2253 Frogger —— 最短路变形
    POJ1759 Garland —— 二分
    POJ3685 Matrix —— 二分
  • 原文地址:https://www.cnblogs.com/dsliang/p/1645225.html
Copyright © 2020-2023  润新知