-
Notifications
You must be signed in to change notification settings - Fork 18k
time: provide Truncate usable for durations > 1 minute #16647
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
Comments
Also affecting Time.Round. I am not satisfied we shouldn't truncate or round with anything longer or equal to one hour though. It is a perfectly valid and commonly required case. Shouldn't we change the behavior for the non hour aligned time zones instead? |
You can truncate to the hour in the local timezone using code like https://play.golang.org/p/IWdx7kALZx (a modification of Quentin's link--it's the I guess the question is whether we should have a version of |
I thought about writing your truncateHour but I suspect it does not do the
right thing in the face of DST. It is this source of nuance that made me
originally look for a proper Truncate in the time package.
|
Well, if you define how truncation should behave during a DST transition, I can write you a function that does it. My version already implements what I think the correct behavior should be, given that DST transitions always occur on the hour. |
For DST I think 01:30 EDT should truncate to 01:00 EDT and 01:30 EST should On Aug 10, 2016 21:28, "Ian Lance Taylor" notifications@github.com wrote:
|
There is no DST bit in the time package. There is the absolute time, and the presentation time. DST is entirely a function of the presentation time--it doesn't exist in the absolute time. The Location includes the set of times where a DST transition occurs. So whether to display DST is determined entirely by the absolute time and the Location. There is no other information. |
Of course, but whether or not there's an explicit "DST bit", it's encoded in the chosen offset. time.Truncate as implemented always works on absolute time, but with this bug I'm trying to say that users might expect time.Truncate to operate on presentation time. Thus, we do have to care about which presentation time to show. Every time you call time.Date, in fact, you're round-tripping through presentation time (as your playground example does). So while I would like Go to provide a time.Truncate that works usefully in presentation time, the one we have doesn't, and the documentation should explain that. |
I don't disagree with what you say, except that I think the documentation for But I still don't understand why you think the |
Perhaps an example is best:
|
Thanks for the example. What do you think of this version?
|
Off the top of my head, I can't think of a timezone for which that Now, given that, what if anything should we do? I think the docs should at least be improved to more explicitly state that Truncate does not work for time.Hour, and to remove the example. Do we want to actually change Truncate to behave as you propose? Or provide a new version of Truncate? In general I'm concerned that, like many things related to times, truncating is subtle and easy to get wrong - as evidenced by how long it took this thread to reach a working function. Thus I would prefer if the standard library already had the right subtle behavior built-in. |
I do not think we should the existing If we add a new function, what would that function do? How would we document it? It's not clear that we need a variant of |
I sent CL 28730 to clarify the docs. I think the behavior I want out of Truncate and Round is to be able to zero out the least significant fields of a time. That is, zero out the fractional seconds, or zero out the seconds, or zero out the minutes, or the hour, etc. In this particular case it came up because I want to bucket times in a way that I can then use a format string that omits the more detailed fields. For example, if I call 12:45 AM -> Truncate(Hour), I get back 12:30 AM (in some time zones). If I then go on to format that as 12 AM, that's very misleading, because it's actually the 12:30 AM - 1:30 AM bucket, not the 12 AM - 1 AM bucket. As I pointed out with my playground link, it's not as simple as calling time.Date with some of the fields set to zero. |
CL https://golang.org/cl/28730 mentions this issue. |
I haven't been able to think of a really good solution. What if we implement a set of methods parallel to
|
Truncate and Round operate on absolute time, which means that Truncate(Hour) may return a time with non-zero Minute(). Document that more clearly, and remove the misleading example which suggests it is safe. Updates #16647 Change-Id: I930584ca030dd12849195d45e49ed2fb74e0c9ac Reviewed-on: https://go-review.googlesource.com/28730 Reviewed-by: Ian Lance Taylor <iant@golang.org>
@ianlancetaylor Hmm, that's a pretty significant API surface increase, for a type that already has a bunch of methods. Especially if you also want to offer Round varieties. We could do something like t.TruncateTo().Hour() to hide everything under another type, though maybe that's just synctatic sugar. Or Truncater(t).Hour() with a Truncater type that implements those methods? |
We could make them functions rather than methods. |
Perhaps it's time to introduce a time/timeutil package
for such useful helper functions.
|
I don't agree that the truncating by day is a utility but a correct implementation of a specific case for Truncate. It should be next to Truncate rather than being in a util package. |
We're not going to add new API here. |
The example for time.Time.Truncate suggests truncating by time.Hour, but in fact Truncate does not do what the user probably wants if the timezone is not hour-aligned.
e.g. https://play.golang.org/p/hAfBrYWNeZ
I suggest just removing the time.Hour example, and possibly explicitly suggest that Truncate cannot be used for times >= time.Hour because of timezones.
I doubt we can actually change the implementation of Truncate at this point, so I've marked this a Documentation bug.
The text was updated successfully, but these errors were encountered: