<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi Itai,<div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class=""><div class="">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.</div></div><div class=""><br class=""></div><div class="">— Pitiphong P.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On 7 Sep BE 2560, at 01:03, Itai Ferber <<a href="mailto:iferber@apple.com" class="">iferber@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
<meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8" class="">
<div class="">
<div style="font-family:sans-serif" class=""><div style="white-space:normal" class=""><p dir="auto" class="">Hi Pitiphong,</p><p dir="auto" class="">Don’t worry — your original email was clear, and we are on the same page about <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date{En,De}codingStrategy</code> and <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents{En,De}codingStrategy</code> being separate things.<br class="">
To clarify my points, though, there are two main things I want to say:</p>
<ol class="">
<li value="1" class="">I think there is a mismatch here between your goal of representing the components of a date (and what <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> can specifically hold) and the goal of ISO 8601</li>
<li value="2" class="">I think that there is an inherent problem in parsing <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> due to ambiguity</li>
</ol><p dir="auto" class="">I think both of these issues can be solved by reading and writing a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code> (formatted however you need it to be) instead of <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code>.</p><p dir="auto" class="">To elaborate:</p>
<ul class="">
<li class=""><p dir="auto" class=""><code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> is meant to be a container for an <em class="">arbitrary</em> subset of information about a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code>. A <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code> represents a specific instant in time, but <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> are effectively meaningless without additional context. In the examples that you give, it’s possible to represent the concepts at hand with <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code>, but in order to make those components actionable and meaningful, you still need to convert them to <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code>s. Note also that:</p>
<ul class="">
<li class="">It’s entirely possible to create a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> which represents a date which does not exist, or a time which does not exist</li>
<li class="">Any of these concepts can also be represented by a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code> instead of just components; e.g., an all-day event can be represented by a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code> that represents the beginning of the day (<code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">00:00:00</code>) and a flag that indicates that the time of the event can be ignored, or by a start <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code> that represents the start of the day and and end <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code> that represents the end of the day</li>
</ul></li>
<li class=""><p dir="auto" class="">Unlike <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code>, 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 <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> instances which simply cannot be represented by an ISO 8601 string</p></li>
<li class=""><p dir="auto" class="">There is also the issue of decoding arbitrary ISO 8601 strings into <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code>. <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code>, 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:</p>
<ul class="">
<li class="">ISO 8601 allows for date representations by year, month, and day (<code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">YYYY-MM-DD</code>), among other forms. But it also allows days to be left unspecified (<code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">YYYY-MM</code>), and even months (<code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">YYYY</code>)</li>
<li class="">Similarly, it allows for a time representations by hour, minute, and second (<code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">hh:mm:ss</code>), but also just hour and minute (<code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">hh:mm</code>), and just hour (<code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">hh</code>). Importantly, it allows time separators to be omitted (<code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">hhmmss</code>, <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">hhmm</code>, <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">hh</code>)</li>
<li class="">Consider then, attempting to parse the string <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">"2017"</code> without any context — what <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> should be read out? Intuitively, <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">2017</code> looks like a year (<code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">YYYY</code>), but it is equally valid to parse as the time <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">20:17</code> (<code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">hhmm</code>). Without knowing the expected format, parsing is ambiguous</li>
</ul><p dir="auto" class="">We cannot promise to parse <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> in all cases because there are many combinations of strings that are just completely ambiguous. </p></li>
<li class=""><p dir="auto" class="">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 <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code> and a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateFormatter</code> (or if you need ISO 8601 specifically, <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">ISO8601DateFormatter</code>)? With a formatter, the format is unambiguous because you explicitly provide it, and there is nothing the date can’t represent that <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> 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?]</p></li>
<li class=""><p dir="auto" class="">And lastly, if <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">.iso8601</code> is not necessarily a good fit for this strategy, what separates <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">.custom</code> from just overriding <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">encode(to:)</code> and <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">init(from:)</code> and writing the components out in the format that you need?</p></li>
</ul><p dir="auto" class="">I think answers to these questions can help us push this forward. :)</p><p dir="auto" class="">— Itai</p><p dir="auto" class="">On 5 Sep 2017, at 10:41, Pitiphong Phongpattranont wrote:</p>
</div>
<div style="white-space:normal" class=""></div>
<blockquote style="border-left:2px solid #777; color:#777; margin:0 0 5px; padding-left:5px" class=""><div id="0AA36A42-DC6C-4D81-88FB-6C1EA9BC207C" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi Itai,<div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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.)</div><div class=""><br class=""></div><div class="">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</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">Thank you</div><div class="">— Pitiphong P.</div><div class=""><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On 6 Sep BE 2560, at 00:15, Itai Ferber <<a href="mailto:iferber@apple.com" class="">iferber@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
<meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8" class="">
<div class="">
<div style="font-family:sans-serif" class=""><div style="white-space:normal" class=""><p dir="auto" class="">Hi Pitiphong,</p><p dir="auto" class="">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.<br class="">
What is the use case in mind for needing to encode and decode <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> directly, as opposed to encoding and decoding a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code> instance and pulling the components you need from that?</p><p dir="auto" class="">From a correctness standpoint, I also want to point out that <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> is really just a "bag of stuff" that doesn’t necessarily mean much until converted into a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code> through a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Calendar</code> and a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">TimeZone</code>. 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 <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> that don’t really make sense for (or are not supported by) ISO-8601-formatted dates. For instance, you can have a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> which just has a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">TimeZone</code>, but ISO 8601 does not allow representing a time zone without a corresponding time. <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DateComponents</code> also, for instance, has a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">quarter</code> component (among others) which I’m almost certain ISO 8601 has no equivalent for.</p><p dir="auto" class="">Given that conceptual mismatch, I think we’d need a very compelling use case to support this over simply using <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">Date</code>.</p><p dir="auto" class="">— Itai</p><p dir="auto" class="">On 3 Sep 2017, at 0:55, Pitiphong Phongpattranont via swift-evolution wrote:</p>
</div>
<div style="white-space:normal" class=""><blockquote style="border-left:2px solid #777; color:#777; margin:0 0 5px; padding-left:5px" class=""><p dir="auto" class="">Hi folks, I have an idea on improving the JSON{Encoder/Decoder} to pitch.<br class="">
<br class="">
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 (<a href="https://en.wikipedia.org/wiki/ISO_8601" style="color:#777" class="">https://en.wikipedia.org/wiki/ISO_8601</a>) 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`.<br class="">
<br class="">
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<br class="">
<br class="">
Here’s an initial `DateComponentsStrategy` strategy that I want JSON{Encoder/Decoder} I can think of now, any suggestion is welcomed.<br class="">
<br class="">
```swift<br class="">
/// The strategy to use for encoding `DateComponents` values.<br class="">
public enum DateComponentsStrategy {<br class="">
/// Defer to `Date` for choosing an encoding. This is the default strategy.<br class="">
case deferredToDateComponents<br class="">
<br class="">
/// Encode the `Date` as an ISO-8601-formatted string (in RFC 3339 format).<br class="">
case iso8601<br class="">
<br class="">
/// Encode the `Date` as a custom value encoded by the given closure.<br class="">
///<br class="">
/// If the closure fails to encode a value into the given encoder, the encoder will encode an empty automatic container in its place.<br class="">
case custom((DateComponents, Encoder) throws -> Void)<br class="">
}<br class="">
```<br class="">
<br class="">
What do you guys think about this pitch?<br class="">
<br class="">
<br class="">
Pitiphong Phongpattranont<br class="">
_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="color:#777" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></p>
</blockquote></div>
<div style="white-space:normal" class="">
</div>
</div>
</div>
</div></blockquote></div><br class=""></div></div></div></blockquote>
<div style="white-space:normal" class="">
<blockquote style="border-left:2px solid #777; color:#777; margin:0 0 5px; padding-left:5px" class="">
</blockquote></div>
<div style="white-space:normal" class="">
</div>
</div>
</div>
</div></blockquote></div><br class=""></div></body></html>