golang-Windows 设置系统本地时间

本文档介绍了如何使用Go语言调用Win32API的SetLocalTime和SetSystemTime函数来修改Windows系统的日期和时间。详细阐述了结构体SYSTEMTIME的定义及参数设置,并提供了具体的Go代码示例。同时,文章还包含了一个时间格式校验的函数,确保输入的时间参数符合规范。需要注意的是,修改系统时间需具备管理员权限。
摘要由CSDN通过智能技术生成

golang 调用win32api 对windows系统时间进行调用,主要参考的是微软的win32api文档,根据官方文档,有两者设置方式:
setlocaltime:设置当前的本地时间和日期。https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-setlocaltime
setsystemtime:设置当前系统时间和日期。系统时间以协调世界时 (UTC) 表示https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-setsystemtime

// 根据官方文档中的描述,setlocaltime 需要传一个输入参数,该参数是一个名为SYSTEMTIME的指针结构体
BOOL SetLocalTime(
  [in] const SYSTEMTIME *lpSystemTime
);

// SYSTEMTIME 定义:
typedef struct _SYSTEMTIME {
  WORD wYear;
  WORD wMonth;
  WORD wDayOfWeek;
  WORD wDay;
  WORD wHour;
  WORD wMinute;
  WORD wSecond;
  WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;

// word 类型在golang 里面可以看作是 uint16
// SetLocalTime的返回值,如果设置成功,则返回值不是0,反之则为0

golang 调用win32api的方式 是通过 syscall 库去调用相应的 windows .dll 文件,根据上述文档描述,两个接口都是存在于 Kernel32.dll 这个文件当中,因此我们可以使用如下代码去实现调用接口:

dll2 := syscall.NewLazyDLL("kernel32.dll")
proc := dll2.NewProc("SetLocalTime")

具体实现方式如下: 

// 定义对应的结构体
type SYSTEMTIME struct {
	WYear         uint16
	WMonth        uint16
	WDayOfWeek    uint16
	WDay          uint16
	WHour         uint16
	WMinute       uint16
	WSecond       uint16
	WMilliseconds uint16
}

// 设置本地系统时间
func SetLocalTime(year, month, day, hour, minute, seconds uint16) error {
	s := SYSTEMTIME{
		WYear: year, WMonth: month, WDay: day, WHour: hour, WMinute: minute, WSecond: seconds,
	}
	fmt.Println("s", s)
	dll2 := syscall.NewLazyDLL("kernel32.dll")
	proc := dll2.NewProc("SetLocalTime")
    // 调用接口,传参
	r, _, err := proc.Call(uintptr(unsafe.Pointer(&s)))
	if r <= 0 {
		return err
	} else {
		return nil
	}
}

最后执行的话,需要在使用管理员权限在cmd 中执行才会成功.

下面是关于输入时间格式的一个校验,因为使用 SetLocalTime,对于输入时间系统不会做过多校验.我代码主要框架是gin.就不做过多修改了

func setTime(c *gin.Context) {
	var t struct {
		Year    uint16 `json:"year"`
		Month   uint16 `json:"month"`
		Day     uint16 `json:"day"`
		Hour    uint16 `json:"hour"`
		Minute  uint16 `json:"minute"`
		Seconds uint16 `json:"seconds"`
	}
	err := c.Bind(&t)
	if err != nil {
		c.JSON(200, utils.Returns(utils.ParamErr, err.Error(), c, nil, nil))
		return
	}
	msg := []string{}
	monthMap := map[uint16]string{
		1: "Jan", 2: "Feb", 3: "Mar", 4: "Apr", 5: "May", 6: "Jun", 7: "Jul",
		8: "Aug", 9: "Sep", 10: "Oct", 11: "Nov", 12: "Dec",
	}
	if t.Year < 1601 || t.Year > 30827 {
		msg = append(msg, "year range is from 1601 to 30827")
	}
	switch t.Month {
	case 1:
	case 3:
	case 5:
	case 7:
	case 8:
	case 10:
	case 12:
		if t.Day < 1 || t.Day > 31 {
			msg = append(msg, fmt.Sprintf("%d/%s of days range is from 1 to 31", t.Year, monthMap[t.Month]))
		}
	case 2:
		if t.Year%4 == 0 && t.Year%100 != 0 || t.Year%400 == 0 { // 闰年
			if t.Day < 1 || t.Day > 29 {
				msg = append(msg, fmt.Sprintf("%d/%s of days range is from 1 to 29", t.Year, monthMap[t.Month]))
			}
		} else { // 平年
			if t.Day < 1 || t.Day > 28 {
				msg = append(msg, fmt.Sprintf("%d/%s of days range is from 1 to 28", t.Year, monthMap[t.Month]))
			}
		}
	case 4:
	case 6:
	case 9:
	case 11:
		if t.Day < 1 || t.Day > 30 {
			msg = append(msg, fmt.Sprintf("%d/%s of days is ranges 1-30", t.Year, monthMap[t.Month]))
		}
	default:
		msg = append(msg, "month range is from 1 to 12")
	}
	if t.Hour < 0 || t.Hour > 59 {
		msg = append(msg, "hour range is from 0 to 59")
	}
	if t.Minute < 0 || t.Minute > 59 {
		msg = append(msg, "minute range is from 0 to 59")
	}
	if t.Seconds < 0 || t.Seconds > 59 {
		msg = append(msg, "seconds range is from  0 to 59")
	}
	if len(msg) > 0 {
		c.JSON(200, utils.Returns(utils.TimeRangeErr, strings.Join(msg, ","), c, nil, nil))
		return
	}
	err = utils.SetLocalTime(t.Year, t.Month, t.Day, t.Hour, t.Minute, t.Seconds)
	if err != nil {
		c.JSON(200, utils.Returns(utils.UpdateErr, err.Error(), c, nil, nil))
		return
	}
	c.JSON(200, utils.Returns(utils.Succ, "", c, nil, nil))
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值