vinniyo
vinniyo

Reputation: 877

Get the first and last day of current month

I'm trying to get the first and last day of the current month. You can add days and hours but not the month, which I was thinking of subtracting one day from the next month to get the last day of this month. Something like this:

package main

import (
    "fmt"
    "time"
)

func main() {

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

    fmt.Println(LastDay)

}

Upvotes: 52

Views: 69217

Answers (9)

Nivesh_NXD
Nivesh_NXD

Reputation: 11

dd := time.Now()
firstDayOfCurrentMonth := time.Now().AddDate(0, 0, -dd.Day()+1)
lastDayOfCurrentMonth := firstDayOfCurrentMonth.AddDate(0, 1, -1)

Explaination:

dd.Day will give the day from particular date ex: March 4, 2010. it will give 04 as day.

AddDate returns the time corresponding to adding the given number of years, months, and days to t. For example: AddDate(-1, 2, 3) applied to January 1, 2011 returns March 4, 2010.

AddDate normalizes its result in the same way that Date does, so, for example, adding one month to October 31 yields December 1, the normalized form for November 31.

Upvotes: 0

RajGohel
RajGohel

Reputation: 51

This can also be a solution:

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)

Output:

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

Click here to try it out: Playground Link

Upvotes: 5

Xian Shu
Xian Shu

Reputation: 708

goutils provides many useful func tools. goutils

beginningOfTMonth:=time.TimeBeginningOfMonth(t)
endOfTMonth:=time.TimeEndOfMonth(t)


beginningOfTWeek:=time.TimeBeginningOfWeek(t)
endOfTWeek:=time.TimeEndOfWeek(t)

Upvotes: 2

Shreyas
Shreyas

Reputation: 1534

Not sure when AddDate(...) was added to time.Time, but quite possibly it was added after this question had its prime time :)

Here's another way to achieving the same with 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())
}

Then you could use today := time.Now() and pass it over to one/both of the functions like so - eom := EndOfMonth(today) to get the appropriate date.

If time, DST and such are important, it should be pretty straightforward to ornament those details on top of it once you get the date.

Finally, here's a playground link where you can play around with it - https://play.golang.org/p/DxnGuqh6g4k

Upvotes: 46

gabs
gabs

Reputation: 340

The @Apin's answer is dangerous because the now lib makes many wrong assumptions (it bit me in the foot too).
The now lib doesn't consider daylight saving times and many other things: https://github.com/jinzhu/now/issues/13

This is how I'm doing it:

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)

Upvotes: 24

peterSO
peterSO

Reputation: 166569

Package time

import "time" 

func Date

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

Date returns the Time corresponding to

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

in the appropriate zone for that time in the given location.

The month, day, hour, min, sec, and nsec values may be outside their usual ranges and will be normalized during the conversion. For example, October 32 converts to November 1.

A daylight savings time transition skips or repeats times. For example, in the United States, March 13, 2011 2:15am never occurred, while November 6, 2011 1:15am occurred twice. In such cases, the choice of time zone, and therefore the time, is not well-defined. Date returns a time that is correct in one of the two zones involved in the transition, but it does not guarantee which.

Date panics if loc is nil.

Month and day values outside their usual ranges will be normalized. For example, for the first and last day of the month time interval,

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)
}

Output:

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

Upvotes: 4

Richard Knop
Richard Knop

Reputation: 83697

I would do it like this:

// 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()
}

a

Upvotes: 5

Apin
Apin

Reputation: 2668

You can use now library, it really simple :

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

Please take a look here for detail : https://github.com/jinzhu/now

Upvotes: 27

Amit Kumar Gupta
Amit Kumar Gupta

Reputation: 18567

time.Month is a type, not a value, so you can't Add it. Also, your logic is wrong because if you add a month and subtract a day, you aren't getting the end of the month, you're getting something in the middle of next month. If today is 24 April, you'll get 23 May.

The following code will do what you're looking for:

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

Upvotes: 73

Related Questions