github.com/aquayi/gokit@v0.0.0-20170805152833-88827a405d9b/time.go (about)

     1  package GoKit
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"log"
     7  	"time"
     8  )
     9  
    10  // DateOf 返回会把 timestamp 普通的日期格式
    11  // 例如:把	1136185384 转换成 "2006-01-02 15:03:04 +0800 CST"
    12  func DateOf(t int64) string {
    13  	return time.Unix(t, 0).String()
    14  }
    15  
    16  // WaitFunc 返回 一个 cycleCh  chan<- time.Duration 和 一个 Wait 函数
    17  // 如果 cycleCh <- d ,则 Wait() 的sleep时间被修改为 d
    18  // sleep时间的修改会立即生效,不用等到此waitDuration结束。
    19  // 例如:当100秒的waitDuration时间已过51秒时,把waitDuration修改为50秒,程序会立刻结束。
    20  //      不用等到100秒才结束。
    21  // 例如:100秒的waitDuration在结束前,把waitDuration修改为200秒,
    22  //      此次Wait()会sleep 200秒才结束。
    23  //
    24  // checkCycle是检查是否到期的时间段,也是最小等待时间段。
    25  //
    26  // 当checkCycle较大时,Wait()的sleep时间会和waitDuration,有较大的差距,
    27  // 程序的实际等待时间,总是 checkCycle × int(waitDuration/checkCycle + 1)
    28  func WaitFunc(checkCycle time.Duration, name string) (chan<- time.Duration, func()) {
    29  	cycleCh := make(chan time.Duration, 7)
    30  	beginTime := time.Now()
    31  	waitDuration := checkCycle
    32  
    33  	return cycleCh, func() {
    34  
    35  		for {
    36  			select {
    37  			case waitDuration = <-cycleCh:
    38  				if waitDuration <= checkCycle {
    39  					log.Printf("WARNING: %s的 等待时间 <= 检查周期 ,程序只会按照检查周期来等待。", name)
    40  				}
    41  				log.Printf("INFO: %s的 等待时间 已经修改为:%s", name, waitDuration)
    42  			default:
    43  			}
    44  
    45  			// 把判断是否结束的语句,放在最后,很有必要。
    46  			// 因为很有可能,wait()的调用周期总是大于waitDuration
    47  			// 而导致总是无法进入for循环,来改变waitDuration的值
    48  			// 特别是第一个waitDuration的值为checkCycle,总是比较小的。
    49  
    50  			if time.Now().Before(beginTime.Add(waitDuration)) {
    51  				time.Sleep(checkCycle)
    52  			} else {
    53  				break
    54  			}
    55  		}
    56  
    57  		beginTime = time.Now()
    58  	}
    59  }
    60  
    61  //SleepFunc 返回一个等待sleep函数, 使程序暂停一个duration。
    62  //SleepFunc是以上WaitFunc的简化版本,通常运用于API访问限制
    63  //利用闭包,把beginTime变量包裹到了sleep函数内。
    64  func SleepFunc(duration time.Duration) func() {
    65  	beginTime := time.Now()
    66  	return func() {
    67  		//无需判断,如果Sleep的时间为负,则不会Sleep。
    68  		time.Sleep(duration - time.Since(beginTime))
    69  		beginTime = time.Now()
    70  	}
    71  }
    72  
    73  // ParseLocalTime 把string格式的时间,转换成time.time
    74  // NOTICE: 我写这个函数的原因是
    75  // 1. 添加更详解的错误说明。
    76  // 2. 编写单元测试,查看是否真的转换成功了。
    77  func ParseLocalTime(strTime string) (*time.Time, error) {
    78  	t, err := time.ParseInLocation("2006-01-02 15:04:05", strTime, time.Local)
    79  	if err != nil {
    80  		msg := fmt.Sprintf("无法把%s转换成time.time格式: %s", strTime, err)
    81  		return nil, errors.New(msg)
    82  	}
    83  
    84  	return &t, nil
    85  }