Hi Itai, Thanks for a good and solid explanation. First I want to express my use case that was the reason I try to pitch this idea. We have a schedule service and the data model that represent the occurrence holds an information on what date of this occurrence was created in terms of a date string “2017-09-06” which is conform to ISO 8601. In this case we don’t intend to store a `Date` value (which is a specific point in the time line) but only store an information of what date it was occurred. So I decided to parse the date string into a `DateComponents` value.
What motivates me to pitch this idea in the end was that I tried to rely on the auto synthesized code by the compiler. Since the `DateComponents` already conforms to the Encodable/Decodable protocol which already allow the compiler to synthesize the code for encode(to:) and init(from:), however since I need to decode from the data I told you at first, those generated code will fail to decode the `DateComponents` and cause me some bugs. That’s what encourage me to do this pitch. — Pitiphong P. > On 7 Sep BE 2560, at 01:03, Itai Ferber <ifer...@apple.com> wrote: > > Hi Pitiphong, > > Don’t worry — your original email was clear, and we are on the same page > about Date{En,De}codingStrategy and DateComponents{En,De}codingStrategy being > separate things. > To clarify my points, though, there are two main things I want to say: > > I think there is a mismatch here between your goal of representing the > components of a date (and what DateComponents can specifically hold) and the > goal of ISO 8601 > I think that there is an inherent problem in parsing DateComponents due to > ambiguity > I think both of these issues can be solved by reading and writing a Date > (formatted however you need it to be) instead of DateComponents. > > To elaborate: > > DateComponents is meant to be a container for an arbitrary subset of > information about a Date. A Date represents a specific instant in time, but > DateComponents are effectively meaningless without additional context. In the > examples that you give, it’s possible to represent the concepts at hand with > DateComponents, but in order to make those components actionable and > meaningful, you still need to convert them to Dates. Note also that: > > It’s entirely possible to create a DateComponents which represents a date > which does not exist, or a time which does not exist > Any of these concepts can also be represented by a Date instead of just > components; e.g., an all-day event can be represented by a Date that > represents the beginning of the day (00:00:00) and a flag that indicates that > the time of the event can be ignored, or by a start Date that represents the > start of the day and and end Date that represents the end of the day > Unlike DateComponents, ISO 8601 strings have some structure to them. They > cannot represent just a time zone, for instance, or some singular components > of a date/time (e.g. a month without a year, a day without a month and year, > a minute without an hour, a second without a minute and hour, etc.). I think > this is a relatively large conceptual mismatch that is worth considering > deeply. There are a lot of DateComponents instances which simply cannot be > represented by an ISO 8601 string > > There is also the issue of decoding arbitrary ISO 8601 strings into > DateComponents. DateComponents, having no structure at all, have no specified > format they can expect to decode from, and ISO 8601 does not always provide > that structure. Consider the following example: > > ISO 8601 allows for date representations by year, month, and day > (YYYY-MM-DD), among other forms. But it also allows days to be left > unspecified (YYYY-MM), and even months (YYYY) > Similarly, it allows for a time representations by hour, minute, and second > (hh:mm:ss), but also just hour and minute (hh:mm), and just hour (hh). > Importantly, it allows time separators to be omitted (hhmmss, hhmm, hh) > Consider then, attempting to parse the string "2017" without any context — > what DateComponents should be read out? Intuitively, 2017 looks like a year > (YYYY), but it is equally valid to parse as the time 20:17 (hhmm). Without > knowing the expected format, parsing is ambiguous > We cannot promise to parse DateComponents in all cases because there are many > combinations of strings that are just completely ambiguous. > > So, to get at the core of this — if there is a specific format that you would > like to encode to and from, why not do so with a Date and a DateFormatter (or > if you need ISO 8601 specifically, ISO8601DateFormatter)? With a formatter, > the format is unambiguous because you explicitly provide it, and there is > nothing the date can’t represent that DateComponents can. You can always > parse the date and pull out only those components that you care about. You > also mention interoperability with an external JSON source — how is that > source producing a string/parsing one back? [What I’m getting at here is: > what is the value of adding a new, potentially risky strategy over existing > methods that might work just as well, or better?] > > And lastly, if .iso8601 is not necessarily a good fit for this strategy, what > separates .custom from just overriding encode(to:) and init(from:) and > writing the components out in the format that you need? > > I think answers to these questions can help us push this forward. :) > > — Itai > > On 5 Sep 2017, at 10:41, Pitiphong Phongpattranont wrote: > > Hi Itai, > > I think my first pitch email was not clear enough and want to sorry for that. > I have been working on a calendar app for awhile and understand the concept > of calendar or date and time programming in some level. I didn’t pitch the > idea of encoding and decoding `Date` value with this > `DateComponents{Encoding/Decoding}Strategy`. I still agree that `Date` value > should be encoded/decoded with the `Date{Encoding/Decoding}Strategy`. The > DateComponents{Encoding/Decoding}Strategy I pitched only apply for > `DateComponents` value only. > > About the use case, I think there are some application which store an > information of a `Date` value that is not include a time value (A date of > September 6th, 2017) for example a calendar app which want to store the Start > and End date of an `All Day Event` with a value of DateComponents type or an > alarm app which want to store just a time of the day that user want to set an > recurring alarm (10:30am.) > > The problem I found with the current implementation is that I have no control > on how the DateComponents implement the conformance methods of the Encodable > and Decodable protocol. This means that if I have a service that serialize > those properties with a difference notation (ISO 8601 in my case) then I > cannot rely on the auto synthesized implementation from the compiler and need > to do a manual encoding/decoding by manually implement the Encodable and > Decodable > > Lastly, on the issue that `ISO8601` standard does not support every > components in DateComponents, I still haven’t thought this though and still > thinking about it. I want to pitch the idea first and would like to have a > discussion/brainstorm on should we do this and how we can do it. My backup > plan is doesn’t include the `iso8601` strategy but still have the `custom` > strategy for those who need to apply a custom encoding/decoding strategy > which will be apply to all values in a payload. Since we encode/decode a JSON > from one source at a time and the encoding/decoding strategy of > DateComponents of that source should be consistency throughout its types > (which may be the types that I own or the types from a 3rd party service), I > think this still is a valid use case for providing a custom strategy. > > Thank you > — Pitiphong P. > > >> On 6 Sep BE 2560, at 00:15, Itai Ferber <ifer...@apple.com >> <mailto:ifer...@apple.com>> wrote: >> >> Hi Pitiphong, >> >> Thanks for pitching this! My main question here is about the use case. Since >> encoding/decoding strategies apply to all values in a payload (whether or >> not those belong to types that you own), they inherently come with some risk. >> What is the use case in mind for needing to encode and decode DateComponents >> directly, as opposed to encoding and decoding a Date instance and pulling >> the components you need from that? >> >> From a correctness standpoint, I also want to point out that DateComponents >> is really just a "bag of stuff" that doesn’t necessarily mean much until >> converted into a Date through a Calendar and a TimeZone. There is somewhat >> of a mismatch between this "bag of stuff" and what ISO 8601 intends to >> represent — an actual date and time. It’s possible to represent things in a >> DateComponents that don’t really make sense for (or are not supported by) >> ISO-8601-formatted dates. For instance, you can have a DateComponents which >> just has a TimeZone, but ISO 8601 does not allow representing a time zone >> without a corresponding time. DateComponents also, for instance, has a >> quarter component (among others) which I’m almost certain ISO 8601 has no >> equivalent for. >> >> Given that conceptual mismatch, I think we’d need a very compelling use case >> to support this over simply using Date. >> >> — Itai >> >> On 3 Sep 2017, at 0:55, Pitiphong Phongpattranont via swift-evolution wrote: >> >> Hi folks, I have an idea on improving the JSON{Encoder/Decoder} to pitch. >> >> Since JSON doesn’t have a native representation for `DateComponents` like it >> doesn’t have for `Date` too so that there’re many ways to represent it in >> JSON, for example ISO 8601, UNIX timestamp, etc. for Date. There are also a >> few ways to represent `DateComponents` too, for example ISO 8601 >> (https://en.wikipedia.org/wiki/ISO_8601 >> <https://en.wikipedia.org/wiki/ISO_8601>) also describes how to represent >> some of the valid date components (e.g. "2017-09-03”). Unlike what >> JSON{Encoder/Decoder} does to represent `Date` value with several strategy >> but there is no support like that for `DateComponents`. >> >> The current implementation DateComponents is to encode/decode with >> KeyedContainer and cannot provide a custom or ISO 8601 compatible >> implementation. So I think JSON{Encoder/Decoder} should have a strategy for >> encoding/decoding `DateComponents` just like for Date >> >> Here’s an initial `DateComponentsStrategy` strategy that I want >> JSON{Encoder/Decoder} I can think of now, any suggestion is welcomed. >> >> ```swift >> /// The strategy to use for encoding `DateComponents` values. >> public enum DateComponentsStrategy { >> /// Defer to `Date` for choosing an encoding. This is the default strategy. >> case deferredToDateComponents >> >> /// Encode the `Date` as an ISO-8601-formatted string (in RFC 3339 format). >> case iso8601 >> >> /// Encode the `Date` as a custom value encoded by the given closure. >> /// >> /// If the closure fails to encode a value into the given encoder, the >> encoder will encode an empty automatic container in its place. >> case custom((DateComponents, Encoder) throws -> Void) >> } >> ``` >> >> What do you guys think about this pitch? >> >> >> Pitiphong Phongpattranont >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution> >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution