Re: Issue 215 in noda-time: LocalDateTime.ToString() throws exception near end of time

32 views
Skip to first unread message

noda...@googlecode.com

unread,
Apr 20, 2013, 5:00:46 AM4/20/13
to noda...@googlegroups.com
Updates:
Summary: LocalDateTime.ToString() throws exception near end of time
Status: Accepted
Labels: Milestone-1.1-consider

Comment #2 on issue 215 by malcolm.rowe: LocalDateTime.ToString() throws
exception near end of time
http://code.google.com/p/noda-time/issues/detail?id=215

This does appear to be a regression against 1.0.x, probably because of
r7a65b5f5f560 (issue 197).

In fact, I think you can reproduce essentially the same problem with simply:

Console.WriteLine(Instant.MaxValue.InUtc());

Under 1.0.1, this produces:

Local: 01/01/31197 02:48:05 Offset: +00 Zone: UTC

Under 1.1.0, I get:

Unhandled Exception: System.ArgumentOutOfRangeException: Value should be in
range [-27255-31195]
Parameter name: year
31197
at NodaTime.Utility.Preconditions.CheckArgumentRange (System.String
paramName, Int32 value, Int32 minInclusive, Int32 maxInclusive) [0x00000]
in <filename unknown>:0
at NodaTime.Calendars.BasicCalendarSystem.GetYearTicks (Int32 year)
[0x00000] in <filename unknown>:0
at NodaTime.Calendars.GregorianCalendarSystem.GetYearTicks (Int32 year)
[0x00000] in <filename unknown>:0
at NodaTime.Calendars.BasicGJCalendarSystem.GetMonthOfYear (LocalInstant
localInstant, Int32 year) [0x00000] in <filename unknown>:0
at NodaTime.Calendars.BasicCalendarSystem.GetDayOfMonth (LocalInstant
localInstant) [0x00000] in <filename unknown>:0
at NodaTime.Fields.BasicDayOfMonthDateTimeField.GetValue (LocalInstant
localInstant) [0x00000] in <filename unknown>:0
at NodaTime.LocalDateTime.get_Day () [0x00000] in <filename unknown>:0
at NodaTime.Text.LocalDateTimePatternParser.<.cctor>b__b (LocalDateTime
value) [0x00000] in <filename unknown>:0
at (wrapper delegate-invoke) <Module>:invoke_int__this___LocalDateTime
(NodaTime.LocalDateTime)
at
NodaTime.Text.Patterns.DatePatternHelper+<>c__DisplayClass15`2+<>c__DisplayClass18[NodaTime.LocalDateTime,NodaTime.Text.LocalDateTimePatternParser+LocalDateTimeParseBucket].<CreateDayHandler>b__13
(LocalDateTime value, System.Text.StringBuilder sb) [0x00000] in <filename
unknown>:0
at (wrapper delegate-invoke)
<Module>:invoke_void__this___LocalDateTime_StringBuilder
(NodaTime.LocalDateTime,System.Text.StringBuilder)
at (wrapper delegate-invoke)
<Module>:invoke_void__this___LocalDateTime_StringBuilder
(NodaTime.LocalDateTime,System.Text.StringBuilder)
at (wrapper delegate-invoke)
<Module>:invoke_void__this___LocalDateTime_StringBuilder
(NodaTime.LocalDateTime,System.Text.StringBuilder)
at (wrapper delegate-invoke)
<Module>:invoke_void__this___LocalDateTime_StringBuilder
(NodaTime.LocalDateTime,System.Text.StringBuilder)
at (wrapper delegate-invoke)
<Module>:invoke_void__this___LocalDateTime_StringBuilder
(NodaTime.LocalDateTime,System.Text.StringBuilder)
at (wrapper delegate-invoke)
<Module>:invoke_void__this___LocalDateTime_StringBuilder
(NodaTime.LocalDateTime,System.Text.StringBuilder)
at (wrapper delegate-invoke)
<Module>:invoke_void__this___LocalDateTime_StringBuilder
(NodaTime.LocalDateTime,System.Text.StringBuilder)
at (wrapper delegate-invoke)
<Module>:invoke_void__this___LocalDateTime_StringBuilder
(NodaTime.LocalDateTime,System.Text.StringBuilder)
at (wrapper delegate-invoke)
<Module>:invoke_void__this___LocalDateTime_StringBuilder
(NodaTime.LocalDateTime,System.Text.StringBuilder)
at (wrapper delegate-invoke)
<Module>:invoke_void__this___LocalDateTime_StringBuilder
(NodaTime.LocalDateTime,System.Text.StringBuilder)
at
NodaTime.Text.Patterns.SteppedPatternBuilder`2+SteppedPattern[NodaTime.LocalDateTime,NodaTime.Text.LocalDateTimePatternParser+LocalDateTimeParseBucket].Format
(LocalDateTime value) [0x00000] in <filename unknown>:0
at
NodaTime.Text.Patterns.PatternBclSupport`1[NodaTime.LocalDateTime].Format
(LocalDateTime value, System.String patternText,
NodaTime.Globalization.NodaFormatInfo formatInfo) [0x00000] in <filename
unknown>:0
at NodaTime.LocalDateTime.ToString () [0x00000] in <filename unknown>:0
at System.String.Concat (System.Object[] args) [0x00039] in
/home/malcolm/noda-time/mono-2.10.9/mcs/class/corlib/System/String.cs:2134
at NodaTime.ZonedDateTime.ToString () [0x00000] in <filename unknown>:0
at System.IO.TextWriter.Write (System.Object value) [0x00006] in
/home/malcolm/noda-time/mono-2.10.9/mcs/class/corlib/System.IO/TextWriter.cs:163
at System.IO.TextWriter.WriteLine (System.Object value) [0x00000] in
/home/malcolm/noda-time/mono-2.10.9/mcs/class/corlib/System.IO/TextWriter.cs:273
at System.IO.SynchronizedWriter.WriteLine (System.Object value) [0x00008]
in
/home/malcolm/noda-time/mono-2.10.9/mcs/class/corlib/System.IO/TextWriter.cs:563
at System.Console.WriteLine (System.Object value) [0x00000] in
/home/malcolm/noda-time/mono-2.10.9/mcs/class/corlib/System/Console.cs:423
at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0


Note that it appears to be the ToString() that causes this: simply
computing the LocalDateTime is fine.

--
You received this message because this project is configured to send all
issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings

noda...@googlecode.com

unread,
Apr 20, 2013, 6:15:46 AM4/20/13
to noda...@googlegroups.com

Comment #4 on issue 215 by jonathan.skeet: LocalDateTime.ToString() throws
In some ways I see this as *not* a regression. I think I'd prefer to give
an exception than a misleading string representation - it's not like there
actually *is* a transition at 01/01/31197 02:48:05.

After the refactoring at NDC, I'm hoping to prevent LocalDate/LocalDateTime
values which are outside the range of the calendar they're associated with
from ever escaping - at which point we'd throw a more meaningful exception
earlier.

noda...@googlecode.com

unread,
Apr 20, 2013, 4:06:12 PM4/20/13
to noda...@googlegroups.com

Comment #5 on issue 215 by malcolm.rowe: LocalDateTime.ToString() throws
The regression I was flagging was that Instant.MaxValue.InUtc().ToString()
(arguably) DTRT in 1.0.x and fails completely in 1.1.0.

If you're saying that our proleptic calendars are not, in fact, intended to
be proleptic, then it's probably not a regression.

noda...@googlecode.com

unread,
Apr 21, 2013, 3:07:07 AM4/21/13
to noda...@googlegroups.com

Comment #6 on issue 215 by jonathan.skeet: LocalDateTime.ToString() throws
I think we may disagree about the meaning of proleptic :)

I'm saying that Instant.MaxValue is meant to be "the end of time" - and the
end of time isn't 31197 AD. I think we probably want to special-case
Instant.MaxValue => LocalTime (any calendar) to give LocalInstant.MaxValue
in that calendar, and special-case that value to give "EOT" as a ToString
value. Maybe. Either that, or throw an exception.

Fuel for further discussion though.

I suspect that pretty much *any* sensible change (even restoring the old
behaviour) could be tricky in the 1.1 branch.

noda...@googlecode.com

unread,
Apr 22, 2013, 3:21:22 PM4/22/13
to noda...@googlegroups.com

Comment #7 on issue 215 by mj1856: LocalDateTime.ToString() throws
The only real reason I am concerned with EOT values is to denote that
something is intended to go on forever. While I understand that it's hard
to pin a date on it, it still does exist on the timeline. Just like +/-
infinity are still on the line of Real numbers.

Perhaps someone doing astronomical doomsday calculations cares about years
that large, but I guess I'm one of those that would stop at 9999 and call
that good enough. From my perspective, anything > 9999 is close enough to
infinity. :)

So what would I expect? If End equals EOT, then IsoLocalEnd also equals
EOT. EOT plus or minus anthing is still EOT. Same for beginning of time
values (BOT)

I suppose the alternative would be for some of these properties to be
nullable. There would then be no concept of EOT, but anywhere that might
go on forever would be a Nullable<Instant> or Nullable<LocalDateTime>.
Intervals being a good example. The only problem there is that Null means
either BOT or EOT depending on where it is used, so comparisons can be
problematic.

noda...@googlecode.com

unread,
Jun 6, 2013, 9:04:23 AM6/6/13
to noda...@googlegroups.com

Comment #8 on issue 215 by qcastel...@gmail.com: LocalDateTime.ToString()
Sorry for the duplicate before i did no found this post :s

My concern about MinValue and MaxValue are more about finding a convention
saying that the field is actually empty without using a nullable or as
mj1856 to have a date that will always fit some tests.

the thing is, outside these cases using a date that is close to EOT or BOT
would most certainly be a bug.
To my opinion it is too tempting to use those values available in Instant
to let the serialisation crash. I don't think i am the only one who is
using this kind of coding convention.

To me the best would be to crash on any value above calendar capacity
except for EOT and BOT which should give the max and the min of the
considered calendar.

I understand the problem is bigger than that and this may not be the
reliant comportment you want but i think this is a really tricky problem so
good luck with it :)

Anyways thanks again for your API and your time :)

noda...@googlecode.com

unread,
Jun 6, 2013, 9:13:33 AM6/6/13
to noda...@googlegroups.com

Comment #9 on issue 215 by jonathan.skeet: LocalDateTime.ToString() throws
Your description of EOT and BOT being valid, but nearby ones not being
valid is where I'd like to go too. Just don't expect it to happen any time
soon - especially when I need to balance performance requirements around it
too.

I would like to discourage the use of BOT/EOT as substitutes for null
values, mind you - they're meant to be meaningful values for cases like "an
interval which stretches from the beginning of time until X". But they
should definitely be serializable... (Both XML and JSON.)

noda...@googlecode.com

unread,
Jul 26, 2013, 2:31:37 PM7/26/13
to noda...@googlegroups.com
Updates:
Labels: -Milestone-1.1-consider Milestone-1.3-consider

Comment #10 on issue 215 by jonathan.skeet: LocalDateTime.ToString() throws
We've fixed Instant.MinValue and Instant.MaxValue for release 1.2, but
*only* for Instant. A lot more work is needed to handle this sort of thing
in general, and I'm hoping to address that in 1.3 - so I'm punting this to
then for now.

noda...@googlecode.com

unread,
May 30, 2014, 4:37:46 AM5/30/14
to noda...@googlegroups.com
Updates:
Labels: -Milestone-1.3-consider Milestone-unscheduled

Comment #11 on issue 215 by malcolm.rowe: LocalDateTime.ToString() throws
(No comment was entered for this change.)

noda...@googlecode.com

unread,
Aug 2, 2014, 4:09:39 PM8/2/14
to noda...@googlegroups.com
Updates:
Status: Fixed

Comment #12 on issue 215 by jonathan.skeet: LocalDateTime.ToString() throws
Noda Time 2.0 fixes all of this. Any value you can create, you should be
able to format.

(There are some internal values which are unprintable, but that's a
different matter.)
Reply all
Reply to author
Forward
0 new messages