如何将Unix时间戳解析为time.Time类型的时间?

huangapple go评论109阅读模式
英文:

How to parse unix timestamp to time.Time

问题

我正在尝试解析一个Unix时间戳,但是我得到了一个超出范围的错误。这对我来说并没有太多意义,因为布局是正确的(就像Go文档中所示):

package main

import "fmt"
import "time"

func main() {
    tm, err := time.Parse("1136239445", "1405544146")
    if err != nil{
        panic(err)
    }

    fmt.Println(tm)
}

Playground

英文:

I'm trying to parse an Unix timestamp but I get out of range error. That doesn't really makes sense to me, because the layout is correct (as in the Go docs):

package main

import "fmt"
import "time"

func main() {
    tm, err := time.Parse("1136239445", "1405544146")
    if err != nil{
        panic(err)
    }

    fmt.Println(tm)
}

Playground

答案1

得分: 395

time.Parse函数不能解析Unix时间戳。相反,你可以使用strconv.ParseInt将字符串解析为int64,然后使用time.Unix创建时间戳:

package main

import (
	"fmt"
	"time"
	"strconv"
)

func main() {
	i, err := strconv.ParseInt("1405544146", 10, 64)
	if err != nil {
		panic(err)
	}
	tm := time.Unix(i, 0)
	fmt.Println(tm)
}

输出:

2014-07-16 20:55:46 +0000 UTC

Playground: http://play.golang.org/p/v_j6UIro7a

编辑:

strconv.Atoi更改为strconv.ParseInt,以避免在32位系统上发生整数溢出。

英文:

The time.Parse function does not do Unix timestamps. Instead you can use strconv.ParseInt to parse the string to int64 and create the timestamp with time.Unix:

package main

import (
	"fmt"
	"time"
	"strconv"
)

func main() {
	i, err := strconv.ParseInt("1405544146", 10, 64)
	if err != nil {
		panic(err)
	}
	tm := time.Unix(i, 0)
	fmt.Println(tm)
}

Output:

2014-07-16 20:55:46 +0000 UTC

Playground: http://play.golang.org/p/v_j6UIro7a

Edit:

Changed from strconv.Atoi to strconv.ParseInt to avoid int overflows on 32 bit systems.

答案2

得分: 29

你可以直接使用time包中的time.Unix函数,将Unix时间戳转换为UTC时间。

package main

import (
	"fmt"
	"time"
)

func main() {
	unixTimeUTC := time.Unix(1405544146, 0) // 在UTC时区下获取Unix时间戳

	unitTimeInRFC3339 := unixTimeUTC.Format(time.RFC3339) // 将UTC时间转换为RFC3339格式

	fmt.Println("unix时间戳在UTC时区下:---", unixTimeUTC)
	fmt.Println("unix时间戳在unitTimeInRFC3339格式下:---", unitTimeInRFC3339)
}

输出结果:

unix时间戳在UTC时区下:--- 2014-07-16 20:55:46 +0000 UTC
unix时间戳在unitTimeInRFC3339格式下:--- 2014-07-16T20:55:46Z

在Go Playground中查看:https://play.golang.org/p/5FtRdnkxAd

英文:

You can directly use time.Unix function of time which converts the unix time stamp to UTC

package main

import (
  "fmt"
  "time"
)


func main() {
	unixTimeUTC:=time.Unix(1405544146, 0) //gives unix time stamp in utc 

    unitTimeInRFC3339 :=unixTimeUTC.Format(time.RFC3339) // converts utc time to RFC3339 format

	fmt.Println("unix time stamp in UTC :--->",unixTimeUTC)
    fmt.Println("unix time stamp in unitTimeInRFC3339 format :->",unitTimeInRFC3339)
}

Output

unix time stamp in UTC :---> 2014-07-16 20:55:46 +0000 UTC
unix time stamp in unitTimeInRFC3339 format :----> 2014-07-16T20:55:46Z

Check in Go Playground: https://play.golang.org/p/5FtRdnkxAd

答案3

得分: 6

分享一些我为日期创建的函数:

