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: civil time package #19700

Open
jba opened this issue Mar 24, 2017 · 25 comments

Comments

@jba
Copy link
Contributor

commented Mar 24, 2017

I propose a package with minimal implementations of the types Date, Time and DateTime, which represent times without a corresponding location.

A civil time or date does not represent a point or interval of time, but they are useful for representing events transpiring between humans. For example, your birthday begins at midnight on your birthdate regardless of where you are in the world. If you're turning 21, you can buy a drink in New York at midnight, but teleport instantaneously to San Francisco and you'll be denied, because it is 9 PM the day before.

In practice, the main motivation for these types is to represent values in database-like storage systems, like BigQuery and Spanner (and other, non-Google products).

The package currently exists at cloud.google.com/go/civil, and has been in use by the BigQuery and Spanner client libraries for a few months. For now, I'd like to move it to golang.org/x/time/civil. It is probably too esoteric to be worth including in the standard library, but if there were ever a "second-tier" set of packages that augmented the standard library, it could live there. (See #17244.)

A CL is in progress at https://go-review.googlesource.com/c/38571.

@rakyll rakyll added the Proposal label Mar 24, 2017

@bradfitz

This comment has been minimized.

Copy link
Member

commented Mar 24, 2017

If you're turning 18, you can buy a drink in New York at midnight, but teleport instantaneously to San Francisco and you'll be denied, because it is 9 PM the day before.

And because the drinking age in California is 21. The ballot measure never happened.

@gopherbot gopherbot added this to the Proposal milestone Mar 24, 2017

@jba

This comment has been minimized.

Copy link
Contributor Author

commented Mar 24, 2017

21 in NY too, it turns out. Edited comment.

@kevinburke

This comment has been minimized.

Copy link
Contributor

commented Mar 26, 2017

fun story... the drinking age is 21 in every state because of a law that withheld federal highway money unless states mandated 21 as the drinking age. https://en.wikipedia.org/wiki/National_Minimum_Drinking_Age_Act

@rsc

This comment has been minimized.

Copy link
Contributor

commented Mar 27, 2017

On hold for #17244, which in turn is essentially blocked on understanding the long-term plan for package management. Soon.

@FlorianUekermann

This comment has been minimized.

Copy link
Contributor

commented Sep 21, 2017

I left a comment on the implementation in the CL. I'll mirror the parts that are not about implementation details here:

In my opinion time.Duration already implements a civil time (see #20757 for a list of issues that may be interesting).

Please clarify the difference between a civil date and just a normal date (dates don't have timezone issues to my knowledge, especially because they don't represent a moment in time).
If a civil date is just a date I don't think creating a civil package is appropriate. A simple date package or adding a Date type to the time package would be sufficient. The latter would also be useful for reusing unexported functionality from time.

There are multiple tiny "date" packages that look more or less the same (I implemented one here https://godoc.org/github.com/infobaleen/date, but there are others which are practically identical).

@jba

This comment has been minimized.

Copy link
Contributor Author

commented Sep 25, 2017

time.Duration paired with a reference time could represent a civil DateTime (not a civil Time, which is an odd beast that is nevertheless present in many SQL versions). We'd still want another type for DateTime because of the reference time. Also, the range of time.Duration is about 290 years, not nearly long enough for the range of applications we'd like to support (Sumerian calendars to Star Trek chronologies).

Since we need a civil DateTime type, and a civil Time type to support SQL, it seems reasonable to put the Date type in the same package with them. Since the time package is big enough as it is, a small, separate package makes sense.

@FlorianUekermann

This comment has been minimized.

Copy link
Contributor

commented Sep 30, 2017

time.Duration paired with a reference time could represent a civil DateTime. . We'd still want another type for DateTime because of the reference time.

type Civil struct{ Date time.Date; Time time.Duration }, assuming a time.Date type (#21365) is implemented. Basically just two int64s in a struct.

Also, the range of time.Duration is about 290 years, not nearly long enough for the range of applications we'd like to support (Sumerian calendars to Star Trek chronologies).

Maybe I misunderstood the goal, as I don't see the range problem you are mentioning. Are you considering other calendars where a day doesn't have 24*60*60*1e9 nanoseconds?

@bradfitz

This comment has been minimized.

Copy link
Member

commented Sep 30, 2017

Maybe I misunderstood the goal, as I don't see the range problem you are mentioning. Are you considering other calendars where a day doesn't have 246060*1e9 nanoseconds?

Other calendars are not a goal. The time package documents that:

The calendrical calculations always assume a Gregorian calendar, with no leap seconds.

@jba

This comment has been minimized.

Copy link
Contributor Author

commented Oct 3, 2017

type Civil struct{ Date time.Date; Time time.Duration }, assuming a time.Date type (#21365) is implemented. Basically just two int64s in a struct.

Where does that type live? And what about the type that just represents a time of day (civil.TIme in my package)?

Maybe I misunderstood the goal, as I don't see the range problem you are mentioning. Are you considering other calendars where a day doesn't have 246060*1e9 nanoseconds?

I didn't understand your proposal. I thought you wanted to represent a DateTime as a duration from some single reference time, like Unix represents time as an offset from 1/1/1970.

@FlorianUekermann

This comment has been minimized.

Copy link
Contributor

commented Oct 3, 2017

Where does that type live?

I don't have a strong opinion on that. I would suggest putting it in "exp" first and integrating it in "time" later

And what about the type that just represents a time of day (civil.TIme in my package)?

time.Duration is sufficient (look at it's metods). Maybe alias it.
If you need something to support SQL, I think that belongs in/under the sql package. The concept of civil Date and DateTime are useful in a much wider scope, that can be supported mote easily.

@lpar

This comment has been minimized.

Copy link

commented Apr 13, 2018

I've also needed a pure Date for SQL and other things, but I implemented it by wrapping time.Time. Might that be a better implementation approach?

@Vitucho

This comment has been minimized.

Copy link

commented May 21, 2018

i don't understand why is duplicate "time: add weekday helper functions #25469" (btw please see my last comment)... please don't take me wrong i only try to understand how do you think.

@gopherbot

This comment has been minimized.

Copy link

commented Feb 26, 2019

Change https://golang.org/cl/38571 mentions this issue: civil: types for civil time

@jba

This comment has been minimized.

Copy link
Contributor Author

commented Feb 28, 2019

If nothing is blocking this any longer, I'd like to proceed.

I appreciate the suggestions for alternative implementations (wrapping time.Time or using offsets from a base). They would support faster comparison and addition operations at the cost of slower construction time. I propose unexporting the civil.Date and civil.Time fields and adding getter methods, to allow for future change of implementation.

@sandipbgt

This comment has been minimized.

Copy link

commented Apr 3, 2019

Can someone help me ? How do i store date of birth in golang gorm library?

@jba

This comment has been minimized.

Copy link
Contributor Author

commented Apr 3, 2019

Try asking on the gorm issue tracker: https://github.com/jinzhu/gorm/issues/new.

@fgblomqvist

This comment has been minimized.

Copy link

commented Apr 10, 2019

What's the status of this? I'm a bit unfamiliar with how these CLs work, but it looks like it hasn't seen any activity for about a month. Is it just waiting for some final confirmation on its inclusion? Right now we're importing the google package, which is a huge import, just to get access to the civil one (can't get subdirectory importing to work with go modules).

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Apr 10, 2019

The proposal of creating golang.org/x/time/civil is on hold until #17244 is decided. And #17244 is on hold until the modules work settles, which may happen in 1.13.

@lpar

This comment has been minimized.

Copy link

commented Jul 22, 2019

I'd just like to put in a word for having both zoned and unzoned civil datetime types. For calendars, you want to be able to support implicit time zone, as well as explicit.

@jba

This comment has been minimized.

Copy link
Contributor Author

commented Jul 22, 2019

Isn't a zoned civil datetime just a time.Time? As the first comment says, these types

represent times without a corresponding location.

@lpar

This comment has been minimized.

Copy link

commented Jul 22, 2019

To clarify, I'm saying that a date/time library needs to support at least all of the following:

  • 15:04:05
  • 2006-01-02
  • 2006-01-02 15:04:05
  • 2006-01-02 15:04:05 -0500
@kardianos

This comment has been minimized.

Copy link
Contributor

commented Aug 23, 2019

@rsc (or more generally the Proposal committee)

I would like to re-open this proposal for consideration in order to get closure on it.

Why Now?

The SQL Server Driver currently supports "https://godoc.org/cloud.google.com/go/civil" for date, time and date time types. However, "cloud.google.com/go" is a heavy module and I would prefer we do not require it, when I really just want the civil types from it. I have extracted it from that package as "github.com/golang-sql/civil" with a PR to switch to using it denisenkom/go-mssqldb#501 . However, if this proposal was accepted and https://golang.org/cl/38571 was accepted, I would want to use that.

Why use Civil types at all?

Business applications frequently use both Date, Timestamp and Timestampz (or equivalent) types. One type of bug I have encountered is where a DB Date type is used, but in certain instances time.Time will set the wrong date based on the time of day (due to timezone). This is fixable, but in newer code I've chosen to use civil.Date. This simplifies reading and understanding the code and prevents through fundamental design an entire class of bugs.

When working with Dates in a date based scheduler, converting to civil.Date simplified the code over time.Time. Equality and inequality became much simpler cognitively and slightly simpler in code.

When sending a parameter to a database instance, can be important to have proper types so they are represented correctly the the SQL:

  • "github.com/ziutek/mymysql/mysql".Date
  • "cloud.google.com/go/civil".(Date, Time, DateTime) for spanner
  • "github.com/kshvakov/clickhouse/lib/types".(Date, DateTime)
  • "github.com/mailru/go-clickhouse".Date

What do I want

Go1.13 is almost out. I would like resolution whether x/time/civil will be a package or not. If not, I will use "github.com/golang-sql/civil". If it may, then I will wait until it gets merged. Once this is sorted out, I will encurage other database drivers to support these civil types as well.


Date, DateTime, Time (of day), and Decimal types are the last types commonly supported by Databases. I'm addressing Decimal support with https://golang.org/issue/30870 .

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Aug 23, 2019

Seems like we still need to sort out #17244. But I'll take that one off hold.

@jba

This comment has been minimized.

Copy link
Contributor Author

commented Aug 31, 2019

The golang.org/x/time repo already has a go.mod file, and has for six months. Unless someone wants to argue that golang.org/x/time/rate and golang.org/x/time/civil should be different modules, I don't think #17244 is a blocker anymore.

@jba

This comment has been minimized.

Copy link
Contributor Author

commented Sep 19, 2019

@ianlancetaylor can you remove the Proposal-Hold label?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.