public override string ToString() { int y = 0, m = 0, d = 0; if (HasKnownYear() || HasKnownMonth() || HasKnownDay()) { int unmaskedVal = GetUnmaskedValue(); var dtx = CalendarConverter.jd_to_gregorian2((int)unmaskedVal); y = dtx.Year; m = dtx.Month; d = dtx.Day; } int sign = Math.Sign(y); y = Math.Abs(y); string sy = HasKnownYear() ? y.ToString().PadLeft(4, '0') : "????"; if (sign == -1) { sy = "-" + sy; } string sm = HasKnownMonth() ? m.ToString().PadLeft(2, '0') : "??"; string sd = HasKnownDay() ? d.ToString().PadLeft(2, '0') : "??"; string result = string.Format("{0}/{1}/{2}", sy, sm, sd); if (IsApproximateDate()) { result = "~" + result; } else if (IsDateBefore()) { result = "<" + result; } else if (IsDateAfter()) { result = ">" + result; } return(result); }
/// <summary> /// Calculates Julian day nubmer (JDN, https://en.wikipedia.org/wiki/Julian_day) using the specified date in /// the specified <paramref name="calendar"/>. /// Return value of this method ain't a usual JDN. See Returns section for more information. /// </summary> /// <param name="calendar">Source calendar. The <paramref name="year"/>, <paramref name="month"/> and /// <paramref name="day"/> are in this calendar.</param> /// <param name="year">Year number. Pass `UnknownYear` constant when year is unknown. /// This method DOES NOT check that `year` is inside a valid range. It's duty of a caller.</param> /// <param name="month">Month number. Pass `UnknownMonth` constant when month is unknown. /// This method DOES NOT check that `month` is inside a valid range. It's duty of a caller.</param> /// <param name="day">Day number. Pass `UnknownDay` constant when day is unknown. /// This method DOES NOT check that `day` is inside a valid range. It's duty of a caller.</param> /// <returns>Masked Julian day nubmer. See description of the <see cref="fValue"/> member for detailed /// information about masked JDN value. /// /// This method doesn't change the 27th and 28th bit ("date before" and "date after"). /// </returns> private static int CreateVal(UDNCalendarType calendar, int year, int month, int day) { int result = 0; /* * @ruslangaripov: * * The next conversation assume that `UnknownYear` member is 0. * * If all the `CalendarConverter::{calendar type}_to_jd` functions guarantee valid JDN for 0th year, we can * safely use the following code: * * int uYear = year; * * But if at least one of `CalendarConverter::{calendar type}_to_jd` functions fails on 0th year (read: * gives incorrect JDN) we HAVE TO use code like this: * * int uYear = (UnknownYear != year) ? year : 1; * * Here `1` is the first valid year for an algorithm that calculates JDN. I believe any such calculation * succeeds doing such calculation with 1st year. * * Wikipedia says that "For the year (Y) astronomical year numbering is used", and therefore I currently * stick with "0th year always valid for calculation JDN". And therefore, a * `CalendarConverter::{calendar type}_to_jd` succeeds with `UnknownYear`: * * int result = (int) (CalendarConverter::{calendar type}_to_jd(UnknownYear, uMonth, uDay)); * * `result` after the code from above is a valid JDN. */ int uYear = year; int uMonth = Math.Max(UnknownMonth + 1, month); int uDay = Math.Max(UnknownDay + 1, day); switch (calendar) { case UDNCalendarType.ctGregorian: result = CalendarConverter.gregorian_to_jd2(uYear, uMonth, uDay); // fixed break; case UDNCalendarType.ctJulian: result = CalendarConverter.julian_to_jd2(uYear, uMonth, uDay); // fixed break; case UDNCalendarType.ctHebrew: result = CalendarConverter.hebrew_to_jd3(uYear, uMonth, uDay); // fixed to the 3rd variant break; case UDNCalendarType.ctIslamic: result = CalendarConverter.islamic_to_jd3(uYear, uMonth, uDay); // fixed to the 3rd variant break; } if (UnknownYear == year) { result |= IgnoreYear; } if (UnknownMonth + 1 > month) { result |= IgnoreMonth; } if (UnknownDay + 1 > day) { result |= IgnoreDay; } return(result); }