🔵
TimeCraft

Golang Timestamp

Golang时间戳转换完整教程

掌握Go语言time包处理Unix时间戳的所有技巧,包含获取、转换、格式化和时区处理的详细代码示例。

获取当前时间戳

使用time包获取当前Unix时间戳

Go
package main

import (
    "fmt"
    "time"
)

func main() {
    // 获取当前时间戳(秒级)
    timestamp := time.Now().Unix()
    fmt.Println(timestamp)  // 1735660800

    // 获取当前时间戳(毫秒级)
    timestampMs := time.Now().UnixMilli()
    fmt.Println(timestampMs)  // 1735660800000

    // 获取当前时间戳(微秒级)
    timestampUs := time.Now().UnixMicro()
    fmt.Println(timestampUs)  // 1735660800000000

    // 获取当前时间戳(纳秒级)
    timestampNs := time.Now().UnixNano()
    fmt.Println(timestampNs)  // 1735660800000000000
}

时间戳转日期

将Unix时间戳转换为Time对象或格式化字符串

Go
package main

import (
    "fmt"
    "time"
)

func main() {
    // 时间戳转Time对象
    timestamp := int64(1735660800)
    t := time.Unix(timestamp, 0)  // 第二参数是纳秒
    
    // 格式化输出
    fmt.Println(t.Format("2006-01-02 15:04:05"))  // 2025-01-01 00:00:00
    fmt.Println(t.Format("2006/01/02"))            // 2025/01/01
    fmt.Println(t.Format("15:04:05"))              // 00:00:00
    fmt.Println(t.Format("2006年01月02日 15时04分05秒"))  // 2025年01月01日 00时00分00秒

    // 毫秒时间戳转换
    timestampMs := int64(1735660800000)
    tMs := time.UnixMilli(timestampMs)
    fmt.Println(tMs.Format("2006-01-02 15:04:05.000"))

    // 获取各个时间字段
    fmt.Printf("年: %d\n", t.Year())
    fmt.Printf("月: %d\n", t.Month())
    fmt.Printf("日: %d\n", t.Day())
    fmt.Printf("时: %d\n", t.Hour())
    fmt.Printf("分: %d\n", t.Minute())
    fmt.Printf("秒: %d\n", t.Second())
}

日期转时间戳

将日期字符串或Time对象转换为Unix时间戳

Go
package main

import (
    "fmt"
    "time"
)

func main() {
    // 创建指定日期的Time对象
    t := time.Date(2025, 1, 1, 0, 0, 0, 0, time.Local)
    timestamp := t.Unix()
    fmt.Println(timestamp)  // 1735660800

    // 解析日期字符串
    layout := "2006-01-02 15:04:05"
    t2, err := time.Parse(layout, "2025-01-01 00:00:00")
    if err != nil {
        panic(err)
    }
    fmt.Println(t2.Unix())

    // 解析带时区的日期字符串
    t3, err := time.Parse(time.RFC3339, "2025-01-01T00:00:00+08:00")
    if err != nil {
        panic(err)
    }
    fmt.Println(t3.Unix())

    // 使用ParseInLocation解析本地时间
    loc, _ := time.LoadLocation("Asia/Shanghai")
    t4, err := time.ParseInLocation("2006-01-02 15:04:05", "2025-01-01 00:00:00", loc)
    if err != nil {
        panic(err)
    }
    fmt.Println(t4.Unix())
}

日期格式化

将日期格式化为各种显示格式(注意Go的特殊格式化方式)

Go
package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Unix(1735660800, 0)

    // Go使用参考时间: 2006-01-02 15:04:05
    // 2006 = 年, 01 = 月, 02 = 日
    // 15 = 时(24小时制), 04 = 分, 05 = 秒

    // 常用格式
    fmt.Println(t.Format("2006-01-02"))              // 2025-01-01
    fmt.Println(t.Format("2006/01/02 15:04:05"))     // 2025/01/01 00:00:00
    fmt.Println(t.Format("2006-01-02T15:04:05Z07:00"))  // ISO 8601
    fmt.Println(t.Format("Jan 02, 2006"))            // Jan 01, 2025
    fmt.Println(t.Format("Monday, January 02, 2006")) // Wednesday, January 01, 2025

    // 时间戳格式化(毫秒)
    fmt.Println(t.Format("2006-01-02 15:04:05.000"))

    // 预定义格式
    fmt.Println(t.Format(time.RFC3339))      // 2025-01-01T00:00:00Z
    fmt.Println(t.Format(time.RFC1123))      // Wed, 01 Jan 2025 00:00:00 UTC
    fmt.Println(t.Format(time.Kitchen))      // 12:00AM

    // 中文格式
    fmt.Println(t.Format("2006年01月02日 15时04分05秒"))
}

