/// <summary> /// Computes the cache entry value for the given year, but without populating the cache. /// </summary> private static int ComputeCacheEntry(int year) { int days = ElapsedDaysNoCache(year); // We want the elapsed days for the next year as well. Check the cache if possible. int nextYear = year + 1; int nextYearDays; if (nextYear <= MaxYear) { int cacheIndex = YearStartCacheEntry.GetCacheIndex(nextYear); YearStartCacheEntry cacheEntry = YearCache[cacheIndex]; nextYearDays = cacheEntry.IsValidForYear(nextYear) ? cacheEntry.StartOfYearDays & ElapsedDaysCacheMask : ElapsedDaysNoCache(nextYear); } else { nextYearDays = ElapsedDaysNoCache(year + 1); } int daysInYear = nextYearDays - days; bool isHeshvanLong = daysInYear % 10 == 5; bool isKislevShort = daysInYear % 10 == 3; return(days | (isHeshvanLong ? IsHeshvanLongCacheBit : 0) | (isKislevShort ? IsKislevShortCacheBit : 0)); }
/// <summary> /// Fetches the start of the year (in days since 1970-01-01 ISO) from the cache, or calculates /// and caches it. /// </summary> /// <param name="year">The year to fetch the days at the start of. This must be within 1 year of the min/max /// range, but can exceed it to make week-year calculations simple.</param> internal virtual int GetStartOfYearInDays([Trusted] int year) { Preconditions.DebugCheckArgumentRange(nameof(year), year, MinYear - 1, MaxYear + 1); int cacheIndex = YearStartCacheEntry.GetCacheIndex(year); YearStartCacheEntry cacheEntry = yearCache[cacheIndex]; if (!cacheEntry.IsValidForYear(year)) { int days = CalculateStartOfYearDays(year); cacheEntry = new YearStartCacheEntry(year, days); yearCache[cacheIndex] = cacheEntry; } return(cacheEntry.StartOfYearDays); }
/// <summary> /// Fetches the start of the year (in days since 1970-01-01 ISO) from the cache, or calculates /// and caches it. /// </summary> protected int GetStartOfYearInDays(int year) { if (year < MinYear || year > MaxYear) { return(CalculateStartOfYearDays(year)); } int cacheIndex = YearStartCacheEntry.GetCacheIndex(year); YearStartCacheEntry cacheEntry = yearCache[cacheIndex]; if (!cacheEntry.IsValidForYear(year)) { int days = CalculateStartOfYearDays(year); cacheEntry = new YearStartCacheEntry(year, days); yearCache[cacheIndex] = cacheEntry; } return(cacheEntry.StartOfYearDays); }
/// <summary> /// Returns the cached "elapsed day at start of year / IsHeshvanLong / IsKislevShort" combination, /// populating the cache if necessary. Bits 0-22 are the "elapsed days start of year"; bit 23 is /// "is Heshvan long"; bit 24 is "is Kislev short". If the year is out of the range for the cache, /// the value is populated but not cached. /// </summary> /// <param name="year"></param> private static int GetOrPopulateCache(int year) { if (year < MinYear || year > MaxYear) { return(ComputeCacheEntry(year)); } int cacheIndex = YearStartCacheEntry.GetCacheIndex(year); YearStartCacheEntry cacheEntry = YearCache[cacheIndex]; if (!cacheEntry.IsValidForYear(year)) { int days = ComputeCacheEntry(year); cacheEntry = new YearStartCacheEntry(year, days); YearCache[cacheIndex] = cacheEntry; } return(cacheEntry.StartOfYearDays); }
/// <summary> /// Fetches the start of the year (in days since 1970-01-01 ISO) from the cache, or calculates /// and caches it. /// </summary> /// <param name="year">The year to fetch the days at the start of. This must be within 1 year of the min/max /// range, but can exceed it to make week-year calculations simple.</param> internal virtual int GetStartOfYearInDays([Trusted] int year) { Preconditions.DebugCheckArgumentRange(nameof(year), year, MinYear - 1, MaxYear + 1); // TODO(2.0): Check that it's valid to cache values outside the advertised // bounds of the calendar (by one year). We used not to cache them, but just // the check was relatively expensive. int cacheIndex = YearStartCacheEntry.GetCacheIndex(year); YearStartCacheEntry cacheEntry = yearCache[cacheIndex]; if (!cacheEntry.IsValidForYear(year)) { int days = CalculateStartOfYearDays(year); cacheEntry = new YearStartCacheEntry(year, days); yearCache[cacheIndex] = cacheEntry; } return(cacheEntry.StartOfYearDays); }
/// <summary> /// Returns the cached "elapsed day at start of year / IsHeshvanLong / IsKislevShort" combination, /// populating the cache if necessary. Bits 0-22 are the "elapsed days start of year"; bit 23 is /// "is Heshvan long"; bit 24 is "is Kislev short". If the year is out of the range for the cache, /// the value is populated but not cached. /// </summary> /// <param name="year"></param> private static int GetOrPopulateCache(int year) { if (year < MinYear || year > MaxYear) { return ComputeCacheEntry(year); } int cacheIndex = YearStartCacheEntry.GetCacheIndex(year); YearStartCacheEntry cacheEntry = YearCache[cacheIndex]; if (!cacheEntry.IsValidForYear(year)) { int days = ComputeCacheEntry(year); cacheEntry = new YearStartCacheEntry(year, days); YearCache[cacheIndex] = cacheEntry; } return cacheEntry.StartOfYearDays; }