Golang - 从 YearDay int32 中查找月份和日期

Golang - Find month and day of month from YearDay int32

我有一个固定的数据结构,其中包含 YearDay 和 TimeOfDay 字段。 YearDay 是当年过去的天数,TimeOfDay 是当天过去的秒数(最多 86400)。 YearDay 是一个 int32,而 TimeOfDay 是一个 float64。

我想将其转换为 time.Now().UnixNano() 形式,但不确定如何转换。时间模块有一个 YearDay(),但没有给定 yearDay (int32)(可能是一年)的反函数来给我一个月中的月份和日期。

理想情况下,我想以某种方式解析

d := time.Date(time.Year(), month, day, hour, min, sec, ms, time.UTC)

月、日、时、分、秒、毫秒以某种方式预先确定,或者我可以轻松转换为我想要的任何形式的等价物(但主要是 UnixNano())。

我最好的想象是一个复杂的 switch 语句,它减去 31、28(29)、30、31 ... 并查看 int 何时最终为负数以找到月份和日期,但它必须是两个带有闰年检查的 switch 语句以选择要使用的 switch 块,同时在 TimeOfDay 上进行几个余数计算。有没有更简单更干净的方法?

编辑:我在玩弄它时最终实现了以下功能,但我肯定会使用 Icza 的解决方案。很高兴知道日子会溢出来。谢谢!

func findMonthAndDay(yearDay int32) (int32, int32) {
    year := time.Now().Year()
    isLeapYear := year%400 == 0 || year%4 == 0 && year%100 != 0 // Calculates if current year is leapyear

    // Determines which array to send to for loop
    var monthsOfYear [12]int32
    if isLeapYear {
        monthsOfYear = [12]int32{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    } else {
        monthsOfYear = [12]int32{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    }

    var currentMonth int32
    var currentDayInMonth int32

    // Loop through array of months
    for i := range monthsOfYear {
        // If yearDay - next month #OfDays positive, not correct month
        if yearDay-monthsOfYear[i] > 0 {
            // Subtract month #OfDays and continue
            yearDay = yearDay - monthsOfYear[i]

        } else {
            currentMonth = int32(i + 1) // Month found (+1 due to index at 0)
            currentDayInMonth = yearDay // Remainder of YearDay is day in month
            break
        }
    }
    return currentMonth, currentDayInMonth
}

您可以使用 Time.AddDate() to add the number of days to a time.Time 值。添加天数大于31是可以的,实现归一化结果。

并将 TimeOfDay 转换为 time.Duration and use Time.Add() 以添加它。当转换为time.Duration时,我们可以将它乘以1e9得到纳秒数,所以小数秒将被保留。

示例:

t := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
fmt.Println(t)

var yearDay int32 = 100
var timeOfDay float64 = 70000.5

t = t.AddDate(0, 0, int(yearDay))
t = t.Add(time.Duration(timeOfDay * 1e9))

fmt.Println(t)
fmt.Println("Unix:", t.Unix())
fmt.Println("UnixNano:", t.UnixNano())

输出(在 Go Playground 上尝试):

2020-01-01 00:00:00 +0000 UTC
2020-04-10 19:26:40.5 +0000 UTC
Unix: 1586546800
UnixNano: 1586546800500000000