-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: time: export zone and zoneTrans, and add a function to generate a Location #49951
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
Can't you load the Location from VTIMEZONE.TZID? |
Regrettably, it's not that simple. This works for components created by some applications, but not all. Looking at my personal calendar, about 30% fail to parse when using this assumption. Some just have a TZID of Some of the ones that say Aside from the anecdotal data, it's not safe to assume the
FWIW, this approach you're suggesting is the one we initially took, and that's how we discovered this problem, apologies for not mentioning it initially.
This won't yield the right results for repeating events (e.g.: a repeating event that repeats every day at 10:00, for a timezone with some DST). It's also a bit problematic in that de-serialising the data, and the serialising it again would result in some data loss, and if the date for the iCalendar component is changed the timezone needs to be re-read since it's DST data has been lost. |
time.Location
structtime.Location
struct
CC @ianlancetaylor who seems to have modified this relatively recently. Maybe this should be a proposal? @WhyNotHugo if you have a particular API in mind that would serve your use-case, then proposing that and having a discussion on that could be fruitful. |
The Rename the current With both func NewLocationFromZoneData(name string, zones []Zone, zoneTrans []ZoneTrans) Location... I tried thinking of alternative APIs without using |
time.Location
struct
This seems like a reasonable thing to do, but we probably want to define new structs that we're more willing to live with long term. The current zone and zoneTrans are clearly not ready for public consumption. Just to start things rolling:
Does this make sense? Should we just have a single slice with a Zone pointer inside the ZoneChange? |
This proposal has been added to the active column of the proposals project |
As a reference, here's a referrence BEGIN:VTIMEZONE
TZID:Europe/Amsterdam
BEGIN:DAYLIGHT
DTSTART:19810329T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
TZNAME:CEST
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19961027T030000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:CET
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
END:STANDARD
END:VTIMEZONE There's a key trait about it: the fact that is starts on the last sunday of a given month, but I'm not sure the above API can actually represent that. I've found others that start on the first and second sunday of the month. Potentially any valid Trying to support something as flexible as icalendar might be too much complexity, and it's not worth it unless it's not needed (and I hope someone will correct me if any super-werid DST exists out here that breaks my assumptions). |
For the record, #20629 is the proposal that led to adding If we expose structs with zone transition information to construct new Locations, we should consider whether/how to allow reading the zone transition information from Locations. Even if we only want to add an API to create new locations as part of this proposal, an API to read the transitions would probably use the same zone types if we add such API in the future. Use-cases for reading include things like "When is the next DST transition?", but I don't know how often this is needed. I also have some unfinished and unpublished experimental code for strict alternative to time.Parse that could benefit from reading the zone transitions as I wouldn't need to parse the tzdata files myself (but I'm not convinced that it's worth any changes in the standard library).
I agree with this.
What would the be the requirements for the parameters? I think
Advantages of this seem to be that:
On the other hand, currently some zones don't need to be referenced by a transition. In particular, if the first zone is not used by a transition, it is used for times before the first transition time: Lines 193 to 212 in 8ff254e
We'd probably need a way to specify the zone to be used before the first transition time explicitly.
If we are going to add an API to create new Locations programmatically, I think we need to support everything that
The extend string rule in tzdata supports things like last sunday of a given month. There is one start rule and one end rule in the extend string. So it might be possible to build such rule from the VTIMEZONE in practice, although theoretically VTIMEZONE can contain multiple rules. |
It would be appropriate to produce an extend string for any entry in VTIMEZONE that does not have a termination date. Hopefully there would be at most two such entries, one for standard time and one for daylight time. Turning the VTIMEZONE start and end times into a |
There is a |
Another use-case for reading the zone data from |
It seems like we need some form for the future extension string, if we are to add this API. Or is VTIMEZONE the only other possible format, and we should add it directly? What APIs do other languages provide for this kind of need? |
I've read through the code and spec a few time, and I'm not sure what the Is it the name of the
I've mixed feeling about this approach. It sounds like a lot of "noise" to convert to an entirely different format to create a I worry a bit that the extra conversion might add quite a bit of unnecessary overhead. For example, a cli calendar app I'm porting to golang reads 3k icalendar entries, so this extra conversion for each item doesn't sound minimal. It might be worth giving a shot though, at least to have some understanding of how much overhead this is. |
The "extend string" is roughly documented at https://man7.org/linux/man-pages/man3/tzset.3.html. It is the "first format" permitted in the |
Ah, thanks for the clarification. |
Still wondering about:
|
Rust uses a Python is duck-typed, so some libraries just have their own timezone implementation that matches the interface of the regular one, and they can be used interchangeably. This does shed light onto an entirely different alternative: It's possible to create a
I believe so. JMAP calendar uses just IANA names. I can't think of many other specs around calendaring / timezones. |
Backwards-compatibility concerns aside, even if you change all functions that take But we need to keep in mind that we also need to be able to convert a |
So I tried writing some code for testing. https://github.com/martin-sucha/timezones creates new When converting to tzif data, we need zone indexes, not pointers because there is a limit for how many zones can be present. Benchmarks:
And https://github.com/martin-sucha/vtimezone2tzif converts a Benchmark: ToLocationTemplate parses VTIMEZONE and builds
@WhyNotHugo please try if something like that could work for you. Also I think it would be good to have some testing corpus of iCalendar files to see if all can be supported by the tzif format. There is another argument against using pointers in var zones []Zone
var changes []Change
for i := 0; i < 100; i++ {
zones = append(zones, Zone{...})
changes = append(changes, Change{Start: t, &zones[i]})
} In this case, when append to |
Yeah, libraries would need to kind of "opt-in" into the new interface by updating functions that receive I think this Do you think it's sensible to try and copy this implementation/API into Location? This would allow constructing instances without going through tzif as an intermediate format at all and reading all the data that would be needed to serialise a Regarding sample data: I've extracted |
If you have a vtimezone2tzdata, then it seems like that could be a 3rd-party package used in concert with time.LoadLocationFromTZData, and then we don't need to add code to package time at all. Do I have that right? |
Seems like we are still waiting to find the answer to:
|
There are arguments against exporting the extend string, see #50062 (comment) So it seems we'd need a different API if we wanted to expose it. Also, the
Note that That leaves the question whether to expose
I think (1) is solved because https://github.com/martin-sucha/timezones exists now (and the code is ~250 lines of code). As for (2), it seems that the performance of going through tzdata will be only about 2.5 times (5.38µs versus 2.20µs in the benchmark I posted previously) slower than allocating a There is another argument, which are the limitations imposed by the tzif file format. Currently it allows only a small number of zone names (all names must fit into a 255 byte buffer) so the timezones package must deduplicate them when writing the data. It is not clear whether this will ever be a problem in practice though. So for the use case of converting a |
It seems that code to convert a |
Great, thanks. For the reverse, it seems like if you have a database of VTIMEZONEs you want (or you grab the timezone database and use github.com/martin-sucha/timezones to get VTIMEZONES), then you can just use time.Locations constructed from it and not worry about converting the "native" time.Locations back to VTIMEZONE. Note that we also don't provide a way to convert the "native" time.Locations to tzdata format. Especially on Windows, that would be difficult. It sounds like we probably do not need to make modifications to the time package here. |
Based on the discussion above, this proposal seems like a likely decline. |
I've been looking more into github.com/martin-sucha/timezones, and it seems it may be a feasible workaround. It does seem like there's going to be a lot more data conversion and parsing that necessary, but seems usable enough. I'm not opposed to dropping this proposal. |
This will be useful for converting timezones to other formats, for example to VTIMEZONEs. See golang/go#49951 (comment)
No change in consensus, so declined. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?What did you do?
Trying to create an instance of
time.Location
based on data read from an iCalendar file.What did you expect to see?
Some way to construct a
time.Location
instance.What did you see instead?
No public function to create such an instance;
time.Location
instances can only be created withtime.LoadLocationFromTZData
.More background
We're trying to parse iCalendar files, which contain
VTIMEZONE
entries, which represent a timezone (time.Location
in go).However, there's no public function to create
time.Location
instances, and the only way to create them is using using IANA Time Zone database-formatted data, which is a rather complex binary format.So currently, the only way to create
time.Location
entries for the timezones read, is to convert them into the above mentioned binary format, and then feed that intotime.LoadLocationFromTZData
.This has two big problems: (1) it's very complex to convert
VTIMEZONE
data into that binary format, and also, needless complexity (2) it's very inefficient, since every entry read has to be converted into an intermediate representation, to then be parsed again and then converted into the final one.Making the
time.zone
andtime.zoneTrans
public (e.g.: renaming them intotime.Zone
andtime.ZoneTrans
, plus adding atime.LocationFromZoneInfo(name string, zones []Zone, zoneTrans []ZoneTrans) Location
function would very much help address this issue.I'd be happy to try and tackle the implementation myself, if the approach seems sound, but I figure it's best to ask for feedback on that first; it's possible that someone has cleaner approaches to solving this issue, or that this breaks some existing convention.
As an alternative approach, a function that takes a string with an RFC-5545 compliant
VTIMEZONE
and returns atime.Location
instance might be a cleaner API, but I'm not sure if adding iCalendar-specific code into this package would be deemed acceptable.The text was updated successfully, but these errors were encountered: