【问题标题】:Get the first and last day of current month in Go/Golang?在 Go/Golang 中获取当前月份的第一天和最后一天?
【发布时间】:2016-08-18 05:34:49
【问题描述】:

我正在尝试获取当月的第一天和最后一天。您可以添加日期和时间,但不能添加月份,我想从下个月减去一天以获得本月的最后一天。像这样的:

package main

import (
    "fmt"
    "time"
)

func main() {

    date := time.Now()
    nextMonth := date.Add(time.Month)
    LastDay := nextMonth.Add(-time.Hour * 24)

    fmt.Println(LastDay)

}

【问题讨论】:

  • 如果在您当地时区的当月最后一天转换到 DST 或从 DST 转换,LastDay 将不正确。

标签: date go time


【解决方案1】:

time.Month 是一个类型,而不是一个值,所以你不能Add 它。此外,您的逻辑是错误的,因为如果您添加一个月并减去一天,您不会得到月底,而是在下个月中旬得到一些东西。如果今天是 4 月 24 日,您将得到 5 月 23 日。

以下代码将满足您的需求:

package main

import (
    "time"
    "fmt"
)

func main() {
    now := time.Now()
    currentYear, currentMonth, _ := now.Date()
    currentLocation := now.Location()

    firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation)
    lastOfMonth := firstOfMonth.AddDate(0, 1, -1)

    fmt.Println(firstOfMonth)
    fmt.Println(lastOfMonth)
}

Playground link

