【问题标题】:Date range by week number Golang按周数划分的日期范围 Golang
【发布时间】:2018-09-12 17:32:52
【问题描述】:

通过这个简单的函数,我可以得到周数。现在,有了星期数,我怎样才能得到日期范围,从星期日开始?

import (
    "fmt"
    "time"
)
func main() {
    Week(time.Now().UTC())
}

func Week(now time.Time) string {
    _, thisWeek := now.ISOWeek()
    return "S" + strconv.Itoa(thisWeek)
}

【问题讨论】:

    标签: date go range


    【解决方案1】:

    感谢@prajwal Singh,我发现了更通用的方法来找出一周的开始和最后一天 w.r.t 月、周和年

    func DateRange(week, month, year int) (startDate, endDate time.Time) {
    
        timeBenchmark := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
        weekStartBenchmark := timeBenchmark.AddDate(0, 0, -(int(timeBenchmark.Weekday())+6)%7)
    
        startDate = weekStartBenchmark.AddDate(0, 0, (week-1)*7)
        endDate = startDate.AddDate(0, 0, 6)
    
        return startDate, endDate
    }
    

    【讨论】:

      【解决方案2】:

      前言:Time.ISOWeek() 返回您从星期一开始的周数,因此我将回答您的问题,该问题也处理从星期一开始的周数。如果您希望它在周日开始的几周内工作,请根据您的需要进行更改。

      我在github.com/icza/gox 发布了这个实用程序,请参阅timex.WeekStart()


      标准库不提供返回给定周的日期范围(年+周数)的函数。所以我们必须自己构建一个。

      这并不难。我们可以从年中开始,与一周的第一天(星期一)对齐,获取该时间值所在的周,然后修正:添加与周差乘以 7 一样多的天。

      这就是它的样子:

      func WeekStart(year, week int) time.Time {
          // Start from the middle of the year:
          t := time.Date(year, 7, 1, 0, 0, 0, 0, time.UTC)
      
          // Roll back to Monday:
          if wd := t.Weekday(); wd == time.Sunday {
              t = t.AddDate(0, 0, -6)
          } else {
              t = t.AddDate(0, 0, -int(wd)+1)
          }
      
          // Difference in weeks:
          _, w := t.ISOWeek()
          t = t.AddDate(0, 0, (week-w)*7)
      
          return t
      }
      

      测试它:

      fmt.Println(WeekStart(2018, 1))
      fmt.Println(WeekStart(2018, 2))
      fmt.Println(WeekStart(2019, 1))
      fmt.Println(WeekStart(2019, 2))
      

      输出(在Go Playground上试试):

      2018-01-01 00:00:00 +0000 UTC
      2018-01-08 00:00:00 +0000 UTC
      2018-12-31 00:00:00 +0000 UTC
      2019-01-07 00:00:00 +0000 UTC
      

      这个WeekStart() 实现的一个很好的特性是它可以很好地处理超出范围 周。即如果一周通过0,将被解释为上一年的最后一周。如果一周通过-1,它将指定上一年的倒数第二周。同样,如果您通过一年中的最大周数加 1,它将被解释为下一年的第一周等。

      上面的WeekStart()函数只返回给定一周的第一天(星期一),因为一周的最后一天总是它的第一天+6天。

      如果我们还需要最后一天:

      func WeekRange(year, week int) (start, end time.Time) {
          start = WeekStart(year, week)
          end = start.AddDate(0, 0, 6)
          return
      }
      

      测试它:

      fmt.Println(WeekRange(2018, 1))
      fmt.Println(WeekRange(2018, 2))
      fmt.Println(WeekRange(2019, 1))
      fmt.Println(WeekRange(2019, 2))
      

      输出(在Go Playground上试试):

      2018-01-01 00:00:00 +0000 UTC 2018-01-07 00:00:00 +0000 UTC
      2018-01-08 00:00:00 +0000 UTC 2018-01-14 00:00:00 +0000 UTC
      2018-12-31 00:00:00 +0000 UTC 2019-01-06 00:00:00 +0000 UTC
      2019-01-07 00:00:00 +0000 UTC 2019-01-13 00:00:00 +0000 UTC
      

      【讨论】:

        【解决方案3】:

        以下为我找到一周的第一天的工作,虽然不是从周数而是从时间。如果您添加一个额外的参数 - 对于硬编码的 time.Monday - 这可以是一周中的任何一天,例如周日。

        func weekStartDate(date time.Time) time.Time {
            offset := (int(time.Monday) - int(date.Weekday()) - 7) % 7
            result := date.Add(time.Duration(offset*24) * time.Hour)
            return result
        }
        

        测试:

            func TestWeekStartDate(t *testing.T) {
                date := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
                for i := 0; i < 2000; i++ {
                    weekStart := weekStartDate(date)
                    log.Printf("%s %s", date.Format("2006-01-02 Mon"), weekStart.Format("2006-01-02 Mon"))
                    assert.NotNil(t, weekStart)
                    assert.Equal(t, time.Monday, weekStart.Weekday())
                    date = date.Add(24 * time.Hour)
                }
            }
        

        输出:

        ...
        2021/01/17 08:50:03 2020-12-15 Tue 2020-12-14 Mon
        2021/01/17 08:50:03 2020-12-16 Wed 2020-12-14 Mon
        2021/01/17 08:50:03 2020-12-17 Thu 2020-12-14 Mon
        2021/01/17 08:50:03 2020-12-18 Fri 2020-12-14 Mon
        2021/01/17 08:50:03 2020-12-19 Sat 2020-12-14 Mon
        2021/01/17 08:50:03 2020-12-20 Sun 2020-12-14 Mon
        2021/01/17 08:50:03 2020-12-21 Mon 2020-12-21 Mon
        2021/01/17 08:50:03 2020-12-22 Tue 2020-12-21 Mon
        2021/01/17 08:50:03 2020-12-23 Wed 2020-12-21 Mon
        2021/01/17 08:50:03 2020-12-24 Thu 2020-12-21 Mon
        2021/01/17 08:50:03 2020-12-25 Fri 2020-12-21 Mon
        2021/01/17 08:50:03 2020-12-26 Sat 2020-12-21 Mon
        2021/01/17 08:50:03 2020-12-27 Sun 2020-12-21 Mon
        2021/01/17 08:50:03 2020-12-28 Mon 2020-12-28 Mon
        2021/01/17 08:50:03 2020-12-29 Tue 2020-12-28 Mon
        2021/01/17 08:50:03 2020-12-30 Wed 2020-12-28 Mon
        2021/01/17 08:50:03 2020-12-31 Thu 2020-12-28 Mon
        2021/01/17 08:50:03 2021-01-01 Fri 2020-12-28 Mon
        2021/01/17 08:50:03 2021-01-02 Sat 2020-12-28 Mon
        2021/01/17 08:50:03 2021-01-03 Sun 2020-12-28 Mon
        2021/01/17 08:50:03 2021-01-04 Mon 2021-01-04 Mon
        2021/01/17 08:50:03 2021-01-05 Tue 2021-01-04 Mon
        2021/01/17 08:50:03 2021-01-06 Wed 2021-01-04 Mon
        2021/01/17 08:50:03 2021-01-07 Thu 2021-01-04 Mon
        2021/01/17 08:50:03 2021-01-08 Fri 2021-01-04 Mon
        2021/01/17 08:50:03 2021-01-09 Sat 2021-01-04 Mon
        2021/01/17 08:50:03 2021-01-10 Sun 2021-01-04 Mon
        2021/01/17 08:50:03 2021-01-11 Mon 2021-01-11 Mon
        2021/01/17 08:50:03 2021-01-12 Tue 2021-01-11 Mon
        2021/01/17 08:50:03 2021-01-13 Wed 2021-01-11 Mon
        2021/01/17 08:50:03 2021-01-14 Thu 2021-01-11 Mon
        2021/01/17 08:50:03 2021-01-15 Fri 2021-01-11 Mon
        2021/01/17 08:50:03 2021-01-16 Sat 2021-01-11 Mon
        2021/01/17 08:50:03 2021-01-17 Sun 2021-01-11 Mon
        2021/01/17 08:50:03 2021-01-18 Mon 2021-01-18 Mon
        2021/01/17 08:50:03 2021-01-19 Tue 2021-01-18 Mon
        2021/01/17 08:50:03 2021-01-20 Wed 2021-01-18 Mon
        2021/01/17 08:50:03 2021-01-21 Thu 2021-01-18 Mon
        2021/01/17 08:50:03 2021-01-22 Fri 2021-01-18 Mon
        2021/01/17 08:50:03 2021-01-23 Sat 2021-01-18 Mon
        2021/01/17 08:50:03 2021-01-24 Sun 2021-01-18 Mon
        2021/01/17 08:50:03 2021-01-25 Mon 2021-01-25 Mon
        2021/01/17 08:50:03 2021-01-26 Tue 2021-01-25 Mon
        2021/01/17 08:50:03 2021-01-27 Wed 2021-01-25 Mon
        2021/01/17 08:50:03 2021-01-28 Thu 2021-01-25 Mon
        2021/01/17 08:50:03 2021-01-29 Fri 2021-01-25 Mon
        2021/01/17 08:50:03 2021-01-30 Sat 2021-01-25 Mon
        2021/01/17 08:50:03 2021-01-31 Sun 2021-01-25 Mon
        2021/01/17 08:50:03 2021-02-01 Mon 2021-02-01 Mon
        2021/01/17 08:50:03 2021-02-02 Tue 2021-02-01 Mon
        2021/01/17 08:50:03 2021-02-03 Wed 2021-02-01 Mon
        2021/01/17 08:50:03 2021-02-04 Thu 2021-02-01 Mon
        2021/01/17 08:50:03 2021-02-05 Fri 2021-02-01 Mon
        ...
        

        【讨论】:

          【解决方案4】:

          感谢@icza 的解决方案,找到了一种在逻辑方面进一步简化它的方法:

          func DateRange(week, year int) (startDate, endDate time.Time) {
              timeBenchmark := time.Date(year, 7, 1, 0, 0, 0, 0, time.UTC)
              weekStartBenchmark := timeBenchmark.AddDate(0, 0, -(int(timeBenchmark.Weekday())+6)%7)
          
              _, weekBenchmark := weekStartBenchmark.ISOWeek()
              startDate = weekStartBenchmark.AddDate(0, 0, (week-weekBenchmark)*7)
              endDate = startDate.AddDate(0, 0, 6)
          
              return startDate, endDate
          }
          

          效果也很好。

          【讨论】:

            猜你喜欢
            • 2010-10-29
            • 1970-01-01
            • 1970-01-01
            • 2011-03-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-11-04
            相关资源
            最近更新 更多