在Linux和macOS上的Go中RFC3339的时间格式化结果不同

时间:2019-03-29 02:44:17

标签: go time format rfc3339

我在下面运行了go代码。

package main

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

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

}

然后在Linux上的结果是

2014-07-16T20:55:46Z
2006-01-02T15:04:05Z07:00

在macOS上是

2014-07-17T05:55:46+09:00
2006-01-02T15:04:05Z07:00

这是同一时间,但格式化结果不同。你知道原因吗?

4 个答案:

答案 0 :(得分:1)

不要下结论。检查所有证据。例如,考虑当地时区。

  

Package time

import "time" 
     

func Unix

func Unix(sec int64, nsec int64) Time
     

Unix返回与给定Unix时间sec相对应的本地时间   自1970年1月1日世界标准时间以来的秒和nsec纳秒。


例如,

package main

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

func main() {
    i, err := strconv.ParseInt("1405544146", 10, 64)
    if err != nil {
        panic(err)
    }
    t := time.Unix(i, 0)
    fmt.Println(t)
    fmt.Println(t.Format(time.RFC3339))
    fmt.Println(time.RFC3339)
    fmt.Println(runtime.GOOS, runtime.GOARCH, runtime.Version())
}

游乐场:https://play.golang.org/p/UH6o57YckiV

输出(游乐场):

2014-07-16 20:55:46 +0000 UTC
2014-07-16T20:55:46Z
2006-01-02T15:04:05Z07:00
nacl amd64p32 go1.12

输出(Linux):

2014-07-16 16:55:46 -0400 EDT
2014-07-16T16:55:46-04:00
2006-01-02T15:04:05Z07:00
linux amd64 devel +5b68cb65d3 Thu Mar 28 23:49:52 2019 +0000

不同的时区(UTC与EDT),因此格式化的日期和时间也不同。


在您的示例中,您有2014-07-16T20:55:46Z2014-07-17T05:55:46+09:00,不同的时区,因此格式不同的日期和时间。

答案 1 :(得分:1)

private void download() { StorageReference sr = FirebaseStorage.getInstance().getReference().child("text.txt"); Log.d("keys tasksnapshot anf", sr.toString()); try { File localFile = File.createTempFile("text", "txt"); sr.getFile(localFile) .addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() { @Override public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) { Log.d("keys: tasksnapshot", taskSnapshot.toString()); } }); } catch (Exception e) { e.printStackTrace(); } openFile(); } private void openFile() { FileInputStream fis = null; try { fis = openFileInput("text.txt"); InputStreamReader isr = new InputStreamReader(fis); BufferedReader bufferedReader = new BufferedReader(isr); StringBuilder sb = new StringBuilder(); String line; while ((line = bufferedReader.readLine()) != null) { sb.append(line); } TextView textView = findViewById(R.id.tv); textView.setText(sb.toString()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } 2014-07-16T20:55:46Z的时区不同。

time.RFC3339是常量。 https://golang.org/pkg/time/#RFC3339

2014-07-17T05:55:46+09:00

使用数字时间或Z触发ISO 8601。

数字时区偏移格式如下:

const (
        // ...
        RFC3339     = "2006-01-02T15:04:05Z07:00"
        RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
        // ...
)

并用Z替换格式中的符号会触发ISO 8601打印Z的行为,而不是UTC区域的偏移。

-0700  ±hhmm
-07:00 ±hh:mm
-07    ±hh

答案 2 :(得分:0)

两个不同的操作系统为相同的输入产生不同的输出的原因是由于操作系统的时区配置。 Linux框上的时区似乎没有未设置

go将尝试从本地操作系统获取时区。如果不可用,则默认为UTC。如果要从MacOS和Linux获得一致的输出,请确保时区相同。要明确地执行此操作,请设置TZ环境变量。这将适用于Linux和MacOS等。

$ go build -o gotime ./main.go

$ uname -s
Linux
$ TZ=CET ./gotime 
2014-07-16T22:55:46+02:00
2006-01-02T15:04:05Z07:00

$ TZ="" ./gotime 
2014-07-16T20:55:46Z
2006-01-02T15:04:05Z07:00

$ uname -s
Darwin
$ TZ=CET ./gotime
2014-07-16T22:55:46+02:00
2006-01-02T15:04:05Z07:00

$ TZ="" ./gotime
2014-07-16T20:55:46Z
2006-01-02T15:04:05Z07:00

答案 3 :(得分:0)

此问题归因于golang上的时间位置。

Linux golang的默认时间位置为“ UTC”,而MacOS golang的默认时间位置为“ Local”。 (“本地”使用操作系统的时间位置。)

您可以检查时间位置。

fmt.Println(time.Local) // Result of MacOS is "Local"

如果要从MacOS获得“ UTC”结果,则应使用“输入”功能。

lo, _ := time.LoadLocation("UTC")    
tmUTC := time.Unix(1405544146, 0).In(lo).Format(time.RFC3339)

如果在MacOS上运行代码,则可以获得类似linux的结果。

i, err := strconv.ParseInt("1405544146", 10, 64)
if err != nil {
    panic(err)
}
tm := time.Unix(i, 0).Format(time.RFC3339)
fmt.Println(tm)
lo, _ := time.LoadLocation("UTC")
tmUTC := time.Unix(i, 0).In(lo).Format(time.RFC3339)