• 欢迎来到小爱博客,一个分享互联网IT技术的网站,喜欢就收藏吧!

golang包time用法详解

go 小爱 1个月前 (09-20) 26次浏览 已收录 0个评论 扫描二维码

在我们编程过程中,经常会用到与时间相关的各种务需求,下面来介绍 golang 中有关时间的一些基本用法,我们从 time 的几种 type 来开始介绍。

时间可分为时间点与时间段,golang 也不例外,提供了以下两种基础类型
– 时间点(Time)
– 时间段(Duration)

除此之外 golang 也提供了以下类型,做一些特定的业务
– 时区(Location)
– Ticker
– Timer(定时器)

我们将按以上顺序来介绍 time 包的使用。

时间点(Time)

我们使用的所有与时间相关的业务都是基于点而延伸的,两点组成一个时间段,大多数应用也都是围绕这些点与面去做逻辑处理。

初始化

go 针对不同的参数类型提供了以下初始化的方式

<code class="language-go hljs  has-numbering">      <span class="hljs-comment">// func Now() Time</span>
      fmt.Println(time.Now())

      <span class="hljs-comment">// func Parse(layout, value string) (Time, error)</span>
      time.Parse(<span class="hljs-string">"2016-01-02 15:04:05"</span>, <span class="hljs-string">"2018-04-23 12:24:51"</span>)

      <span class="hljs-comment">// func ParseInLocation(layout, value string, loc *Location) (Time, error) (layout已带时区时可直接用Parse)</span>
      time.ParseInLocation(<span class="hljs-string">"2006-01-02 15:04:05"</span>, <span class="hljs-string">"2017-05-11 14:06:06"</span>, time.Local)

      <span class="hljs-comment">// func Unix(sec int64, nsec int64) Time</span>
      time.Unix<span class="hljs-number">(1e9</span>,<span class="hljs-number"> 0</span>)

      <span class="hljs-comment">// func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time</span>
      time.Date<span class="hljs-number">(2018</span>,<span class="hljs-number"> 1</span>,<span class="hljs-number"> 2</span>,<span class="hljs-number"> 15</span>,<span class="hljs-number"> 30</span>,<span class="hljs-number"> 10</span>,<span class="hljs-number"> 0</span>, time.Local)

      <span class="hljs-comment">// func (t Time) In(loc *Location) Time 当前时间对应指定时区的时间</span>
      loc, _ := time.LoadLocation(<span class="hljs-string">"America/Los_Angeles"</span>)
      fmt.Println(time.Now().In(loc))

      <span class="hljs-comment">// func (t Time) Local() Time</span></code>

获取到时间点之后为了满足业务和设计,需要转换成我们需要的格式,也就是所谓的时间格式化。

格式化

to string

格式化为字符串我们需要使用 time.Format 方法来转换成我们想要的格式

<code class="language-go hljs  has-numbering">      fmt.Println(time.Now().Format(<span class="hljs-string">"2006-01-02 15:04:05"</span>))  <span class="hljs-comment">// 2018-04-24 10:11:20</span>
      fmt.Println(time.Now().Format(time.UnixDate))         <span class="hljs-comment">// Tue Apr 24 09:59:02 CST 2018</span></code>

Format 函数中可以指定你想使用的格式,同时 time 包中也给了一些我们常用的格式