请注意,我想要获取特定位置的时间(不仅仅是UTC时间)。如果你想要UTC时间,只需删除loc变量和.In(loc)函数调用。

func GetTimeStamp() string {
    loc, _ := time.LoadLocation("America/Los_Angeles")
    t := time.Now().In(loc)
    return t.Format("20060102150405")
}

func GetTodaysDate() string {
    loc, _ := time.LoadLocation("America/Los_Angeles")
    current_time := time.Now().In(loc)
    return current_time.Format("2006-01-02")
}

func GetTodaysDateTime() string {
    loc, _ := time.LoadLocation("America/Los_Angeles")
    current_time := time.Now().In(loc)
    return current_time.Format("2006-01-02 15:04:05")
}

func GetTodaysDateTimeFormatted() string {
    loc, _ := time.LoadLocation("America/Los_Angeles")
    current_time := time.Now().In(loc)
    return current_time.Format("Jan 2, 2006 at 3:04 PM")
}

func GetTimeStampFromDate(dtformat string) string {
    form := "Jan 2, 2006 at 3:04 PM"
    t2, _ := time.Parse(form, dtformat)
    return t2.Format("20060102150405")
}

以上是我创建的几个日期函数。

英文:

Sharing a few functions which I created for dates:

Please note that I wanted to get time for a particular location (not just UTC time). If you want UTC time, just remove loc variable and .In(loc) function call.

func GetTimeStamp() string {
     loc, _ := time.LoadLocation("America/Los_Angeles")
     t := time.Now().In(loc)
     return t.Format("20060102150405")
}
func GetTodaysDate() string {
    loc, _ := time.LoadLocation("America/Los_Angeles")
    current_time := time.Now().In(loc)
    return current_time.Format("2006-01-02")
}

func GetTodaysDateTime() string {
    loc, _ := time.LoadLocation("America/Los_Angeles")
    current_time := time.Now().In(loc)
    return current_time.Format("2006-01-02 15:04:05")
}

func GetTodaysDateTimeFormatted() string {
    loc, _ := time.LoadLocation("America/Los_Angeles")
    current_time := time.Now().In(loc)
    return current_time.Format("Jan 2, 2006 at 3:04 PM")
}

func GetTimeStampFromDate(dtformat string) string {
    form := "Jan 2, 2006 at 3:04 PM"
    t2, _ := time.Parse(form, dtformat)
    return t2.Format("20060102150405")
}

答案4

得分: 5

对于毫秒级 Unix 时间戳精度,在 go1.18 中的代码如下:

    i, err := strconv.ParseInt("1652084489543", 10, 64)
    if err != nil {
        panic(err)
    }
    tm := time.UnixMilli(i)
    fmt.Println(tm)

请注意,这段代码将字符串 "1652084489543" 解析为 int64 类型的整数,并使用 time.UnixMilli 函数将其转换为对应的时间。最后,使用 fmt.Println 打印出该时间。

英文:

for millis unix timestamp precision, in go1.18

    i, err := strconv.ParseInt("1652084489543", 10, 64)
    if err != nil {
        panic(err)
    }
    tm := time.UnixMilli(i)
    fmt.Println(tm)

答案5

得分: 4

这是一个旧问题,但我注意到缺少一个实用的答案。

例如,我们正在使用MavLink协议工作,需要处理一个在此处定义的结构的消息。

如果我们有以下数据结构:

字段名 类型 单位 描述
time_boot_ms uint64_t ms 时间戳(系统启动后的时间)。
press_abs float hPa 绝对压力
press_diff float hPa 差分压力1
temperature int16_t cdegC 绝对压力温度
temperature_press_diff ** int16_t cdegC 差分压力温度(如果不可用,则为0)。将值为0(或1)报告为1 cdegC。

因此,我们接收到需要使用time_boot_ms作为参考将其插入数据库并与其他消息同步的常量更新。

我们可以做什么?

正如我们注意到的,时间以毫秒为单位,而且每个有一些Go经验的人都知道,由于某种未知的原因,将毫秒分辨率的Unix timestamp转换为time.Time非常复杂。内置的time.Unix()函数只支持秒和纳秒精度。

