time.Format with "Month Year" format incorrectly displayed

168 views
Skip to first unread message

Bagas Sanjaya

unread,
May 5, 2021, 5:04:31 PM5/5/21
to golan...@googlegroups.com
Hi,

I need to display date in "month year" format, for example "August 2018".

So I had this minimal reproducible code (excluding package name and import statements):

```
func main() {
target := TargetDate(8)

fmt.Println("Target month is ", target.Format("January 2009"))
}

// TargetDate returns target date for selected month
func TargetDate(month int) time.Time {
return time.Date(2018, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
}
```

I expected that the output date for code above was "August 2018",
but what I got was "August 1009". But when I changed the date format string
to "January 2006" (year 2006 as on the reference time mentioned in
documentation for `time`), I got the expected result.

Was above a bug?

--
An old man doll... just what I always wanted! - Clara

Ian Lance Taylor

unread,
May 5, 2021, 5:38:48 PM5/5/21
to Bagas Sanjaya, golang-nuts
You wrote 2009 where you need to write 2006.

Ian

Bagas Sanjaya

unread,
May 5, 2021, 11:23:20 PM5/5/21
to Ian Lance Taylor, golang-nuts
On 06/05/21 04.37, Ian Lance Taylor wrote:
> You wrote 2009 where you need to write 2006.
>
> Ian
>
Thanks.

Wouldn't it possible to define arbitrary reference time and format it
according to what it would like?

Kurtis Rader

unread,
May 5, 2021, 11:35:40 PM5/5/21
to Bagas Sanjaya, Ian Lance Taylor, golang-nuts
On Wed, May 5, 2021 at 8:23 PM Bagas Sanjaya <bagas...@gmail.com> wrote:
On 06/05/21 04.37, Ian Lance Taylor wrote:
  > You wrote 2009 where you need to write 2006.

Wouldn't it possible to define arbitrary reference time and format it
according to what it would like?

If arbitrary literals for the various components were allowed it is certain to create ambiguities. Especially, when you allow for locale specific spellings and formatting of the date components.. The Go approach is easier to understand if you read/speak English but suggests you can replace exact literals (e.g., "2006") with what seems like an equivalent literal (e.g., "2009") rather than the opaque POSIX `%Y`. This is the reason I am not a fan of the Go approach compared to the POSIX strftime approach (see https://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html)

--
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

Marvin Renich

unread,
May 6, 2021, 8:57:54 AM5/6/21
to golang-nuts
* Kurtis Rader <kra...@skepticism.us> [210505 23:35]:
The fact that this sort of confusion over the layout for Time.Format
occurs frequently is a good indication that the approach taken is not as
programmer-friendly as it ought to be. However, Time.Format has what I
consider to be a much more egregious design flaw; one that should have
ruled it out as the design for the standard library: the notation
cannot unambiguously represent any desired format containing literals.
If you want literal digits in the output, you are unlikely to be able
use a single call to Time.Format without additional string manipulation
afterward.

Try to code the Go equivalent of the Linux command «date +"%Y 4 %d"».
You either need two calls to Time.Format with string concatenation, or
you must manipulate the string result of Time.Format to insert the
literal "4".

The %x notation is used in Go's fmt package, so this syntax must already
be clearly understood by a Go programmer. This notation allows any
literal to be unambiguously contained within the format string. Why add
the cognitive overload of a completely different notation for time
formatting that many programmers struggle to understand? Also, I would
be very surprised if there were many Go programmers who never have to
look up which reference digit to use for day and which for seconds; the
order is arbitrary and not logical. It doesn't take much to remember
that %H %M %S is hours, minutes, and seconds, while %y %m %d is year,
month, and day.

I would be willing to bet that if a Time.Printf were added to the time
package, it would very quickly become the overwhelming favorite over
Time.Format. This would be a compatible change that could easily be
added without violating the Compatibility Promise.

If I were designing this, however, I would not just copy the Linux date
format. I would use format modifiers similar to the fmt package. E.g.
instead of %y for two-digit year and %Y for four-digit year, year would
always be %y with a way to indicate how it should be formatted.

...Marvin

Howard C. Shaw III

unread,
May 6, 2021, 9:22:58 AM5/6/21
to golang-nuts
Alternatives:
Excel style formatter: https://github.com/metakeule/fmtdate
bday, err := fmtdate.NewTimeDate("YYYY-MM-DD", "2000-12-04")

C-library style formatter: 

str, err := strftime.Format("%Y-%m-%d %H:%M:%S", t)
str, err := strftime.Format("%Y/%m/%d", time.Now())

C-library style formatter with different interface, includes parsing using C-library format specifiers:
// formatting 
fmt.Println("Current date: ", arrow.Now().CFormat("%Y-%m-%d %H:%M")) 
// parsing
parsed, _ := arrow.CParse("%Y-%m-%d", "2015-06-03") 

Parsing:
Useful for parsing date strings when you don't necessarily know the dateformat ahead of time, or the format can vary:
Howard

Tom Limoncelli

unread,
May 11, 2021, 12:55:54 PM5/11/21
to Ian Lance Taylor, Bagas Sanjaya, golang-nuts
On Wed, May 5, 2021 at 5:38 PM Ian Lance Taylor <ia...@golang.org> wrote:

You wrote 2009 where you need to write 2006.

Ian

I've always felt that the documentation could be more clear about this.

The documentation is technically accurate, but frequently leads a new user to assume that (for example) any year can be used, not just the year 2006.  Same for all the other fields.  My theory is that new users see this and are so amazed at how magical it looks that they assume even more magic.  If Jan works, why not Feb too?

Oddly enough, the documentation never seems to confuse people that already know how it works.

Tom

--
Email: t...@whatexit.org    Work: tlimo...@StackOverflow.com
Blog:  http://EverythingSysadmin.com/
Reply all
Reply to author
Forward
0 new messages