<code class="language-go hljs  has-numbering"><span class="hljs-keyword">const</span> (
    ANSIC       = <span class="hljs-string">"Mon Jan _2 15:04:05 2006"</span>
    UnixDate    = <span class="hljs-string">"Mon Jan _2 15:04:05 MST 2006"</span>
    RubyDate    = <span class="hljs-string">"Mon Jan 02 15:04:05 -0700 2006"</span>
    RFC822      = <span class="hljs-string">"02 Jan 06 15:04 MST"</span>
    RFC822Z     = <span class="hljs-string">"02 Jan 06 15:04 -0700"</span> <span class="hljs-comment">// RFC822 with numeric zone</span>
    RFC850      = <span class="hljs-string">"Monday, 02-Jan-06 15:04:05 MST"</span>
    RFC1123     = <span class="hljs-string">"Mon, 02 Jan 2006 15:04:05 MST"</span>
    RFC1123Z    = <span class="hljs-string">"Mon, 02 Jan 2006 15:04:05 -0700"</span> <span class="hljs-comment">// RFC1123 with numeric zone</span>
    RFC3339     = <span class="hljs-string">"2006-01-02T15:04:05Z07:00"</span>
    RFC3339Nano = <span class="hljs-string">"2006-01-02T15:04:05.999999999Z07:00"</span>
    Kitchen     = <span class="hljs-string">"3:04PM"</span>
    <span class="hljs-comment">// Handy time stamps.</span>
    Stamp      = <span class="hljs-string">"Jan _2 15:04:05"</span>
    StampMilli = <span class="hljs-string">"Jan _2 15:04:05.000"</span>
    StampMicro = <span class="hljs-string">"Jan _2 15:04:05.000000"</span>
    StampNano  = <span class="hljs-string">"Jan _2 15:04:05.000000000"</span>
)     </code>

注意galang 中指定的特定时间格式为 "2006-01-02 15:04:05 -0700 MST", 为了记忆方便,按照美式时间格式 月日时分秒年 外加时区 排列起来依次是 01/02 03:04:05PM ‘06 -0700,刚开始使用时需要注意。

to time stamp

<code class="language-go hljs  has-numbering">      <span class="hljs-keyword">func</span> (t Time) Unix() <span class="hljs-typename">int64</span>
      <span class="hljs-keyword">func</span> (t Time) UnixNano() <span class="hljs-typename">int64</span>

      fmt.Println(time.Now().Unix())

      <span class="hljs-comment">// 获取指定日期的时间戳</span>
      dt, _ := time.Parse(<span class="hljs-string">"2016-01-02 15:04:05"</span>, <span class="hljs-string">"2018-04-23 12:24:51"</span>)
      fmt.Println(dt.Unix())

      fmt.Println(time.Date<span class="hljs-number">(2018</span>,<span class="hljs-number"> 1</span><span class="hljs-number">,2</span><span class="hljs-number">,15</span><span class="hljs-number">,30</span><span class="hljs-number">,10</span><span class="hljs-number">,0</span>, time.Local).Unix())</code>

其他

time 包还提供了一些常用的方法,基本覆盖了大多数业务,从方法名就能知道代表的含义就不一一说明了。

<code class="language-go hljs  has-numbering">      <span class="hljs-keyword">func</span> (t Time) Date() (year <span class="hljs-typename">int</span>, month Month, day <span class="hljs-typename">int</span>)
      <span class="hljs-keyword">func</span> (t Time) Clock() (hour, min, sec <span class="hljs-typename">int</span>)
      <span class="hljs-keyword">func</span> (t Time) Year() <span class="hljs-typename">int</span>
      <span class="hljs-keyword">func</span> (t Time) Month() Month
      <span class="hljs-keyword">func</span> (t Time) Day() <span class="hljs-typename">int</span>
      <span class="hljs-keyword">func</span> (t Time) Hour() <span class="hljs-typename">int</span>
      <span class="hljs-keyword">func</span> (t Time) Minute() <span class="hljs-typename">int</span>
      <span class="hljs-keyword">func</span> (t Time) Second() <span class="hljs-typename">int</span>
      <span class="hljs-keyword">func</span> (t Time) Nanosecond() <span class="hljs-typename">int</span>
      <span class="hljs-keyword">func</span> (t Time) YearDay() <span class="hljs-typename">int</span>
      <span class="hljs-keyword">func</span> (t Time) Weekday() Weekday
      <span class="hljs-keyword">func</span> (t Time) ISOWeek() (year, week <span class="hljs-typename">int</span>)
      <span class="hljs-keyword">func</span> (t Time) IsZero() <span class="hljs-typename">bool</span>
      <span class="hljs-keyword">func</span> (t Time) Local() Time
      <span class="hljs-keyword">func</span> (t Time) Location() *Location
      <span class="hljs-keyword">func</span> (t Time) Zone() (name <span class="hljs-typename">string</span>, offset <span class="hljs-typename">int</span>)
      <span class="hljs-keyword">func</span> (t Time) Unix() <span class="hljs-typename">int64</span></code>