如何获得毫秒精度?

嗯,我们可以等到他们发布Go1.7版本,或者我们可以将毫秒乘以纳秒,或将其分为秒和纳秒。

让我们实现第二个想法,将其分为秒和纳秒:

unixUTCtime := time.Unix(ms/int64(1000), (ms%int64(1000))*int64(1000000))

现在我们可以将其封装在一个func中,并在我们的主函数中使用它,如下所示:

package main

import (
    "fmt"
    "time"
)

const msInSecond int64 = 1e3
const nsInMillisecond int64 = 1e6

// UnixToMS 将毫秒级Unix Epoch转换为time.Time
func UnixToMS (ms int64) time.Time {
    return time.Unix(ms/msInSecond, (ms%msInSecond)*nsInMillisecond)
}


func main() {
    unixTimes := [...]int64{758991688, 758992188, 758992690, 758993186}
    var unixUTCTimes []time.Time
    for index, unixTime := range unixTimes {
        unixUTCTimes = append(unixUTCTimes, UnixToMS(unixTime))
        if index > 0 {
            timeDifference := unixUTCTimes[index].Sub(unixUTCTimes[index-1])
            fmt.Println("Time difference in ms :-->", timeDifference)
        }
    }
}

输出将是:

Time difference in ms :--> 500ms
Time difference in ms :--> 502ms
Time difference in ms :--> 496ms

在Go Playground中查看

更新

1.7版本开始,go现在提供了毫秒级分辨率,可以使用time.UnixMilli函数将以int64数字表示的Unix时间转换为Time类型(纳秒精度),或者使用UnixMilli函数将Time转换为毫秒精度。这是它们的实现:

func Unix(sec int64, nsec int64) Time {
    if nsec < 0 || nsec >= 1e9 {
        n := nsec / 1e9
        sec += n
        nsec -= n * 1e9
        if nsec < 0 {
            nsec += 1e9
            sec--
        }
    }
    return unixTime(sec, int32(nsec))
}


func UnixMilli(msec int64) Time {
    return Unix(msec/1e3, (msec%1e3)*1e6)
}

func (t Time) UnixMilli() int64 {
    return t.unixSec()*1e3 + int64(t.nsec())/1e6
}

如何使用这个方法?

非常简单,只需修改我们示例的先前实现中的此行:

unixUTCTimes = append(unixUTCTimes, UnixToMS(unixTime))

使用以下代码替换:

unixUTCTimes = append(unixUTCTimes, time.UnixMilli(unixTime))

不需要其他函数,只需调用time.UnixMilli(unixTime)。在此处查看playground

英文:

This is an old question but I noticed that a practical answer is missing.

For example, we were working with the MavLink protocol and we need to process a message with a structure defined here.

If we have this data structure:

Field Name Type Units Description
time_boot_ms uint64_t ms Timestamp (time since system boot).
press_abs float hPa Absolute pressure
press_diff float hPa Differential pressure 1
temperature int16_t cdegC Absolute pressure temperature
temperature_press_diff ** int16_t cdegC Differential pressure temperature (0, if not available). Report values of 0 (or 1) as 1 cdegC.

So, we receive constant updates that we need to process using the time_boot_ms as reference to insert them on the database and synchronize them with other messages.

What can we do?

As we noticed, the time is in milliseconds and everyone, that has some experience with Go, knows that for some unknown reason it's just way too complex to convert a millisecond resolution Unix timestamp to time.Time. The built-in time.Unix() function only supports second and nanosecond precision.

How we can get millisecond precision?

Well, we might wait until they release the version 1.7 of Go or we either have to multiply the milliseconds to nanoseconds or split them into seconds and nanoseconds.

Lets implement the second idea, spit the into seconds and nanoseconds:

unixUTCtime := time.Unix(ms/int64(1000), (ms%int64(1000))*int64(1000000))

Now we can encapsulate it in a func and use it in our main like this:

package main

import (
    &quot;fmt&quot;
    &quot;time&quot;
)

const msInSecond int64 = 1e3
const nsInMillisecond int64 = 1e6

