Rest one month in a date golang

huangapple go评论83阅读模式
英文:

Rest one month in a date golang

问题

我正在尝试在Golang中将一个日期减去一个月,我有以下关于三月和二月的示例代码:

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

然后我执行了以下操作:

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

但程序给出的结果是:

原始日期:2023-03-31 00:00:00 +0000 UTC

减去一个月后的日期:2023-03-03 00:00:00 +0000 UTC

而我期望的结果是:

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

同时,我希望这个减去一个月的操作对每个月都能动态地适用。

谢谢。

英文:

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 dynamically.

Thanks.

答案1

得分: 2

正如自动转换所带来的困扰一样,你也可以利用它。

关键在于如何获取上个月的天数。

// 因为没有0号这一天,所以它表示上个月的最后一天
totDay := time.Date(y, m, 0, 0, 0, 0, 0, time.UTC).Day()

完整的代码如下:

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

在线运行:goplayground

英文:

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.

答案2

得分: 0

正如其他人在评论中提到的,你不能准确地回到3月31日的前一个月。你会得到2月31日,但这个日期不存在,会被规范化为3月3日。

你可以回到上个月的最后一天,但如果你从3月28日、3月29日、3月30日或3月31日开始,结果是一样的。

但如果这是你想要的,你可以回到(或前进)任意数量的月份,同时将日期限制在该月的天数范围内。

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

英文:

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

答案3

得分: 0

我找到了答案:

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("本月:", date)
	fmt.Println("上个月:", endOfLastMonth)
}

这是代码的运行结果:https://go.dev/play/p/iTDFgtdOT9y
在处理日期的过程中,我做出了这个结果。谢谢大家。

英文:

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

huangapple
  • 本文由 发表于 2023年1月19日 11:03:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/75167360.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定