时间段(Duartion)

介绍完了时间点,我们再来介绍时间段,即 Duartion 类型, 我们业务也是很常用的类型。

<code class="language-go hljs  has-numbering">      <span class="hljs-comment">// func ParseDuration(s string) (Duration, error)</span>
      tp, _ := time.ParseDuration(<span class="hljs-string">"1.5s"</span>)
      fmt.Println(tp.Truncate<span class="hljs-number">(1000</span>), tp.Seconds(), tp.Nanoseconds())

      <span class="hljs-keyword">func</span> (d Duration) Hours() <span class="hljs-typename">float64</span>
      <span class="hljs-keyword">func</span> (d Duration) Minutes() <span class="hljs-typename">float64</span>
      <span class="hljs-keyword">func</span> (d Duration) Seconds() <span class="hljs-typename">float64</span>
      <span class="hljs-keyword">func</span> (d Duration) Nanoseconds() <span class="hljs-typename">int64</span>
      <span class="hljs-keyword">func</span> (d Duration) Round(m Duration) Duration         <span class="hljs-comment">// 四舍五入</span>
      <span class="hljs-keyword">func</span> (d Duration) Truncate(m Duration) Duration      <span class="hljs-comment">// 向下取整</span></code>

时区(Location)

我们在来介绍一下时区的相关的函数

<code class="language-go hljs  has-numbering">    <span class="hljs-comment">// 默认UTC    </span>
    loc, err := time.LoadLocation(<span class="hljs-string">""</span>) 
    <span class="hljs-comment">// 服务器设定的时区,一般为CST</span>
    loc, err := time.LoadLocation(<span class="hljs-string">"Local"</span>)
    <span class="hljs-comment">// 美国洛杉矶PDT</span>
    loc, err := time.LoadLocation(<span class="hljs-string">"America/Los_Angeles"</span>)

    <span class="hljs-comment">// 获取指定时区的时间点</span>
    local, _ := time.LoadLocation(<span class="hljs-string">"America/Los_Angeles"</span>)
    fmt.Println(time.Date<span class="hljs-number">(2018</span><span class="hljs-number">,1</span><span class="hljs-number">,1</span><span class="hljs-number">,12</span><span class="hljs-number">,0</span><span class="hljs-number">,0</span><span class="hljs-number">,0</span>, local))</code>

可以在 $GOROOT/lib/time/zoneinfo.zip 文件下看到所有时区。

时间运算

好了,基础的类型我们介绍完,现在开始时间运算相关的函数,也是日常业务中我们大量应用的。

<code class="language-go hljs  has-numbering">      <span class="hljs-comment">// func Sleep(d Duration)   休眠多少时间,休眠时处于阻塞状态,后续程序无法执行</span>
      time.Sleep(time.Duration<span class="hljs-number">(10</span>) * time.Second)

      <span class="hljs-comment">// func After(d Duration) <-chan Time  非阻塞,可用于延迟</span>
      time.After(time.Duration<span class="hljs-number">(10</span>) * time.Second)

      <span class="hljs-comment">// func Since(t Time) Duration 两个时间点的间隔</span>
      start := time.Now()
      fmt.Println(time.Since(start))   <span class="hljs-comment">// 等价于 Now().Sub(t), 可用来计算一段业务的消耗时间</span>

      <span class="hljs-keyword">func</span> Until(t Time) Duration     <span class="hljs-comment">//  等价于 t.Sub(Now()),t与当前时间的间隔</span>

      <span class="hljs-comment">// func (t Time) Add(d Duration) Time</span>
      fmt.Println(dt.Add(time.Duration<span class="hljs-number">(10</span>) * time.Second))   <span class="hljs-comment">// 加</span>

      <span class="hljs-keyword">func</span> (t Time) Sub(u Time) Duration                    <span class="hljs-comment">// 减 </span>

      <span class="hljs-comment">// func (t Time) AddDate(years int, months int, days int) Time</span>
      fmt.Println(dt.AddDate<span class="hljs-number">(1</span>,<span class="hljs-number"> 1</span>,<span class="hljs-number"> 1</span>))

      <span class="hljs-comment">// func (t Time) Before(u Time) bool</span>
      <span class="hljs-comment">// func (t Time) After(u Time) bool</span>
      <span class="hljs-comment">// func (t Time) Equal(u Time) bool          比较时间点时尽量使用Equal函数 </span></code>

