This thread is a perfect encapsulation of the fallacies and misconceptions around date and time programming. It also highlights how inaccurate our language is when dealing with dates and times.
Names are made up
Underlying the proposals and ideas tossed around this thread is the fundamental misconception that there are algorithms that can be used to manipulate “wall dates” (words and numbers that you might find written on a calendar hanging on the wall of your home). This is false. All names and numbers used with calendars are entirely made up. They can change. They have superficial patterns but are not required to follow those patterns. The fundamental problem is not the code nor operating system nor ICU version… the problem is humans. The names we give to segments of time are imagined up by humans, and humans change their mind. All the time. With short notice.
We cannot assume any linearity to dates and times, because of political influences. December 29th is usually followed by December 30th, but wasn’t if you lived in Samoa or Tokelau in 2011. That was a political decision that you can never account for ahead of time. This was a change to the timezone itself, which affected the names that country gave to their perception of their moments in time. So while Daylight Saving Time (a series of rules which affect the names a calendar gives to moments in time) typically do not extend more than an hour or so forward or backward in time, the underlying premise that “timezones themselves affect the name, and timezones are regulated by political bodies” means that date offsetting can never be a wholly algorithmic operation.
Names are ranges
Leading up to the next great flaw in this thread is the idea that “a wall calendar value” is a single concrete thing. This is also false. The true unit of time is an instantaneous, geometrically invisible point called “Planck time”. We measure Planck time using atomic clocks to come up with the SI Base Unit of a “second”, which is not ¹/₈₆₄₀₀th of a day.
Names that we give to human-perceivable time are therefore representative of ranges of time. A “calendrical second” represents all the possible geometrically small moments that happened in that one tick of a second hand. Even nanoseconds or femtoseconds are themselves ranges of Planck time.
So, it is convenient to point to a day on a calendar and say “that is one, isolated thing”, but it is fundamentally inaccurate: calendars break up time into ranges.
Kinds of Named Values
Therefore, when we consider something like “June 2nd, 2014”, there are multiple conflicting meanings for this, and this has also been very evident in this thread. There are two main flavors of calendar values: fixed ones and floating ones, and they have been conflated in this thread to great confusion. A “fixed” value is a one that corresponds to one-and-only-one range of “instants”. An example of this would be something like “June 2nd, 2014 in the Pacific time zone”. That will always represent the unix timestamp range of 1401692400.0 ..< 1401778800.0.
A “floating” value, however, can represent many possible ranges of values. “June 2nd, 2014” is a floating value, because it does not have a time zone. In Samoa (Pacific/Apia), “June 2nd, 2014” would represent the unix timestamp range of 1401620400.0 ..< 1401706800.0. However, a few miles away in American Samoa (Pacific/Pago_Pago), it would be 1401706800.0 ..< 1401793200.0. These ranges do not overlap. A “floating” value cannot be fixed (or anchored) to any single moment in time.
So when we talk about birthdays, it’s important to remember that this is a floating value. One observes the birthday in whatever timezone you happen to find yourself in on the day of the year that happens to have the same month-and-day names as the day on which you were born. You don’t follow necessarily follow the timezone in which you were born.
(And we're not even going to touch the concept of perceived time, which is the idea that someone awake at 12:03 AM on a Saturday will still likely consider it as part of Friday simply because they haven't slept yet)
The Real Answer
The real answer to this is that, since all perceptions and names of times are subject to humanity’s whims and political machinations, you can never reliably come up with a way to algorithmically manipulate dates. You must always use a Calendar. The Calendar type is how we encode the rules we’re aware of regarding time’s names. It relies on a list of exceptions and tweaks that get updated over-the-air by Apple and a small group of very devoted enthusiasts, and even that is incomplete. The list of rules and exceptions gets updated multiple times a year, changing both future names of time and past names, as our understanding of history evolves.
So again, we should not adopt this idea in Foundation, because it is already implemented correctly. We have Date to represent our base “moment in time” concept (despite having a name which we all know is a bad one), and we have DateComponents to represent the various portions of the name for that moment. We have Calendar to move back and forth between the two. We have TimeZone to encode the list of rules and exceptions for how Calendar comes up with those names, and we have Locale to encapsulate the rules for “rendering” those names into human-readable text, done via one of the various formatting APIs.
Could the whole system be better? Absolutely; that’s why I implemented by own Time library; it makes these concepts of fixed-versus-floating values part of the API, so you must always be aware of exactly what you need. But it’s also the kind of domain-level need that not every Swift process needs, and therefore should not be part of Foundation. Foundation provides the building blocks, as it should.