day 29 - timestamp & 定时执行

我们系统的沟通都是透过timestamp, 包含API参数跟资料库的储存都是以timestamp为主,因为timestamp是唯一的, 不管身处哪个时区针对同时间所换出来的timestamp都会是一样的, 这样在API沟通时才不会造成资料错乱的状况。
但是有时候还是会有需要日期跟时间的需求, 像是排程在美东时间00:00时要发送通知等等, 这时候就需要搭配timezone来决定要使用的时区的时间。如果跟我一样身处在台湾, 那可以用Asia/Hong_Kong时区, 如果在美东的话可以使用America/Caracas, 不过这边要注意的是, 很多地区有日光节约时间, 这时候转换日期时就会踩到日光节约时间的雷, 所以美东时间我们采用的是America/Caracas 而不是America/New_York

这边示范Go 几个关於时间的操作

  • 取当前日期&时间

        /** 取当前时间 **/
        locHongKong, _ := time.LoadLocation("Asia/Hong_Kong")
        now := time.Now()
        fmt.Println("Asia/HongKong 当前时间 > ", now.Format("2006-01-02 15:04:05"), ", timestamp > ", now.Unix())
    
  • 取当前美东时区日期&时间

        /** 更改时区 Caracas **/
        locCaracas, _ := time.LoadLocation("America/Caracas")
        fmt.Println("America/Caracas 当前时间 > ", time.Now().In(locCaracas).Format("2006-01-02 15:04:05"), ", timestamp > ", time.Now().In(locCaracas).Unix())
    
  • 往前一天, 往前一个月, 往前一年

        nextYear := now.AddDate(1, 0, 0)
        fmt.Println("Asia/HongKong 加一年 > ", nextYear.Format("2006-01-02 15:04:05"), ", timestamp > ", nextYear.Unix())
    
        nextMonth := now.AddDate(0, 1, 0)
        fmt.Println("Asia/HongKong 加一个月 > ", nextMonth.Format("2006-01-02 15:04:05"), ", timestamp > ", nextMonth.Unix())
    
        nextDay := now.AddDate(0, 0, 1)
        fmt.Println("Asia/HongKong 加一天 > ", nextDay.Format("2006-01-02 15:04:05"), ", timestamp > ", nextDay.Unix())
    
  • 指定当前时区 明天00:00 的时间日期

        /** 明天 00:00 **/
        nextDay, err := time.ParseInLocation("2006-01-02 15:04:05", nextDay.Format("2006-01-02")+" 00:00:00", locHongKong)
        if err != nil {
            fmt.Println("err:", err)
        }
        fmt.Println("明天 00:00 > ", nextDay.Format("2006-01-02 15:04:05"), ", timestamp > ", nextDay.Unix())
    
  • 定时排程, 排程通常会应用在预做、检查或同步资料, 固定每天几点开始预产当天项目或是固定每分钟检查一次状态或抄一次资料之类的。这边示范每分钟的00秒执行一次(hh:mm:00)。

            var (
                ticker         *time.Ticker
                duration       int64
                runCycleSecond int64
            )
            // 定义执行周期
            runCycleSecond = 60
            hour, minute, second := now.Clock()
            // 基础时间
            nowTime := time.Date(2021, 10, 1, hour, minute, second, 0, locHongKong).Unix()
            // 下一分钟开始执行
            setTime := time.Date(2021, 10, 1, hour, minute+1, 0, 0, locHongKong).Unix()
            minusTime := setTime - nowTime
    
            switch {
            case minusTime == 0:
                duration = runCycleSecond
            case minusTime > 0:
                // 余数
                remainder, _ := decimal.NewFromFloat(float64(minusTime)).Mod(decimal.NewFromFloat(float64(runCycleSecond))).Float64()
                if remainder == 0 {
                    duration = runCycleSecond
                } else {
                    duration = int64(remainder)
                }
            }
    
            fmt.Println("每分钟执行检查, 下次检查等待时间:", duration)
            ticker = time.NewTicker(time.Second * time.Duration(duration))
            for range ticker.C {
                Run()
                // 重置 timer = runCycleSecond
                ticker.Reset(time.Second * time.Duration(runCycleSecond))
            }
        }
    
        func Run() {
            fmt.Println("每分钟检查 > ", time.Now().Format("2006-01-02 15:04:05"))
        }
    
    
  • 执行结果

        每分钟执行检查, 下次检查 等待时间: 4
        每分钟检查 >  2021-10-07 08:37:00
        每分钟检查 >  2021-10-07 08:38:00
        每分钟检查 >  2021-10-07 08:39:00
        每分钟检查 >  2021-10-07 08:40:00
    

这边要注意ticker.Reset要使用go1.15以上才能编译。


<<:  Day 22 : 案例分享(7.1) 库存与制造 - 库存移动(调拨)流程

>>:  Day29 go-elasticsearch(三)

[Day27] 建立购物车系统 - 10

本篇同步发文在个人Blog: 一袋.NET要扛几楼?打造容器化的ASP.NET Core网站!系列文...

Day 03 - 动态调整的PM职涯规划(2)

图片来源 继续上一篇的目标设定, 有时候我觉得是因为你心中已有一个"既定的目标"...

【HTML】【CSS】<table>里面时常无效的margin和padding

【前言】 本系列为个人前端学习之路的学习笔记,在过往的学习过程中累积了很多笔记,如今想藉着IT邦帮忙...

Day8:如果怎样就怎样

在讲else、elif之前,先来让我们看看什麽是"if" 程序码如下: [In]...