Go 日期时间操作

在Golang中,时间日期的操作主要通过标准库time包来完成,该包提供了丰富的函数和类型来处理日期和时间 

基础操作

获取当前时间

使用time.Now()函数获取当前时间:

now := time.Now()
fmt.Println(now)
 格式化时间

使用time.Format(layout)方法按照指定的布局格式化时间:

formatted := now.Format("2006-01-02 15:04:05")
fmt.Println(formatted)

注意:布局字符串中的年、月、日等元素必须遵循特定的约定,如2006代表年份,01代表月份等。

解析时间字符串

使用time.Parse(layout, value string)解析时间字符串为Time类型:

parsedTime, err := time.Parse("2006-01-02 15:04:05", "2023-04-01 14:20:00")
if err != nil {
    fmt.Println("Error parsing time:", err)
} else {
    fmt.Println(parsedTime)
}

高级操作

计算时间间隔

使用time.Sub()计算两个时间点之间的间隔:

later := now.Add(time.Hour)
duration := later.Sub(now)
fmt.Println(duration)
时间比较

使用Before()After()Equal()方法比较时间:

if now.Before(later) {
    fmt.Println("Now is before later")
}
设置时间

使用time.Date()函数创建特定的日期时间:

specificTime := time.Date(2023, 4, 30, 15, 30, 0, 0, time.UTC)
fmt.Println(specificTime)
时间戳转换
  • 将时间转换为Unix时间戳(以秒为单位):t.Unix()
  • 将时间转换为Unix纳秒时间戳:t.UnixNano()
  • 从Unix时间戳创建时间:time.Unix(sec int64, nsec int64)
时区处理

使用time.LoadLocation()加载时区,并通过time.In()调整时间的时区:

location, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
    fmt.Println(err)
} else {
    easternTime := now.In(location)
    fmt.Println(easternTime)
}
定时器和ticker
  • time.NewTimer(d Duration)创建一个计时器,d后触发事件。
func main() {
	// 创建一个5秒后到期的计时器
	timer := time.NewTimer(5 * time.Second)

	// 使用select等待计时器的通道发送信号或者主goroutine被中断
	<-timer.C
	fmt.Println("5 seconds have passed")
}
  • time.NewTicker(d Duration)创建一个周期性的ticker,每隔d时间触发一次事件。
package main

import (
	"fmt"
	"time"
)

func main() {
	// 创建一个每4秒触发一次的ticker
	ticker := time.NewTicker(4 * time.Second)

	done := make(chan bool) // 用于控制ticker的停止

	go func() {
		for {
			select {
			case <-ticker.C:
				fmt.Println("Current time:", time.Now().Format("15:04:05"))
			case <-done: // 接收到停止信号后退出循环
				return
			}
		}
	}()

	// 让ticker运行10秒后停止
	time.Sleep(10 * time.Second) //注意主main goroutine退出了就退出整个程序了
	done <- true                 // 发送信号到done通道
	ticker.Stop()                // 停止ticker,释放资源(可选,因为goroutine已退出)
}
 限制并发执行

 使用时间相关的操作来限制并发执行,例如基于时间窗口的限流

使用 channel 作为信号量(Semaphore)来限制并发执行的 goroutine 数量。这是一个非常实用的模式,尤其是在需要控制同时运行的任务数量,以避免资源过度消耗或满足外部服务的调用限制时。

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	semaphore := make(chan struct{}, 5) // 同时只允许5个goroutine执行
	for i := 1; i <= 10; i++ {
		semaphore <- struct{}{} // 获取令牌
		fmt.Println("------for循环遍历到第", i)
		go func(i int) {
			defer func() { <-semaphore }() // 执行完释放令牌
			// 执行具体任务
			time.Sleep(time.Millisecond * time.Duration(rand.Intn(3000)))
			fmt.Printf("---------------------------任务 %d 已完成\n", i)
		}(i)
	}
}
解释:此时for循环跟goroutine是并发的
  • 初始化信号量(Semaphore)semaphore := make(chan struct{}, 5) 创建了一个容量为5的无缓冲channel。这里的 struct{} 是一个空结构体,不占用任何内存空间,常用于这种只需要信号而不传递具体值的场景。声明中的数字5意味着最多允许5个goroutine同时运行。

  • 并发循环: 通过 for 循环启动10个goroutine来模拟执行一系列任务。每个goroutine代表一个独立的任务。

  • 获取令牌semaphore <- struct{}{} 这行代码实质上是向channel中发送一个空结构体。因为channel的容量是5,所以在前5个goroutine发送信号时会立即完成,之后的goroutine会阻塞在这里,直到有goroutine释放令牌。

  • 执行任务: 在每个goroutine中,使用匿名函数执行具体任务。这里使用 time.Sleep 模拟不同长度的任务执行时间,实际应用中这将替换为真正的任务逻辑。

  • 释放令牌defer func() { <-semaphore }() 确保无论goroutine中的代码如何结束(正常执行完毕或因错误提前退出),都会从channel中接收一个信号,从而释放一个令牌,允许等待的goroutine继续执行。

通过这种方式,你有效地控制了并发执行的goroutine数量,确保了在任何时候并发执行的任务都不会超过预设的限制(本例中为5)。这是一种简单而有效的并发控制机制,适用于多种并发编程场景

简单做个案例

package utils

import (
	"time"
)

// UnixToTime 时间戳转换成日期函数
func UnixToTime(timestamp int) string {
	t := time.Unix(int64(timestamp), 0)
	return t.Format("2006-01-02 15:04:05")
}

// DateToUnix 日期转换成时间戳
func DateToUnix(str string) int64 {
	template := "2006-01-02 15:04:05"
	t, err := time.ParseInLocation(template, str, time.Local)
	if err != nil {
		return 0
	}
	return t.Unix()
}

// GetUnix 获取当前时间戳
func GetUnix() int64 {
	return time.Now().Unix()
}

// GetDate 获取当前日期
func GetDate() string {
	template := "2006-01-02 15:04:05"
	return time.Now().Format(template)
}

// GetDay 获取年月日
func GetDay() string {
	template := "20060102"
	return time.Now().Format(template)
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值