Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: time: add time.AddMonth to add a month without normalization #52775

Closed
oussamm opened this issue May 8, 2022 · 10 comments
Closed

proposal: time: add time.AddMonth to add a month without normalization #52775

oussamm opened this issue May 8, 2022 · 10 comments

Comments

@oussamm
Copy link

oussamm commented May 8, 2022

While the time.AddDate is mathematically correct with the normalization results. The need to add/substract a month in date without nomalization is there in several areas.

func (t Time) AddMonth(months int) Time

AddMonth returns the time corresponding to adding the given number of months, increment/decrement years if needed and set days to t by staying in the range days of the month added, without normalize the result.

Example:

start := time.Date(2022, 10, 31, 0, 0, 0, 0, time.UTC)
oneMonthLater := start.AddMonth(1)
threeMonthLater := start.AddMonth(3)

fmt.Printf("oneMonthLater: start.AddMonth(1) = %v\n", oneMonthLater)
fmt.Printf("threeMonthLater: start.AddMonth(3) = %v\n", threeMonthLater)

// Output:
oneMonthLater: start.AddMonth(1) = 2022-11-30 00:00:00 +0000 UTC
threeMonthLater: start.AddMonth(3) = 2023-01-31 00:00:00 +0000 UTC

Same if we reduce the date by one month.
Example:

start := time.Date(2022, 03, 31, 0, 0, 0, 0, time.UTC)
oneMonthBefore := start.AddMonth(-1)

fmt.Printf("oneMonthBefore: start.AddMonth(-1) = %v\n", oneMonthBefore)

// Output:
oneMonthBefore: start.AddMonth(-1) = 2022-02-28 00:00:00 +0000 UTC

// The results should be the same for march 30, march 29 and march 28 for non leap year.
@gopherbot gopherbot added this to the Proposal milestone May 8, 2022
@oussamm oussamm changed the title proposal: time: add time.AddMonth to add a month without normalization. proposal: time: add time.AddMonth to add a month without normalization May 8, 2022
@ritikBhandari
Copy link

What is exactly meant by 'normalization'?

@oussamm
Copy link
Author

oussamm commented May 9, 2022

Thank you for your comment, I took the term from the specification of AddDate method here

@ianlancetaylor
Copy link
Contributor

We have to have some kind of normalization, and in your example of 2022-03-31 minus one month, you can see that happening, in that we don't wind up with 2022-02-31. I think that what you are suggesting is that if AddMonth produces a date that is past the end of the new month, we normalize by returning the last day of that month.

@ianlancetaylor ianlancetaylor added this to Incoming in Proposals (old) May 9, 2022
@oussamm
Copy link
Author

oussamm commented May 9, 2022

Yes exactly @ianlancetaylor. This could be practical to have that in addition of AddDate, there are certain areas where we consider each month separately.

@mpx
Copy link
Contributor

mpx commented May 9, 2022

I tend to find the need to add months/years indicates that a "civil time" representation may be better "instant time" (time.Time). Eg, here is a public civil time implementation: cloud.google.com/go/civil.Date. This package may not handle a particular use case, more of a general comment about considering whether civil or instant time is most appropriate.

time.Date already normalizes out of range days into the next month (eg, October 32 converts to November 1). It would be confusing to have 2 different conversations within the time package. Custom normalisation may be better handled outside the standard library.

@rsc
Copy link
Contributor

rsc commented May 11, 2022

I would expect that AddDate and AddMonth would do the same thing with what look like equivalent parameter lists.
One should not normalize differently from the other.

#19700 is the proposal (unprocessed) for civil time generally.

@rsc rsc moved this from Incoming to Active in Proposals (old) May 11, 2022
@rsc
Copy link
Contributor

rsc commented May 11, 2022

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

@fxrlv
Copy link
Contributor

fxrlv commented May 12, 2022

Why not use AddDate?

func AddMonth(t time.Time, m int) time.Time {
	x := t.AddDate(0, m, 0)
	if d := x.Day(); d != t.Day() {
		return x.AddDate(0, 0, -d)
	}
	return x
}

@oussamm
Copy link
Author

oussamm commented May 12, 2022

Thank you for your comments.
Yes since time.day() with a value of zero represents the last day of the previous month, it will be easy to achieve that.

Sames as you, I don't expecting different behaviour for using AddDate in Go, it's just strange to say, the last month of march, 31 is march, 03.
Like Ian said we have to have some kind of normalization for the days, even for other calendars than gregorian. All calendars contains 12 months, lunar month contains between 29 and 30 days, solar month contains 30 and 31 days, adding the regulations.

After reflexion, I feel like AddDate is very complete, unless if someone has something to add, we may close the proposal.

@oussamm oussamm closed this as completed May 14, 2022
@rsc rsc moved this from Active to Declined in Proposals (old) May 18, 2022
@rsc
Copy link
Contributor

rsc commented May 18, 2022

This proposal has been declined as retracted.
— rsc for the proposal review group

@golang golang locked and limited conversation to collaborators May 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Development

No branches or pull requests

7 participants