You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#时间判断逻辑实现与Windows系统时钟程序更新咨询

嘿,我来帮你解决这两个C# Windows窗体的技术问题:


问题1:实现倒计时3分钟提示逻辑

这个需求核心是定时监控当前时间与目标时间的差值,用Windows Forms自带的Timer控件就能轻松搞定,具体步骤和代码如下:

实现思路

  1. 把目标时间字符串解析成TimeSpan,方便和当前系统时间的TimeOfDay做对比
  2. 添加Timer控件,设置每秒检查一次时间差(间隔1000毫秒)
  3. 在Timer的Tick事件里计算剩余时间,当差值接近3分钟时弹出提示,同时加个标记避免重复弹窗

完整代码示例

using System;
using System.Windows.Forms;

namespace TimeReminder
{
    public partial class MainForm : Form
    {
        private TimeSpan _targetTime;
        private bool _alertShown = false; // 防止重复弹出提示

        public MainForm()
        {
            InitializeComponent();
            // 解析目标时间(这里用你给定的"12:15:00")
            if (TimeSpan.TryParse("12:15:00", out var result))
            {
                _targetTime = result;
                timer1.Interval = 1000; // 每秒检查一次
                timer1.Start();
            }
            else
            {
                MessageBox.Show("目标时间格式不正确!");
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            var currentTime = DateTime.Now.TimeOfDay;
            var remaining = _targetTime - currentTime;

            // 用近似范围判断(避免Timer延迟导致错过精确3分钟节点)
            if (remaining.TotalMinutes >= 2.98 && remaining.TotalMinutes <= 3.02 && !_alertShown)
            {
                MessageBox.Show("3 minutes left");
                _alertShown = true;
                // 可选:时间到后停止Timer
                // timer1.Stop();
            }
            // 时间超过目标点后自动停止监控
            else if (remaining.TotalSeconds < 0)
            {
                timer1.Stop();
            }
        }
    }
}

问题2:Windows窗体程序同步系统时钟到time.windows.com

要实现这个功能需要两步:从NTP服务器获取准确时间,然后调用Windows API修改系统时间(C#没有原生修改系统时间的方法)。另外,修改系统时间必须要有管理员权限,这点一定要注意。

步骤1:从NTP服务器获取时间

time.windows.com是微软官方的NTP服务器,我们通过UDP协议请求获取时间:

private static DateTime GetNtpTime(string ntpServer = "time.windows.com")
{
    var ntpData = new byte[48];
    ntpData[0] = 0x1B; // 标记为客户端请求

    var addresses = System.Net.Dns.GetHostEntry(ntpServer).AddressList;
    var ipEndPoint = new System.Net.IPEndPoint(addresses[0], 123);
    var socket = new System.Net.Sockets.Socket(
        System.Net.Sockets.AddressFamily.InterNetwork,
        System.Net.Sockets.SocketType.Dgram,
        System.Net.Sockets.ProtocolType.Udp
    );

    socket.Connect(ipEndPoint);
    socket.Send(ntpData);
    socket.Receive(ntpData);
    socket.Close();

    // 解析NTP时间(NTP时间从1900年1月1日开始,转换为本地时间)
    ulong intPart = BitConverter.ToUInt32(ntpData, 40);
    ulong fractPart = BitConverter.ToUInt32(ntpData, 44);

    intPart = SwapEndianness(intPart);
    fractPart = SwapEndianness(fractPart);

    var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
    var networkTime = new DateTime(1900, 1, 1).AddMilliseconds(milliseconds);

    return networkTime.ToLocalTime();
}

// NTP返回的是大端字节序,需要转换为小端
private static uint SwapEndianness(ulong x)
{
    return (uint)(((x & 0x000000FF) << 24) +
                   ((x & 0x0000FF00) << 8) +
                   ((x & 0x00FF0000) >> 8) +
                   ((x & 0xFF000000) >> 24));
}

步骤2:调用Windows API设置系统时间

需要用P/Invoke声明SetSystemTime函数,这个函数要求传入UTC时间:

using System.Runtime.InteropServices;

// 对应Windows API的SYSTEMTIME结构体
[StructLayout(LayoutKind.Sequential)]
private struct SYSTEMTIME
{
    public ushort Year;
    public ushort Month;
    public ushort DayOfWeek;
    public ushort Day;
    public ushort Hour;
    public ushort Minute;
    public ushort Second;
    public ushort Milliseconds;
}

// 导入Windows内核API
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetSystemTime([In] ref SYSTEMTIME lpSystemTime);

// 封装设置时间的方法
private static bool SyncSystemClock(DateTime targetTime)
{
    // 转换为UTC时间,因为SetSystemTime要求传入UTC
    var utcTime = targetTime.ToUniversalTime();
    var st = new SYSTEMTIME
    {
        Year = (ushort)utcTime.Year,
        Month = (ushort)utcTime.Month,
        Day = (ushort)utcTime.Day,
        Hour = (ushort)utcTime.Hour,
        Minute = (ushort)utcTime.Minute,
        Second = (ushort)utcTime.Second,
        Milliseconds = (ushort)utcTime.Millisecond
    };

    return SetSystemTime(ref st);
}

最终调用示例

在窗体按钮的点击事件里触发同步:

private void btnSyncTime_Click(object sender, EventArgs e)
{
    try
    {
        var ntpTime = GetNtpTime();
        var success = SyncSystemClock(ntpTime);
        if (success)
        {
            MessageBox.Show("系统时间同步成功!");
        }
        else
        {
            MessageBox.Show("同步失败,请确保程序以管理员身份运行!");
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"同步出错:{ex.Message}");
    }
}

关键提示

  • 必须以管理员身份运行程序,否则SetSystemTime会执行失败。可以在项目属性里设置:右键项目→属性→安全性→启用ClickOnce安全设置→设置为完全信任应用,或者修改app.manifest中的requestedExecutionLevel为requireAdministrator。

内容的提问来源于stack exchange,提问作者S.develop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:12:36