英文:
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)
}
英文:
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)
}
答案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()
函数只支持秒和纳秒精度。
如何获得毫秒精度?
嗯,我们可以等到他们发布Go的1.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
更新
从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 (
"fmt"
"time"
)
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 > 0 {
timeDifference := unixUTCTimes[index].Sub(unixUTCTimes[index-1])
fmt.Println("Time difference in ms :--->", timeDifference)
}
}
}
The output will be:
Time difference in ms :---> 500ms
Time difference in ms :---> 502ms
Time difference in ms :---> 496ms
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 < 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
}
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 == "" {
layout = "2006-01-02 15:04:05"
}
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("1405544146", 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论