time.AddDate() odd behavior

943 views
Skip to first unread message

Alex Dvoretskiy

unread,
Oct 31, 2017, 1:53:40 PM10/31/17
to golang-nuts
Hello Golang-nuts,

package main

import (
"fmt"
"time"
)

func main() {
t := time.Date(2009, time.December, 31, 23, 0, 0, 0, time.UTC)
fmt.Println(t)
fmt.Println(t.AddDate(0, -1, 0))
}

https://play.golang.org/p/hZ7nhnkepK

The result is
2009-12-31 23:00:00 +0000 UTC
2009-12-01 23:00:00 +0000 UTC

I think it should be:
2009-12-31 23:00:00 +0000 UTC
2009-11-30 23:00:00 +0000 UTC

Documentation states that "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."  This is makes sense when you work with time.Date() function, because hours and minutes involved, time zones, daylight savings etc. 
But it doesn't make any sense If you operate with days, months, years for analytical purposes. I think the normal practice ("Normalization") in this case would be to add exactly one month just like in other languages. Not one month and one day. SQL for example:

DECLARE @sp_Date DATETIME = '2009-12-31'
SELECT @sp_Date
SELECT DATEADD(mm , -1, @sp_Date)

2009-12-31 00:00:00.000
2009-11-30 00:00:00.000

Ian Lance Taylor

unread,
Oct 31, 2017, 4:32:47 PM10/31/17
to Alex Dvoretskiy, golang-nuts
I think the function is behaving as documented. You subtracted one
month from December 31, 2009, which gives you November 31, 2009. We
must then normalize that in the same was as the Date function, which
gives you December 1, 2009, which is what you see. I don't think we
can change this now, as it would break backward compatibility. Even
if we were willing to change it, I don't actually understand what you
are proposing. What rule tells us that one month before December 31
is November 30? Or, what rule tells us to normalize November 31 to
November 30 rather than December 1?

Ian

Alex Dvoretskiy

unread,
Oct 31, 2017, 5:19:56 PM10/31/17
to golang-nuts
Yes, there is no particular rule for this case. I guess it depends on the industry, department, or even particular individual. In finance, it would be normalized to November 30. In power engineering December 1. I'm not proposing. Just want to know other peoples opinions on this case for better Go understanding.

John Souvestre

unread,
Oct 31, 2017, 7:47:31 PM10/31/17
to golan...@googlegroups.com

> What rule tells us that one month before December 31
is November 30?  Or, what rule tells us to normalize November 31 to
November 30 rather than December 1?

 

End-of-month mode is needed pretty often, in my experience.  Perhaps there should be two rules so the user could choose which fits his situation?  The current method and a new method with a slightly different name, ex: AddEOM?

 

John

    John Souvestre - New Orleans LA

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Lucio

unread,
Nov 1, 2017, 12:26:58 AM11/1/17
to golang-nuts
Ian is perfectly right.

Subtracting 31 days and then manually "normalising" to end-of-month would seem to give the result being sought here. The existing normalising rule makes perfect mathematical sense and slipping it this way or that on some spurious pretext will just confuse matters. Such adjustments ought to be explicit and clearly documented.

Lucio.
Reply all
Reply to author
Forward
0 new messages