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

Reply via email to