我们大概就介绍完了多数涉及时间点与时间段的函数,接下面我们通过一些使用场景来做一些演示。

使用场景

日期时间差

<code class="language-go hljs  has-numbering">      dt1 := time.Date<span class="hljs-number">(2018</span>,<span class="hljs-number"> 1</span>,<span class="hljs-number"> 10</span>,<span class="hljs-number"> 0</span>,<span class="hljs-number"> 0</span>,<span class="hljs-number"> 1</span>,<span class="hljs-number"> 100</span>, time.Local)
      dt2 := time.Date<span class="hljs-number">(2018</span>,<span class="hljs-number"> 1</span>,<span class="hljs-number"> 9</span>,<span class="hljs-number"> 23</span>,<span class="hljs-number"> 59</span>,<span class="hljs-number"> 22</span>,<span class="hljs-number"> 100</span>, time.Local)
      <span class="hljs-comment">// 不用关注时区,go会转换成时间戳进行计算</span>
      fmt.Println(dt1.Sub(dt2))        </code>

基于当前时间的前后运算

<code class="language-go hljs  has-numbering">      now := time.Now()

      <span class="hljs-comment">// 一年零一个月一天之后</span>
      fmt.Println(now.Date<span class="hljs-number">(1</span><span class="hljs-number">,1</span><span class="hljs-number">,1</span>))
      <span class="hljs-comment">// 一段时间之后</span>
      fmt.Println(now.Add(time.Duration<span class="hljs-number">(10</span>)*time.Minute))

      <span class="hljs-comment">// 计算两个时间点的相差天数</span>
      dt1 = time.Date(dt1.Year(), dt1.Month(), dt1.Day(),<span class="hljs-number"> 0</span>,<span class="hljs-number"> 0</span>,<span class="hljs-number"> 0</span>,<span class="hljs-number"> 0</span>, time.Local)
      dt2 = time.Date(dt2.Year(), dt2.Month(), dt2.Day(),<span class="hljs-number"> 0</span>,<span class="hljs-number"> 0</span>,<span class="hljs-number"> 0</span>,<span class="hljs-number"> 0</span>, time.Local)
      fmt.Println(<span class="hljs-typename">int</span>(math.Ceil(dt1.Sub(dt2).Hours() /<span class="hljs-number"> 24</span>)))</code>

时区转换

