-
-
Notifications
You must be signed in to change notification settings - Fork 73
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
Support for reducing the use of time.Local
by allowing overrides.
#107
base: master
Are you sure you want to change the base?
Conversation
…ests. -- Minor syntax errors.
time.Local
by allowing overrides.
* master: Duplication issue fixed. Some multiple-ness. Test fixed. Resynced and moved some functions around #78 added functionnal option pattern for url parsing usage example, README calendar parsing url support # Conflicts: # components.go
Updated. |
// GetEndAt gets the date and time that the component finishes at, must not be an all day event. | ||
// Warning: by default uses "Local" timezone -- To overwrite it, supply the desired timezone as one of the optional arguments. Ie, GetEndAt(time.UTC) | ||
// If you have a property that specifies a timezone then that is used instead. | ||
func (cb *ComponentBase) GetEndAt(ops ...any) (time.Time, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a breaking change. Anyone who uses types embedding ComponentBase through an interface will have to update the method signature in their interface. If any module has two or more dependencies which do this and they don't all have the same interface, then it will be impossible to build that module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be quite happy adding a new constructor function like this if we want to use the functional options pattern to resolve this.
type Option func(*Calendar)
func ParseCalendarOpts(r io.Reader, opts ...Option) (*Calendar, error)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The constructor is unlikely to be in any interface as it doesn't have a receiver.
Should I provide a proxy struct for quick adaptation. (This library is still pre v1 which is not something I want to say but there are a couple of changes I might need to make that are breaking. If only there was a way of finding out who was using what...)
type NoOpComponentBase struct {
*ComponentBase
}
func (nocb *NoOpCompontentBase) GetEndAt() (time.Time, error) {
return nocb.ComponentBase.GetEndAt()
}
Which could be used as a dropin replacement? + Documentation. A little more work when they upgrade but hopefully something I could put in the function documentation.
Does that work? Or will I need to:
func (cb *ComponentBase) GetEndAt() (time.Time, error) {
}
func (cb *ComponentBase) GetEndAtWithOptions(ops ...any) (time.Time, error) {
}
?
Are we talking specifically about GetEndAt
or the constructor?
Also what is the goal of using func() for the optional arguments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, you can make breaking changes without breaking the modules promise as you're v0.x. But you are easily the most popular (used by 327 public repos) and most mature Go ICS library. If it were my inbox I'd avoid breaking changes where practical. Otherwise jumping right to v2 to make breaking changes would be better.
I'm not sure how you would wire NoOpComponentBase
in? As ComponentBase
is exported, changing the type that things like VAlarm
embed is also a breaking change.
I still think choosing a fallback location when the Calendar
is instantiated is pretty clean, and a new constructor a pretty clean compatible change to do that. That's my opinion.
The reason for making option a type is so its clear what you provide, in my example it would use:
// InLocation provides an Option to set the fallback location. time.Time values
// for events in the calendar which have no explicit location, such as all day
// events, will use this location. The default fallback location is time.Local.
func InLocation(l time.Location) Option {
return func(c *Calendar) {
c.fallbackLocation = l
}
}
So that you can write:
cal, err := ics.ParseCalendarWithOpts(r, ics.InLocation(userLocation))
and according to Rob Pike interface{} says nothing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've replied in PR:
#107 (comment)
* master: Merge remote-tracking branch 'origin/master' into issue97 Fix Some larger upgrades. Tests added. # Conflicts: # components.go
Conflicts resolved. |
Hi @brackendawson I'm moving this out of the thread and into the PR; this is response to: #107 (comment)
Probably a v0.2 then? I'm really at a loss as to what to do here. I let some API conventions in which I kind of regret. I feel that a API breakage with a minor change to fix is preferable to a behavior change. However API pollution is preferable to both.
I hadn't actually considered that... I think using https://github.com/arran4/golang-ical/blob/master/cmd/issues/test97_1/main.go#L24-L25 While this definitely works for single timezone files. (Although if they haven't specified tz..) I also think the code base needs better handling of timezones, especially custom ones as in the linked example. Having a look at Even completely avoid it here:
Just assumes UTC is fine -- In most cases that will work, however (I would love to spend the time to really dig into this, and release a v1+ with all these things considered.) The proposal about So I guess;
|
If you choose to introduce a breaking change then it would be most helpful to move directly to v2.0, this is because your module name would change to
Oh believe me I know, even the Go maintainers bump into this, there's more than one place in the standard library where the API has had to be extended.
So the problem we were trying to address is how to convert ICS timestamps which have no known time zone into Go In the other direction, writing properties: vEvent.AddProperty(ics.ComponentPropertyDtStart, "20240929T144500", ics.WithTZID("Europe/Berlin")) I don't think an berlin, err := time.LoadLocation("Europe/Berlin")
if err != nil {
return err
}
vEvent.SetDtStart(time.Date(2024, 9, 29, 14, 45, 0, 0, berlin)) Now there is no error to handle in our code. |
Attempts to resolve: #99
@brackendawson please review.
Also let me know what comment style is best, happy for you to create a new PR with these commits and your own addendums / fixes of comments.