feat(api): статистика отображается в часовом поясе клиента
This commit is contained in:
96
PARR.API/Helpers/TimeZoneDateHelper.cs
Normal file
96
PARR.API/Helpers/TimeZoneDateHelper.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace PARR.API.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Хелпер для работы с датами в разных часовых поясах (UTC - пользователь). Используется для формирования СТАТИСТИКИ
|
||||
/// </summary>
|
||||
public static class TimeZoneDateHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Создаёт начало дня (00:00:00) в часовом поясе пользователя и конвертирует в UTC
|
||||
/// </summary>
|
||||
/// <param name="userDate"></param>
|
||||
/// <param name="userOffset"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetUtcSartOfDay(DateOnly userDate, TimeSpan userOffset)
|
||||
{
|
||||
var userStart = new DateTimeOffset(userDate.Year, userDate.Month, userDate.Day,
|
||||
0, 0, 0,
|
||||
userOffset);
|
||||
|
||||
return userStart.UtcDateTime;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Создаёт полуоткрытый интервал [start; end) в UTC для фильтрации за период (end не включается)
|
||||
/// </summary>
|
||||
/// <param name="userStartDate"></param>
|
||||
/// <param name="userEndDateExclusive"></param>
|
||||
/// <param name="userOffset"></param>
|
||||
/// <returns></returns>
|
||||
public static (DateTime StartUtc, DateTime EndUtc) GetUtcDateRange(DateOnly userStartDate, DateOnly userEndDateExclusive, TimeSpan userOffset)
|
||||
{
|
||||
var start = new DateTimeOffset(
|
||||
userStartDate.Year, userStartDate.Month, userStartDate.Day,
|
||||
0, 0, 0, userOffset).UtcDateTime;
|
||||
|
||||
var end = new DateTimeOffset(
|
||||
userEndDateExclusive.Year, userEndDateExclusive.Month, userEndDateExclusive.Day,
|
||||
0, 0, 0, userOffset).UtcDateTime;
|
||||
|
||||
return (start, end);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Применяет фильтр по дате к IQueryable
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="dateSelector"></param>
|
||||
/// <param name="startUtc"></param>
|
||||
/// <param name="endUtc"></param>
|
||||
/// <returns></returns>
|
||||
public static IQueryable<T> FilterByDateRangeUtc<T>(this IQueryable<T> query, Expression<Func<T, DateTimeOffset>> dateSelector, DateTime startUtc, DateTime endUtc)
|
||||
{
|
||||
// Строим выражение: t => t.DateCreated.UtcDateTime >= start && < end
|
||||
var param = dateSelector.Parameters[0];
|
||||
var body = Expression.AndAlso(
|
||||
// Строим левую часть: t.DateCreated.UtcDateTime >= startUtc
|
||||
Expression.GreaterThanOrEqual(
|
||||
Expression.Property(dateSelector.Body, nameof(DateTimeOffset.UtcDateTime)),
|
||||
Expression.Constant(startUtc, typeof(DateTime))
|
||||
),
|
||||
// Строим правую часть: t.DateCreated.UtcDateTime < endUtc
|
||||
Expression.LessThan(
|
||||
Expression.Property(dateSelector.Body, nameof(DateTimeOffset.UtcDateTime)),
|
||||
Expression.Constant(endUtc, typeof(DateTime))
|
||||
)
|
||||
);
|
||||
|
||||
// Собираем финальную лямбду: t => (t.DateCreated.UtcDateTime >= start && < end)
|
||||
var lambda = Expression.Lambda<Func<T, bool>>(body, param);
|
||||
|
||||
// Применяем к запросу
|
||||
return query.Where(lambda);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Группирует записи по дате в часовом поясе пользователя (для загруженных записей)
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="dateSelector"></param>
|
||||
/// <param name="userOffset"></param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<DateOnly, int> GroupByUserDate<T>(this IEnumerable<T> source, Func<T, DateTimeOffset> dateSelector, TimeSpan userOffset)
|
||||
{
|
||||
return source.GroupBy(t => DateOnly.FromDateTime(dateSelector(t).ToOffset(userOffset).DateTime))
|
||||
.ToDictionary(g => g.Key, g => g.Count());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user