<code class="language-go hljs  has-numbering">      <span class="hljs-comment">// time.Local 用来表示当前服务器时区</span>
      <span class="hljs-comment">// 自定义地区时间</span>
      secondsEastOfUTC := <span class="hljs-typename">int</span>(<span class="hljs-number">(8</span> * time.Hour).Seconds())
      beijing := time.FixedZone(<span class="hljs-string">"Beijing Time"</span>, secondsEastOfUTC)
      fmt.Println(time.Date<span class="hljs-number">(2018</span><span class="hljs-number">,1</span><span class="hljs-number">,2</span><span class="hljs-number">,0</span><span class="hljs-number">,0</span><span class="hljs-number">,0</span><span class="hljs-number">,0</span>, beijing))  <span class="hljs-comment">// 2018-01-02 00:00:00 +0800 Beijing Time  </span>

      <span class="hljs-comment">// 当前时间转为指定时区时间</span>
      fmt.Println(time.Now().In(beijing))

      <span class="hljs-comment">// 指定时间转换成指定时区对应的时间</span>
      dt, err := time.ParseInLocation(<span class="hljs-string">"2006-01-02 15:04:05"</span>, <span class="hljs-string">"2017-05-11 14:06:06"</span>, time.Local)

      <span class="hljs-comment">// 当前时间在零时区年月日   时分秒  时区</span>
      year, mon, day := time.Now().UTC().Date()     <span class="hljs-comment">// 2018 April 24 </span>
      hour, min, sec := time.Now().UTC().Clock()    <span class="hljs-comment">// 3 47 15</span>
      zone, _ := time.Now().UTC().Zone()            <span class="hljs-comment">// UTC</span></code>

比较两个时间点

<code class="language-go hljs  has-numbering">      dt := time.Date<span class="hljs-number">(2018</span>,<span class="hljs-number"> 1</span>,<span class="hljs-number"> 10</span>,<span class="hljs-number"> 0</span>,<span class="hljs-number"> 0</span>,<span class="hljs-number"> 1</span>,<span class="hljs-number"> 100</span>, time.Local)
      fmt.Println(time.Now().After(dt))     <span class="hljs-comment">// true</span>
      fmt.Println(time.Now().Before(dt))    <span class="hljs-comment">// false</span>

      <span class="hljs-comment">// 是否相等 判断两个时间点是否相等时推荐使用 Equal 函数</span>
</code>

设置执行时间

通过time.After 函数与 select 结合使用可用于处理程序超时设定

<code class="language-go hljs  has-numbering">      <span class="hljs-keyword">select</span> {
      <span class="hljs-keyword">case</span> m := <- c:
            <span class="hljs-comment">// do something</span>
      <span class="hljs-keyword">case</span> <- time.After(time.Duration<span class="hljs-number">(1</span>)*time.Second):
            fmt.Println(<span class="hljs-string">"time out"</span>)
      }</code>

Ticker类型

Ticker 类型包含一个 channel,有时我们会遇到每隔一段时间执行的业务(比如设置心跳时间等),就可以用它来处理,这是一个重复的过程

<code class="language-go hljs  has-numbering">      <span class="hljs-comment">// 无法取消</span>
      tick := time.Tick<span class="hljs-number">(1</span> * time.Minute)
      <span class="hljs-keyword">for</span> _ = <span class="hljs-keyword">range</span> tick {
            <span class="hljs-comment">// do something</span>
      }

      <span class="hljs-comment">// 可通过调用ticker.Stop取消</span>
      ticker := time.NewTicker<span class="hljs-number">(1</span> * time.Minute)
      <span class="hljs-keyword">for</span> _ = <span class="hljs-keyword">range</span> tick {
            <span class="hljs-comment">// do something</span>
      }</code>

Timer类型

Timer 类型用来代表一个单独的事件,当设置的时间过期后,发送当前的时间到 channel, 我们可以通过以下两种方式来创建

<code class="language-go hljs  has-numbering">      <span class="hljs-keyword">func</span> AfterFunc(d Duration, f <span class="hljs-keyword">func</span>()) *Timer   <span class="hljs-comment">// 指定一段时间后指定的函数</span>
      <span class="hljs-keyword">func</span> NewTimer(d Duration) *Timer     </code>

以上两函数都可以使用 Reset, 这个有个需要注意的地方是使用 Reset 时需要确保 t.C 通道被释放时才能调用,以防止发生资源竞争的问题,可通过以下方式解决

<code class="language-go hljs  has-numbering">      <span class="hljs-keyword">if</span> !t.Stop() {
            <-t.C
      }
      t.Reset(d)</code>

小爱博客 , 版权所有
转载请注明原文链接:golang包time用法详解
喜欢 (0)
【你的支持, 我的动力】
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址