时间准确的重要性不言而喻,有时候我们对时间的要求非常严格,有时候也要求不允许用户调整系统时间,有时候。。。等等情况下,我们都需要时间的同步,虽然Windows也有DOS命令来保持和时钟服务进行同步,但本文另辟途径,介绍另一种获取标准时间并同步时间的操作。
首先,我们来看看一个网站:国家授时中心(http://www.time.ac.cn/stime.asp),这个是应该是时间的权威机构,里面有各国各地的时间,我们可以通过同步该时间来实现系统时间的更新。首先分两步,一步是获取“国家授时中心”的时间,一步是更新系统时间。下面的代码就是做这些工作。
#region 获取网络时间
/// <summary>
/// 获取中国国家授时中心网络服务器时间发布的当前时间
/// </summary>
/// <returns></returns>
public static DateTime GetChineseDateTime()
{
DateTime res = DateTime.MinValue;
try
{
string url = " http://www.time.ac.cn/stime.asp ";
HttpHelper helper = new HttpHelper();
helper.Encoding = Encoding.Default;
string html = helper.GetHtml(url);
string patDt = @" \d{4}年\d{1,2}月\d{1,2}日 ";
string patHr = @" hrs\s+=\s+\d{1,2} ";
string patMn = @" min\s+=\s+\d{1,2} ";
string patSc = @" sec\s+=\s+\d{1,2} ";
Regex regDt = new Regex(patDt);
Regex regHr = new Regex(patHr);
Regex regMn = new Regex(patMn);
Regex regSc = new Regex(patSc);
res = DateTime.Parse(regDt.Match(html).Value);
int hr = GetInt(regHr.Match(html).Value, false);
int mn = GetInt(regMn.Match(html).Value, false);
int sc = GetInt(regSc.Match(html).Value, false);
res = res.AddHours(hr).AddMinutes(mn).AddSeconds(sc);
}
catch { }
return res;
}
/// <summary>
/// 从指定的字符串中获取整数
/// </summary>
/// <param name="origin"> 原始的字符串 </param>
/// <param name="fullMatch"> 是否完全匹配,若为false,则返回字符串中的第一个整数数字 </param>
/// <returns> 整数数字 </returns>
private static int GetInt( string origin, bool fullMatch)
{
if ( string.IsNullOrEmpty(origin))
{
return 0;
}
origin = origin.Trim();
if (!fullMatch)
{
string pat = @" -?\d+ ";
Regex reg = new Regex(pat);
origin = reg.Match(origin.Trim()).Value;
}
int res = 0;
int.TryParse(origin, out res);
return res;
}
#endregion
/// <summary>
/// 获取中国国家授时中心网络服务器时间发布的当前时间
/// </summary>
/// <returns></returns>
public static DateTime GetChineseDateTime()
{
DateTime res = DateTime.MinValue;
try
{
string url = " http://www.time.ac.cn/stime.asp ";
HttpHelper helper = new HttpHelper();
helper.Encoding = Encoding.Default;
string html = helper.GetHtml(url);
string patDt = @" \d{4}年\d{1,2}月\d{1,2}日 ";
string patHr = @" hrs\s+=\s+\d{1,2} ";
string patMn = @" min\s+=\s+\d{1,2} ";
string patSc = @" sec\s+=\s+\d{1,2} ";
Regex regDt = new Regex(patDt);
Regex regHr = new Regex(patHr);
Regex regMn = new Regex(patMn);
Regex regSc = new Regex(patSc);
res = DateTime.Parse(regDt.Match(html).Value);
int hr = GetInt(regHr.Match(html).Value, false);
int mn = GetInt(regMn.Match(html).Value, false);
int sc = GetInt(regSc.Match(html).Value, false);
res = res.AddHours(hr).AddMinutes(mn).AddSeconds(sc);
}
catch { }
return res;
}
/// <summary>
/// 从指定的字符串中获取整数
/// </summary>
/// <param name="origin"> 原始的字符串 </param>
/// <param name="fullMatch"> 是否完全匹配,若为false,则返回字符串中的第一个整数数字 </param>
/// <returns> 整数数字 </returns>
private static int GetInt( string origin, bool fullMatch)
{
if ( string.IsNullOrEmpty(origin))
{
return 0;
}
origin = origin.Trim();
if (!fullMatch)
{
string pat = @" -?\d+ ";
Regex reg = new Regex(pat);
origin = reg.Match(origin.Trim()).Value;
}
int res = 0;
int.TryParse(origin, out res);
return res;
}
#endregion
#region P/Invoke 设置本地时间
[DllImport( " kernel32.dll ")]
private static extern bool SetLocalTime( ref SYSTEMTIME time);
[StructLayout(LayoutKind.Sequential)]
private struct SYSTEMTIME
{
public short year;
public short month;
public short dayOfWeek;
public short day;
public short hour;
public short minute;
public short second;
public short milliseconds;
}
/// <summary>
/// 设置本地计算机时间
/// </summary>
/// <param name="dt"> DateTime对象 </param>
public static void SetLocalTime(DateTime dt)
{
SYSTEMTIME st;
st.year = ( short)dt.Year;
st.month = ( short)dt.Month;
st.dayOfWeek = ( short)dt.DayOfWeek;
st.day = ( short)dt.Day;
st.hour = ( short)dt.Hour;
st.minute = ( short)dt.Minute;
st.second = ( short)dt.Second;
st.milliseconds = ( short)dt.Millisecond;
SetLocalTime( ref st);
}
#endregion
[DllImport( " kernel32.dll ")]
private static extern bool SetLocalTime( ref SYSTEMTIME time);
[StructLayout(LayoutKind.Sequential)]
private struct SYSTEMTIME
{
public short year;
public short month;
public short dayOfWeek;
public short day;
public short hour;
public short minute;
public short second;
public short milliseconds;
}
/// <summary>
/// 设置本地计算机时间
/// </summary>
/// <param name="dt"> DateTime对象 </param>
public static void SetLocalTime(DateTime dt)
{
SYSTEMTIME st;
st.year = ( short)dt.Year;
st.month = ( short)dt.Month;
st.dayOfWeek = ( short)dt.DayOfWeek;
st.day = ( short)dt.Day;
st.hour = ( short)dt.Hour;
st.minute = ( short)dt.Minute;
st.second = ( short)dt.Second;
st.milliseconds = ( short)dt.Millisecond;
SetLocalTime( ref st);
}
#endregion
两步操作就可以搞定时间的同步,测试效果还是不错,不过不建议频繁进行时间的同步处理,间隔一段时间检查一次即可。
如果你有更好的方法,希望大家交流提高。