/// <summary> /// Calculates the current date /// This will work also when a year cannot be divided in days without a remainder /// Every year will end at the last full day of the year. /// The time difference carries over from year to year, untill it's enough to get another full day. /// Example: if a year is 365.25 days, the first three years will have 365 days and 0.25 will carry over. /// On the fourth year there will be enough time carried over, so it will have 366 days. /// </summary> /// <param name="time"></param> /// <returns></returns> public virtual Date GetLeapDate(double time) { // Time in a short (non-leap) year double shortYear = loader.Clock.year.value - (loader.Clock.year.value % loader.Clock.day.value); // Chance of getting a leap day in a year double chanceOfLeapDay = (loader.Clock.year.value % loader.Clock.day.value) / loader.Clock.day.value; // Number of days in a short (non-leap) year int daysInOneShortYear = (int)(shortYear / loader.Clock.day.value); // Current Year (calculated as if there were no leap years) int year = (int)(time / shortYear); // Time left this year (calculated as if there were no leap years) double timeFromPreviousYears = year * shortYear; double timeLeftThisYear = time - timeFromPreviousYears; // Current Day of the Year (calculated as if there were no leap years) int day = (int)Math.Floor(timeLeftThisYear / loader.Clock.day.value); // Remove the days lost to leap years day -= (int)Math.Floor(chanceOfLeapDay * year); // If days go negative, borrow days from the previous year while (day < 0) { year--; day += daysInOneShortYear + 1; } // Now 'day' and 'year' correctly account for leap years // Time left to count double left = MOD(time, loader.Clock.day.value); // Number of hours in this day int hours = (int)(left / loader.Clock.hour.value); // Time left to count left = left - hours * loader.Clock.hour.value; // Number of minutes in this hour int minutes = (int)(left / loader.Clock.minute.value); // Time left to count left = left - minutes * loader.Clock.minute.value; // Number of seconds in this minute int seconds = (int)(left / loader.Clock.second.value); // DATE CALCULATION COMPLETE // Temporary Month (needed later) Month month = null; // If there are months, change 'day' to indicate the current 'day of the month' if (loader.calendar.Count > 0) { // Calculate the time passed from the last month reset // Note: months reset every N years (Kronometer.resetMonths) // Total days passed untill now int daysPassedTOT = (int)Math.Floor(time / loader.Clock.day.value); // Days between month resets = normal days between month resets + leap days between month resets int daysBetweenResets = (daysInOneShortYear * loader.resetMonths) + (int)(chanceOfLeapDay * loader.resetMonths); // Days passed since last month reset int daysFromReset = (int)MOD(daysPassedTOT, daysBetweenResets); // Go through each month in the calendar for (int i = 0; i < loader?.calendar?.Count; i++) { Month Mo = loader.calendar[i]; month = Mo; // If there are more days left than there are in this month // AND // this is not the last month of the calendar if (daysFromReset >= Mo.days && Mo != loader.calendar[loader.calendar.Count - 1]) { // Remove this month worth of days and move on to check next month daysFromReset -= Mo.days; } else { break; } // If we run out of months, the last month will last until the next reset } // Set 'day' as 'day of the month' day = daysFromReset; } // The final date return(new Date(year, month, day, hours, minutes, seconds)); }
/// <summary> /// Calculates the current date /// This will work also when a year cannot be divided in days without a remainder /// Every year will end at the last full day of the year. /// The time difference carries over from year to year, untill it's enough to get another full day. /// Example: if a year is 365.25 days, the first three years will have 365 days and 0.25 will carry over. /// On the fourth year there will be enough time carried over, so it will have 366 days. /// </summary> /// <param name="time"></param> /// <returns></returns> public virtual Date GetLeapDate(double time) { // Number of days in a short (non-leap) year int daysInOneShortYear = SmartFloor(loader.Clock.year.value / loader.Clock.day.value); int daysInOneLongYear = (int)Math.Ceiling(loader.Clock.year.value / loader.Clock.day.value); // Time in a short (non-leap) year double shortYear = loader.Clock.day.value * daysInOneShortYear; // Chance of getting a leap day in a year double chanceOfLeapDay = (loader.Clock.year.value / loader.Clock.day.value) % 1; if (daysInOneShortYear == daysInOneLongYear) { chanceOfLeapDay = 0; } // Time left to count double left = time; double leap = 0; int year = 0; int day = 0; int hours = 0; int minutes = 0; int seconds = 0; while (left >= shortYear) { left -= shortYear; leap += chanceOfLeapDay; year += 1; while (SmartFloor(leap) >= 1) { leap = Math.Max(leap - 1, 0); if (!(left < loader.Clock.day.value)) { left -= loader.Clock.day.value; } else { year -= 1; day += daysInOneShortYear; } } } day += (int)(left / loader.Clock.day.value); left -= (int)(left / loader.Clock.day.value) * loader.Clock.day.value; if (left >= loader.Clock.day.value) { day += 1; left -= loader.Clock.day.value; } hours = (int)(left / 3600); left -= hours * 3600; minutes = (int)(left / 60); left -= minutes * 60; seconds = (int)left; // DATE CALCULATION COMPLETE // Temporary Month (needed later) Month month = null; int dayOfMonth = 0; // If there are months, change 'dayOfMonth' to indicate the current 'day of the month' if (loader.calendar.Count > 0) { // Calculate the time passed from the last month reset // Note: months reset every N years (Kronometer.resetMonths) // Total days passed untill now int daysPassedTOT = (int)Math.Floor(time / loader.Clock.day.value); // Days between month resets = normal days between month resets + leap days between month resets int daysBetweenResets = (daysInOneShortYear * loader.resetMonths) + (int)(chanceOfLeapDay * loader.resetMonths); // Days passed since last month reset int daysFromReset = (int)MOD(daysPassedTOT, daysBetweenResets); // Go through each month in the calendar for (int i = 0; i < loader?.calendar?.Count; i++) { Month Mo = loader.calendar[i]; month = Mo; // If there are more days left than there are in this month // AND // this is not the last month of the calendar if (daysFromReset >= Mo.days && Mo != loader.calendar[loader.calendar.Count - 1]) { // Remove this month worth of days and move on to check next month daysFromReset -= Mo.days; } else { break; } // If we run out of months, the last month will last until the next reset } // Set 'dayOfMonth' as 'day of the month' dayOfMonth = daysFromReset; } // The final date return(new Date(year, month, dayOfMonth, day, hours, minutes, seconds)); }