Home > Back-end >  Rest one month in a date golang
Rest one month in a date golang

Time:01-19

Im trying to rest a month in a date in golang i have this example for march an february:

date := time.Date(2023, time.March, 31, 0, 0, 0, 0, time.UTC)

then a make this:

period := date.AddDate(0, -1, -0)

but the program give me:

original date: 2023-03-31 00:00:00 0000 UTC

date after rest: 2023-03-03 00:00:00 0000 UTC

And i expect:

2023-02-28 00:00:00 0000 UTC

at the same time i want that this rest work for every month dynamicaly. Thanks

CodePudding user response:

Just as the automatically transform that comes with go annoys you, you could also take advantage of this.

The trick is how to get the number of days in the previous month.

// as there is no 0 day, it means the last day of the previous mouth
totDay := time.Date(y, m, 0, 0, 0, 0, 0, time.UTC).Day()

The complete code is as follows:

package main

import (
    "fmt"
    "time"
)

func previousMouth(t time.Time) time.Time {
    y, m, d := t.Date()

    curTotDay := time.Date(y, m 1, 0, 0, 0, 0, 0, time.UTC).Day()
    totDay := time.Date(y, m, 0, 0, 0, 0, 0, time.UTC).Day()
    if d == curTotDay {
        d = totDay
    }

    return time.Date(y, m-1, d, 0, 0, 0, 0, time.UTC)
}

func main() {
    date := time.Date(2023, time.March, 31, 0, 0, 0, 0, time.UTC)
    fmt.Println(previousMouth(date))
}

Run it online: goplayground.

CodePudding user response:

As others have mentioned in the comments, you cannot go back exactly one month from 31 March. You would end up at 31 February, but that date doesn't exist and is normalised to 3 March.

You can go back to the last day of the previous month, but you would get the same result if you started at 28 March, 29 March, 30 March or 31 March.

But if that is what you want, you can go back (or forward) any number of months, while clipping the day to remain within the number of days in that month.

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

func daysInMonth(date time.Time) int {
    return date.AddDate(0, 1, -date.Day()).Day()
}

func AddMonthsClipped(date time.Time, months int) time.Time {
    firstDate := firstDayOfMonth(date)
    firstAdded := firstDate.AddDate(0, months, 0)
    addDays, maxDays := date.Day(), daysInMonth(firstAdded)
    if addDays > maxDays {
        addDays = maxDays
    }
    return firstAdded.AddDate(0, 0, addDays-1)
}

func main() {
    date := time.Date(2023, time.March, 31, 0, 0, 0, 0, time.UTC)
    fmt.Println(AddMonthsClipped(date, -1))
}

Go Playground: https://go.dev/play/p/JEihMdM0CHe

CodePudding user response:

I found the answer:

    package main

import (
    "fmt"
    "time"
)

func main() {
    date := time.Date(2023, time.March, 31, 0, 0, 0, 0, time.UTC)
    year, month, _ := date.Date()
    endOfLastMonth := time.Date(year, month, 0, 0, 0, 0, 0, date.Location())
    fmt.Println("This month: ", date)
    fmt.Println("Lasth Month: ", endOfLastMonth)
}

Here the playground: https://go.dev/play/p/iTDFgtdOT9y After working and working with the date, i made this. Thanks you all

  • Related