时区处理

处理不同时区的时间戳转换

Go
package main

import (
    "fmt"
    "time"
)

func main() {
    // 获取本地时区
    loc := time.Local
    fmt.Println("本地时区:", loc)

    // 加载指定时区
    shanghai, _ := time.LoadLocation("Asia/Shanghai")
    newYork, _ := time.LoadLocation("America/New_York")
    utc := time.UTC

    // 当前时间在不同时区
    now := time.Now()
    fmt.Println("本地:", now.Format("2006-01-02 15:04:05"))
    fmt.Println("UTC:", now.In(utc).Format("2006-01-02 15:04:05"))
    fmt.Println("上海:", now.In(shanghai).Format("2006-01-02 15:04:05"))
    fmt.Println("纽约:", now.In(newYork).Format("2006-01-02 15:04:05"))

    // 时间戳转指定时区
    timestamp := int64(1735660800)
    t := time.Unix(timestamp, 0)
    fmt.Println("上海时间:", t.In(shanghai).Format("2006-01-02 15:04:05"))
    fmt.Println("纽约时间:", t.In(newYork).Format("2006-01-02 15:04:05"))

    // 创建指定时区的时间
    t2 := time.Date(2025, 1, 1, 0, 0, 0, 0, shanghai)
    fmt.Println(t2.Unix())  // 上海时区的时间戳
}

常用时间操作

时间计算、比较等常用操作

Go
package main

import (
    "fmt"
    "time"
)

func main() {
    // 时间加减
    now := time.Now()
    tomorrow := now.Add(24 * time.Hour)
    nextWeek := now.AddDate(0, 0, 7)      // 加7天
    nextMonth := now.AddDate(0, 1, 0)     // 加1个月
    nextYear := now.AddDate(1, 0, 0)      // 加1年

    // 时间差计算
    start := time.Now()
    // ... 执行一些操作
    elapsed := time.Since(start)
    fmt.Printf("耗时: %v\n", elapsed)
    fmt.Printf("耗时: %d 毫秒\n", elapsed.Milliseconds())

    // 两个时间的差
    t1 := time.Date(2025, 1, 1, 0, 0, 0, 0, time.Local)
    t2 := time.Date(2025, 1, 15, 12, 0, 0, 0, time.Local)
    diff := t2.Sub(t1)
    fmt.Printf("相差: %v\n", diff)               // 相差: 348h0m0s
    fmt.Printf("相差: %.1f 小时\n", diff.Hours())
    fmt.Printf("相差: %d 天\n", int(diff.Hours())/24)

    // 时间比较
    fmt.Println(t1.Before(t2))  // true
    fmt.Println(t1.After(t2))   // false
    fmt.Println(t1.Equal(t2))   // false

    // 定时器
    ticker := time.NewTicker(1 * time.Second)
    defer ticker.Stop()
    for i := 0; i < 3; i++ {
        <-ticker.C
        fmt.Println("Tick at", time.Now().Format("15:04:05"))
    }
}

最佳实践

  • 格式化时间使用"2006-01-02 15:04:05"这个固定模板
  • 存储时间时使用Unix时间戳,避免时区问题
  • 使用time.Since()和time.Until()计算时间差更简洁
  • Go 1.17+推荐使用UnixMilli()和UnixMicro()方法

常见问题

Go的格式化时间为什么用2006-01-02 15:04:05?

Go使用这个特定的时间作为参考时间,每个数字代表一个时间单位:2006是年、01是月、02是日、15是时(24小时制)、04是分、05是秒。这样做比使用YYYY-MM-DD更不容易出错。

time.Now()返回的是什么时区?

time.Now()返回的是本地时区的时间。可以使用In()方法转换时区,如time.Now().In(time.UTC)转换为UTC时间。

如何解析不同格式的日期字符串?

使用time.Parse()解析不带时区的字符串(返回UTC时间),使用time.ParseInLocation()解析带时区的字符串。需要根据日期格式编写对应的layout。

time.Unix()和time.UnixMilli()的区别?

time.Unix(sec, nsec)接受秒和纳秒两个参数,time.UnixMilli(ms)接受毫秒。Go 1.17+增加了UnixMilli()和UnixMicro()方便毫秒和微秒时间戳的转换。