// UnixToMS Converts Unix Epoch from milliseconds to time.Time
func UnixToMS (ms int64) time.Time {
    return time.Unix(ms/msInSecond, (ms%msInSecond)*nsInMillisecond)
}


func main() {
	unixTimes := [...]int64{758991688, 758992188, 758992690, 758993186}
	var unixUTCTimes []time.Time
	for index, unixTime := range unixTimes {
		unixUTCTimes = append(unixUTCTimes, UnixToMS(unixTime))
		if index &gt; 0 {
			timeDifference := unixUTCTimes[index].Sub(unixUTCTimes[index-1])
			fmt.Println(&quot;Time difference in ms :---&gt;&quot;, timeDifference)
		}
	}
}

The output will be:

Time difference in ms :---&gt; 500ms
Time difference in ms :---&gt; 502ms
Time difference in ms :---&gt; 496ms

Check in Go Playground

Update

From version 1.7, go now provides millisecond resolution either to convert a unix time represented as a int64 number into a Time type (nanosecond precision) using time.UnixMilli function or from Time into millisecond precision using UnixMilli function. This is their implementation:

func Unix(sec int64, nsec int64) Time {
	if nsec &lt; 0 || nsec &gt;= 1e9 {
		n := nsec / 1e9
		sec += n
		nsec -= n * 1e9
		if nsec &lt; 0 {
			nsec += 1e9
			sec--
		}
	}
	return unixTime(sec, int32(nsec))
}


func UnixMilli(msec int64) Time {
	return Unix(msec/1e3, (msec%1e3)*1e6)
}

func (t Time) UnixMilli() int64 {
	return t.unixSec()*1e3 + int64(t.nsec())/1e6
}

How to use this Teo?

Very simple just modify this line from the previous implementation of our example:

unixUTCTimes = append(unixUTCTimes, UnixToMS(unixTime))

with this code:

unixUTCTimes = append(unixUTCTimes, time.UnixMilli(unixTime))

No need of other functions just call time.UnixMilli(unixTime). Check the playground here.

答案6

得分: 3

我会帮你翻译以下内容:

我经常记录日志,其中时间戳是float64类型,并使用这个函数将时间戳转换为字符串:

func dateFormat(layout string, d float64) string{
    intTime := int64(d)
    t := time.Unix(intTime, 0)
    if layout == "" {
        layout = "2006-01-02 15:04:05"
    }
    return t.Format(layout)
}

请注意,这是一个用于将时间戳转换为字符串的Go语言函数。

英文:

I do a lot of logging where the timestamps are float64 and use this function to get the timestamps as string:

func dateFormat(layout string, d float64) string{
	intTime := int64(d)
	t := time.Unix(intTime, 0)
	if layout == &quot;&quot; {
		layout = &quot;2006-01-02 15:04:05&quot;
	}
	return t.Format(layout)
}

答案7

得分: 2

根据Go文档,Unix返回本地时间。

> Unix返回与给定的Unix时间相对应的本地时间

这意味着输出将取决于代码运行的机器,这通常是你所需要的,但有时你可能希望得到UTC时间的值。

为了实现这一点,我修改了代码片段,使其返回UTC时间:

i, err := strconv.ParseInt("1405544146", 10, 64)
if err != nil {
    panic(err)
}
tm := time.Unix(i, 0)
fmt.Println(tm.UTC())

在我的机器上(CEST时区),这将打印:

2014-07-16 20:55:46 +0000 UTC
英文:

According to the go documentation, Unix returns a local time.

> Unix returns the local Time corresponding to the given Unix time

This means the output would depend on the machine your code runs on, which, most often is what you need, but sometimes, you may want to have the value in UTC.

To do so, I adapted the snippet to make it return a time in UTC:

i, err := strconv.ParseInt(&quot;1405544146&quot;, 10, 64)
if err != nil {
	panic(err)
}
tm := time.Unix(i, 0)
fmt.Println(tm.UTC())

This prints on my machine (in CEST)

2014-07-16 20:55:46 +0000 UTC

huangapple
  • 本文由 发表于 2014年7月28日 08:45:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/24987131.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定