获取两个日期之间的实际日历日

时间:2018-02-05 14:00:58

标签: go

我试图在Go中的两个日期之间获得天数,但是当我得到时间(小时)的差异然后除以每天的时间量时,我有一个问题。

问题:如果日期不同(5月7日和5月8日)但是从那时起的时间低于24小时,我的代码计算为没有天数。

我想要的是什么:计算两者之间的实际日期。

// Days
firstDay := firstDate.Unix()
lastDay := lastDate.Unix()
fmt.Println("firstDay: ", firstDay)
fmt.Println("lastDay: ", lastDay)

if firstDay > lastDay {
        fmt.Println("IS TO SMALL")
    return
}

// businessDays = 
businessDays := (lastDay - firstDay) / 86400
fmt.Println("businessDays: ", businessDays)

非常感谢。

3 个答案:

答案 0 :(得分:3)

  1. 使用duration.Hours()获取时间
  2. 使用math.Ceil查找日历日
  3. 使用time.Truncate截断小时和分钟,仅保存一天
  4. 源代码:

    package main
    
    import (
        "fmt"
        "math"
        "time"
    )
    
    func main() {
        d1, err := time.Parse("200601021504", "201801020001")
        if err != nil {
            panic(err)
        }
        d2, err := time.Parse("200601021504", "201801020002")
        if err != nil {
            panic(err)
        }
    
        newD1 := d1.Truncate(time.Hour * 24)
        newD2 := d2.Truncate(time.Hour * 24)
    
        fmt.Printf("days: %v\n", math.Ceil(newD2.Sub(newD1).Hours()/24))
    
    }
    

答案 1 :(得分:1)

由于性能现在是一个问题(我怀疑),我用一些方法写了一些基准:

func TrimToDate(t time.Time) time.Time {
    y, m, d := t.Date()
    return time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
}

func CountTrim(t1, t2 time.Time) int {
    return int((t2.Unix() - TrimToDate(t1.Unix())) / 86400)
}

func CountUnixAdd(t1, t2 time.Time) int {
    Days := (t1.Unix() - t2.Unix()) / 86400

    if t1.Add(time.Duration(Days)*24*time.Hour).Day() != t2.Day() {
        Days++
    }

    return int(Days)
}

func CountDivMul(t1, t2 time.Time) int {
    d1 := t1.Unix() / 86400 * 86400
    return int((t2.Unix() - d1) / 86400)
}

CountTrim使用time.Time.Date方法修剪小时和分钟等等。请注意,只需要调用TrimToDate一次,因为剩余部分将被整数除法丢弃。

CountUnixAdd是一种简单明了的方法:测试是否是相同的日期,如果没有,则添加一个。

CountDivMul几乎与修剪一天的想法相同,但使用更黑客的方式:使用整数除法来消除剩余部分然后再增加。

笔记本电脑上的基准测试结果:

goos: windows
goarch: amd64
pkg: test/stackoverflow/dateprb
BenchmarkCountTrim-8            20000000                62.7 ns/op
BenchmarkCountDivMul-8          1000000000               2.12 ns/op
BenchmarkCountUnixAdd-8         20000000                77.8 ns/op
PASS
ok      test/stackoverflow/dateprb      5.367s

不出所料,hack-y方式比另一方式快,而两种常用方式几乎相同。

完整代码(基准和功能)here

答案 2 :(得分:1)

有许多事情需要担心。例如,由于夏令时(DST),并非所有天都是24小时。如果时间在不同的时区怎么办?等等。

这是解决这些问题的解决方案。

package main

import (
    "fmt"
    "time"
)

// CalendarDays returns the calendar difference between times (t2 - t1) as days.
func CalendarDays(t2, t1 time.Time) int {
    y, m, d := t2.Date()
    u2 := time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
    y, m, d = t1.In(t2.Location()).Date()
    u1 := time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
    days := u2.Sub(u1) / (24 * time.Hour)
    return int(days)
}

func main() {
    first := time.Now().Round(0)
    end := first.Add(48 * time.Hour)
    for last := first; last.Before(end); last = last.Add(6 * time.Hour) {
        fmt.Println("Days:", CalendarDays(last, first), "Last:", last, "First:", first)
    }
}

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

输出:

Days: 0 Last: 2018-02-05 17:38:15.623292254 -0500 EST First: 2018-02-05 17:38:15.623292254 -0500 EST
Days: 0 Last: 2018-02-05 23:38:15.623292254 -0500 EST First: 2018-02-05 17:38:15.623292254 -0500 EST
Days: 1 Last: 2018-02-06 05:38:15.623292254 -0500 EST First: 2018-02-05 17:38:15.623292254 -0500 EST
Days: 1 Last: 2018-02-06 11:38:15.623292254 -0500 EST First: 2018-02-05 17:38:15.623292254 -0500 EST
Days: 1 Last: 2018-02-06 17:38:15.623292254 -0500 EST First: 2018-02-05 17:38:15.623292254 -0500 EST
Days: 1 Last: 2018-02-06 23:38:15.623292254 -0500 EST First: 2018-02-05 17:38:15.623292254 -0500 EST
Days: 2 Last: 2018-02-07 05:38:15.623292254 -0500 EST First: 2018-02-05 17:38:15.623292254 -0500 EST
Days: 2 Last: 2018-02-07 11:38:15.623292254 -0500 EST First: 2018-02-05 17:38:15.623292254 -0500 EST