// Ignore Spelling: Linq using System; namespace AsbCloudInfrastructure { public static class DateTimeExtensions { /// <summary> /// Приветсти к UTC из времени куста /// </summary> /// <param name="date"></param> /// <param name="remoteTimezoneOffsetHours"></param> /// <returns></returns> public static DateTimeOffset ToUtcDateTimeOffset(this DateTime date, double remoteTimezoneOffsetHours) { if (date == default) return new DateTimeOffset(); var dateUtc = date.Kind switch { DateTimeKind.Local => date.ToUniversalTime(), DateTimeKind.Unspecified => DateTime.SpecifyKind(date.AddHours(-remoteTimezoneOffsetHours), DateTimeKind.Utc), _ => date, }; return new DateTimeOffset(dateUtc); } /// <summary> /// Привести ко времени куста из utc /// </summary> /// <param name="date"></param> /// <param name="remoteTimezoneOffsetHours"></param> /// <returns></returns> public static DateTime ToRemoteDateTime(this DateTimeOffset date, double remoteTimezoneOffsetHours) { if (date == default) return new DateTime(0, DateTimeKind.Unspecified); var dateTz = date.ToOffset(TimeSpan.FromHours(remoteTimezoneOffsetHours)); return dateTz.DateTime; } /// <summary> /// Поиск индекса близкого к value значения в span. /// Элементы в span должны быть отсортированы по возрастанию по полю propertyGetter. /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="TProp"></typeparam> /// <param name="span"></param> /// <param name="propertyGetter">метод получения свойства из объекта класса T</param> /// <param name="value">искомое значение</param> /// <param name="maxIterations">максимальное кол-во итераций. Прим.: /// в span из 4000 записей достаточно 9-ти итераций /// 8_000 => 10 итераций; /// 16_000 => 11; /// ... /// 256_000 => 15; /// При недостаточном кол-ве итераций индекс может оказаться близко, но это будет не ближайшее значение /// </param> /// <returns></returns> public static int BinarySearch<T, TProp>(this Span<T> span, Func<T, TProp> propertyGetter, TProp value, int maxIterations = 16) where TProp : IComparable { if (span.Length < 2 || --maxIterations < 0) return 0; var indexOfMiddle = span.Length >> 1; var comparison = value.CompareTo(propertyGetter(span[indexOfMiddle])); if (comparison > 0) { var index = indexOfMiddle + 1 + BinarySearch(span[(indexOfMiddle + 1)..], propertyGetter, value, maxIterations); return index < span.Length ? index : span.Length - 1; } else if (comparison < 0) return BinarySearch(span[..(indexOfMiddle)], propertyGetter, value, maxIterations); else //if (comparison == 0) return indexOfMiddle; } } }