I feel that not being able to round-trip Instant values is a serious
drawback. One of the basic tenets of ISO 8061 is the 'exchange of date and
time-related data'. If we can generate a string but then can not read it
back, we have an issue. Users will develop hacks to work around it.
I'm willing to look at the code and suggest a solution and then code it.
Jon, you are correct that negative years is an edge case. But after
entering the "pit of despair" (is this C# v Haskell Parsec), I still
believe we must address the issue in v1.
Formatting a negative year is typically NOT for human consumption. A
negative year, nearly always mean that the date is not in the current era. So, formatters should throw if the 'y' pattern char is used and an era is
not also being formatted. When an era is also being formatted then we
always format the absolute value of the year.
The current parser that throws when a 'y' pattern encounters a negative
year is correct!
We add a new pattern char 'E', which is an ISO 8061 expansion year. An
expansion year can be negative and/or more that 4 digits. When an
expansion year is formatted at least 4 digits are used. If more then 4
digits are required then a '+' (U+002B) is prepended (in accordance with
ISO 8061) when it is positive; otherwise, a '-' (U+002D) is prepended.
On parsing, the expansion year pattern optionally allows '+' or '-' and at
least 4 digits.
The Instant Extended ISO pattern then becomes:
E'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFF'Z'. And with other ISO patterns
the "yyyy" is replaced with "E".
There's no need to introduce anything extra. We already have y, yy, yyy etc
meaning "absolute year" and Y, YY etc meaning "year of era". "g" and "gg"
represent the name of the era.
So far I'm not seeing any justification for this being a v1-blocker. The
release will be useful to 99% of developers without changing this. Fixing
it later will require no breaking API change - it's just a format which
didn't work before will start to work. Why would we want to delay making
Noda Time available for a corner case which will impact so few people?
That's not to say we don't want to address it, just that I don't want to
hold up the v1 release for it.
No, absolute years are not always positive. As per the docs:
"Some calendars support multiple eras. For example, the ISO calendar
supports the B.C. / B.C.E. and A.D. / C.E. eras. A mapping is provided
between "year within era" and "absolute" year - where an absolute year
uniquely identifies the date, and does not generally skip. In the ISO
calendar, the absolute year 0 is deemed to be 1 B.C. and the absolute year
1 is deemed to be 1 A.D. thus giving a simplified arithmetic system.
Currently negative absolute years cannot be parsed, but will be formatted -
so "13 B.C." would be formatted as "-0012" using the "yyyy" format."
At this point I don't want to introduce a new pattern - I believe we can do
anything we need within the current code; we just need to allow parsing of
negative absolute years.