Golang中打印时间格式差异但反射显示相同的问题

Golang中打印时间格式差异但反射显示相同的问题 免责声明: 抱歉,我是新手。>.<

示例: https://play.golang.org/p/qjXY1U6IMEh

预期: 所有6个(reflect.TypeOf)打印结果都相同,但却有4种看起来不同的日期。我本以为至少会打印出4种不同的类型。

问题: 是否有其他方法或包可以明确地从字符串中识别出各种日期/时间格式?

其他想法: 类型不应该打印为‘String’而不是‘time.Time’吗?

6 回复

我认为标准库中没有任何方法可以实现这一点。

我很好奇:你正在进行的什么项目需要了解时间的格式化方式?

更多关于Golang中打印时间格式差异但反射显示相同的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


skillian:

time.Time

我指的是,尽管日期看起来不同,但 time.Time 本质上都是相同的。

这是因为你写的是:reflect.TypeOf(then).String()reflect.TypeOf 会获取一个“类型”对象(类似于 .NET 中的 System.Type 或 Java 中的 java.lang.Class(我想是的;我其实不太了解 Java))。然后你对该类型对象调用 String 方法,从而获得类型的名称。

func main() {
    fmt.Println("hello world")
}

你好,@Gabriel_Marquez,我得到的每一行输出都不同:

t Default Layout: 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
time.Time

n Default Layout: 2020-02-10 09:10:10.01001001 +0000 UTC
time.Time

t US Layout: November 10, 2009
time.Time

n US Layout: February 10, 2020
time.Time

t ISO Layout: 2009-11-10
time.Time

n ISO Layout: 2020-02-10
time.Time

Program exited.

你得到的是什么?

类似于 .NET 中的 System.Type

有没有一个函数可以打印出字符串匹配的常量名称,以便我检查它是否是日期?

例如,如果我有一个字符串是 ‘Mon Jan _2 15:04:05 2006’,它能否告诉我类型是 ‘ANSIC’,而无需我自己构建某种 switch 语句?

time package - time - Go Packages

Package time provides functionality for measuring and displaying time.

是否存在一个你知道的包,仅通过查看一个字符串就能告诉我诸如 ‘layoutUS’ 或 ‘layoutISO’ 这样的信息?

这是一个常见的时间序列化/反序列化问题。让我通过代码示例来解释:

package main

import (
    "fmt"
    "reflect"
    "time"
)

func main() {
    // 原始时间
    t := time.Date(2023, 12, 25, 10, 30, 45, 0, time.UTC)
    
    // 不同格式的字符串表示
    formats := []string{
        time.RFC3339,
        time.RFC1123,
        time.RFC822,
        "2006-01-02 15:04:05",
    }
    
    var times []time.Time
    for _, format := range formats {
        str := t.Format(format)
        parsed, err := time.Parse(format, str)
        if err != nil {
            fmt.Printf("解析错误: %v\n", err)
            continue
        }
        times = append(times, parsed)
    }
    
    // 检查类型和值
    for i, t := range times {
        fmt.Printf("时间%d:\n", i+1)
        fmt.Printf("  反射类型: %v\n", reflect.TypeOf(t))
        fmt.Printf("  实际值: %v\n", t)
        fmt.Printf("  Unix纳秒: %v\n", t.UnixNano())
        fmt.Printf("  相等性检查: %v\n\n", t.Equal(times[0]))
    }
    
    // 使用time.Equal()进行精确比较
    fmt.Println("所有时间是否相等(使用time.Equal):")
    for i := 1; i < len(times); i++ {
        fmt.Printf("时间1 == 时间%d: %v\n", i+1, times[0].Equal(times[i]))
    }
}

关键点解释:

  1. 类型相同但表示不同:所有解析后的值都是 time.Time 类型,但字符串表示不同是因为使用了不同的格式化布局。

  2. 时间相等性检查:使用 time.Equal() 方法而不是 == 操作符来比较时间值,因为 time.Time 包含时区信息。

  3. 识别格式的方法:要识别字符串的具体格式,可以尝试多种解析:

func detectTimeFormat(str string) (string, error) {
    commonFormats := []string{
        time.RFC3339,
        time.RFC3339Nano,
        time.RFC1123,
        time.RFC822,
        "2006-01-02 15:04:05",
        "2006-01-02",
        "15:04:05",
    }
    
    for _, format := range commonFormats {
        if _, err := time.Parse(format, str); err == nil {
            return format, nil
        }
    }
    return "", fmt.Errorf("无法识别的格式")
}
  1. 关于反射类型reflect.TypeOf() 返回的是值的静态类型,而不是其字符串表示。所有解析后的时间都是 time.Time 类型,因此反射显示相同。

  2. 验证时间值:要查看时间是否真正相同,可以比较它们的 Unix 时间戳:

func areTimesEqual(t1, t2 time.Time) bool {
    return t1.Unix() == t2.Unix() && 
           t1.Nanosecond() == t2.Nanosecond() &&
           t1.Location().String() == t2.Location().String()
}

问题的核心是:不同的字符串格式可以表示相同的时间点,解析后都成为 time.Time 类型的值,但它们的字符串表示会根据格式化的方式而不同。

回到顶部