问题
I am trying to create an Instant
based upon a B.C.E. year in the Gregorian calendar.
Here is what I have so far:
Instant.FromDateTimeOffset(new DateTimeOffset(-1000, 10, 01,
0, 0, 0, 0,
new System.Globalization.GregorianCalendar(),
new TimeSpan()));
I get the error:
An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll Additional information: Year, Month, and Day parameters describe an un-representable DateTime.
Edit
Doing some research on NodaTime
, I can see that it does have the ability to represent the dates I want, as it can accept negative ticks from the Unix epoch:
The Noda Time Instant type represents a point on this global timeline: the number of ticks which have elapsed since the Unix epoch. The value can be negative for dates and times before 1970 of course - the range of supported dates is from around 27000 BCE to around 31000 CE in the Gregorian calendar. - http://nodatime.org/1.3.x/userguide/concepts.html
So I would like to know how to do this using NodaTime
rather than create my own implementation, as is mentioned here for instance.
回答1:
The correct way to create a BCE date in Noda Time is like this:
LocalDate date = new LocalDate(Era.BeforeCommon, 1000, 10, 1);
This gives a LocalDate
object, which is representative of just having a date. You asked for an Instant
, which represents an exact point in time. These are two very different concepts.
In order to get an Instant
from a LocalDate
, one has to make a few assertions:
- What time of day did it occur?
- What time zone was it in?
- Is the time valid and unambiguous on that date within that zone?
Let's pick midnight for the time and UTC for the time zone:
Instant instant = date.AtMidnight().InUtc().ToInstant();
Since we chose UTC, we didn't have to address the valid/unambiguous question. With other zones, we would use one of the InZone
methods instead of InUtc
.
Also - you can indeed create an Instant
directly (as Caramiriel showed), but be careful. Year 1 BCE is represented by year 0, so if you want 1000 BCE, you'd have to pass -999, not -1000.
Instant instant = Instant.FromUtc(-999, 10, 1, 0, 0, 0);
Again, this assumes the time at midnight and the UTC time zone.
Finally, keep in mind that none of these calendar systems or time zones actually existed during that time period, and usually when working with dates so old, the time part is not very accurate or relevant. Therefore, I recommend you attempt to only work in terms of LocalDate
objects, and not use Instant
at all, if you can.
来源:https://stackoverflow.com/questions/32353262/create-instant-using-a-negative-year