【讨论】:

    【解决方案2】:

    @Apin's answer 很危险,因为 now 库做出了许多错误的假设(它也咬到了我的脚)。
    now lib 不考虑夏令时和许多其他事情: https://github.com/jinzhu/now/issues/13

    这就是我的做法:

    t := time.Now()
    firstday := time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.Local)
    lastday := firstday.AddDate(0, 1, 0).Add(time.Nanosecond * -1)
    

    【讨论】:

    【解决方案3】:

    不确定AddDate(...) 何时添加到time.Time,但很可能是在此问题达到黄金时间后添加的:)

    这是使用time.Time.AddDate(...) 实现相同目标的另一种方法-

    func BeginningOfMonth(date time.Time)  (time.Time) {
        return date.AddDate(0, 0, -date.Day() + 1)
    }
    
    func EndOfMonth(date time.Time) (time.Time) {
        return date.AddDate(0, 1, -date.Day())
    }
    

    然后您可以使用today := time.Now() 并将其传递给一个/两个函数,如eom := EndOfMonth(today) 以获得适当的日期。

    如果时间、夏令时等很重要,那么一旦你得到日期,就应该很简单地在上面装饰这些细节。

    最后,这是一个游乐场链接,您可以在其中玩弄它 - https://play.golang.org/p/DxnGuqh6g4k

    【讨论】:

    • 这是迄今为止最优雅的方法。
    • 太棒了......正好在我即将停止向下滚动的时候,因为我已经找到了一个“好”的方法:-)
    【解决方案4】:

    现在可以使用库了,真的很简单:

    now.BeginningOfMonth()    // 2013-11-01 00:00:00 Fri
    now.EndOfMonth()          // 2013-11-30 23:59:59.999999999 Sat
    

    详情请看这里:https://github.com/jinzhu/now

    【讨论】:

    • 如果你不想使用这个库你至少可以从它的方式中学习(你实际上可以复制你需要的部分):github.com/jinzhu/now/blob/master/now.go
    • BUG 警告:now package 在夏令时转换期间不会给出正确的结果。它错误地假设一天总是有 24 小时:func (now *Now) BeginningOfMonth() time.Time:* 24 * time.Hour
    • @peterSO 解决了这个问题,很抱歉这个问题。
    【解决方案5】:

    我会这样做:

    // LastDayOfMonth returns 28-31 - the last day in the month of the time object
    // passed in to the function
    func LastDayOfMonth(t time.Time) int {
        firstDay := time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.UTC)
        lastDay := firstDay.AddDate(0, 1, 0).Add(-time.Nanosecond)
        return lastDay.Day()
    }
    

    一个

    【讨论】:

      【解决方案6】:

      Package time

      import "time" 
      

      func Date

      func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
      

      日期返回时间对应

      yyyy-mm-dd hh:mm:ss + nsec nanoseconds

      在给定位置的相应区域。

      月、日、小时、分钟、秒和纳秒值可能超出它们的值 通常的范围,并将在转换过程中进行归一化。为了 例如,10 月 32 日转换为 11 月 1 日。

      夏令时转换跳过或重复时间。为了 例如,在美国,2011 年 3 月 13 日凌晨 2:15 从未发生过, 而 2011 年 11 月 6 日凌晨 1:15 发生了两次。在这种情况下, 时区的选择,因此时间,没有明确定义。日期 返回在涉及的两个区域之一中正确的时间 过渡,但不保证是哪个。

      如果 loc 为 nil,则日期混乱。

      超出其通常范围的月份和日期值将被标准化。例如,对于月份时间间隔的第一天和最后一天,

      package main
      
      import (
          "fmt"
          "os"
          "time"
      )
      
      func monthInterval(t time.Time) (firstDay, lastDay time.Time) {
          y, m, _ := t.Date()
          loc := t.Location()
          firstDay = time.Date(y, m, 1, 0, 0, 0, 0, loc)
          lastDay = time.Date(y, m+1, 1, 0, 0, 0, -1, loc)
          return firstDay, lastDay
      }
      
      func main() {
          t := time.Now()
          fmt.Println(t.Round(0))
          first, last := monthInterval(t)
          fmt.Println(first)
          fmt.Println(last)
      
          dstLoc, err := time.LoadLocation("America/Los_Angeles")
          if err != nil {
              fmt.Fprintln(os.Stderr, err)
              return
          }
          // Sunday, March 12, 2017, 2:00:00 am to Sunday, March 12, 2017, 3:00:00 am
          dstStart := time.Date(2017, 03, 12, 2+1, 0, 0, 0, dstLoc)
          // Sunday, November 5, 2017, 2:00:00 am to Sunday, November 5, 2017, 1:00:00 am
          dstEnd := time.Date(2017, 11, 5, 2-1, 0, 0, 0, dstLoc)
          t = dstStart
          fmt.Println()
          fmt.Println(t)
          first, last = monthInterval(t)
          fmt.Println(first)
          fmt.Println(last)
          t = dstEnd.Add(time.Hour)
          fmt.Println()
          fmt.Println(t)
          first, last = monthInterval(t)
          fmt.Println(first)
          fmt.Println(last)
      }
      

      输出:

      2017-10-27 05:45:08.197312082 -0400 EDT
      2017-10-01 00:00:00 -0400 EDT
      2017-10-31 23:59:59.999999999 -0400 EDT
      
      2017-03-12 03:00:00 -0700 PDT
      2017-03-01 00:00:00 -0800 PST
      2017-03-31 23:59:59.999999999 -0700 PDT
      
      2017-11-05 01:00:00 -0800 PST
      2017-11-01 00:00:00 -0700 PDT
      2017-11-30 23:59:59.999999999 -0800 PST
      

      【讨论】:

        【解决方案7】:

        这也可以是一个解决方案:

        currentTimestamp := time.Now().UTC()
        currentYear, currentMonth, _ := currentTimestamp.Date()
        currentLocation := currentTimestamp.Location()
        
        firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation)
        lastOfMonth := time.Date(currentYear, currentMonth+1, 0, 23, 59, 59, 999999999, currentLocation)
        
        fmt.Println(firstOfMonth)
        fmt.Println(lastOfMonth)
        

        输出:

        firstOfMonth: 2019-11-01 00:00:00 +0000 UTC
        lastOfMonth: 2019-11-30 23:59:59.999999999 +0000 UTC
        

        点击这里试用: Playground Link

        【讨论】:

          【解决方案8】:

          goutils 提供了许多有用的函数工具。 goutils

          beginningOfTMonth:=time.TimeBeginningOfMonth(t)
          endOfTMonth:=time.TimeEndOfMonth(t)
          
          
          beginningOfTWeek:=time.TimeBeginningOfWeek(t)
          endOfTWeek:=time.TimeEndOfWeek(t)
          

          【讨论】:

            猜你喜欢
            • 2014-03-22
            • 1970-01-01
            • 1970-01-01
            • 2017-01-09
            • 2017-10-29
            • 1970-01-01
            • 2011-11-24
            • 1970-01-01
            • 2016-02-09
            相关资源
            最近更新 更多