使用 group by 时如何对 Linq 中两个日期时间之间的减法时间跨度求和?
How to sum Timespan of subtraction between two datetimes in Linq when using group by?
我的物品具有以下属性:
public int ClientId {get;set;}
public DateTime StartDateTime{get;set;}
public DateTime EndDateTime{get;set;}
我想用 group by 计算每个客户的所有日期时间之间的差异总和,但是这个:
var retVal = (from t items group t by ClientId into z
select new
{
ClientId = z.Key,
TimeSpanClientTotal = z.Sum(h => (h.EndDateTime - h.StartDateTime))
}).ToList();
不起作用,因为 Sum
不适用于 TimeSpan
,这是两个 DateTime
对象之间的差异的 return 值。
关于如何获得每个客户端的总时间跨度的任何建议?
谢谢
您可以使用.TotalMilliseconds 属性
var retVal = (from t items group t by ClientId into z
select new
{
ClientId = z.Key,
TimeSpanClientTotal = z.Sum(h => (h.EndDateTime - h.StartDateTime).TotalMilliseconds)
}).ToList();
你可以这样写:
h.EndDateTime.Subtract(h.StartDateTime).TotalDays();
Enumerable.Sum 只是您在 IEnumerable 上调用的扩展方法。它没有什么特别之处,因此您可以轻松创建另一种扩展方法来计算时间跨度:
static class TimeSpanExtensions
{
public static TimeSpan Sum<TSource>(this IEnumerable<TSource> enumerable,
Func<TSource,TimeSpan?> func )
{
return enumerable.Aggregate(TimeSpan.Zero, (total, it) =>
total+=(func(it)??TimeSpan.Zero);
}
}
假设您的 class 定义是
class Record
{
public int ClientId { get; set; }
public DateTime StartDateTime { get; set; }
public DateTime EndDateTime { get; set; }
public Record(int clientId, DateTime startDateTime, DateTime endDateTime)
{
ClientId = clientId;
StartDateTime = startDateTime;
EndDateTime = endDateTime;
}
}
您可以编写与数字类型相同的代码:
var items = new[] {
new Record(1, DateTime.Now, DateTime.Now.AddHours(1)),
new Record(1, DateTime.Now, DateTime.Now.AddHours(1)),
new Record(1, DateTime.Now, DateTime.Now.AddHours(1))};
var total=items.Sum(h=>(h.EndDateTime-h.StartDateTime));
var grouped= (from t in items
group t by t.ClientId into z
select new
{
ClientId = z.Key,
TimeSpanClientTotal = z.Sum(h => (h.EndDateTime - h.StartDateTime))
}).ToList();
也可以直接使用Enumerable.Aggregate:
var total= items.Aggregate(TimeSpan.Zero, (current, it) =>
current += (it.EndDateTime-it.StartDateTime));
代码可能更丑陋,但您可以做的不仅仅是简单的加法。
就我而言,所有建议的解决方案均无效。它们导致了与 LINQ 限制相关的错误。所以,我的解决方法是这样的:
var appointments = (from apps in DbContext.ClientAppointments
where apps.StartDate.Value.Date == date.Date
select new
{
SpecialistId = apps.SpecialistId,
Duration = (apps.EndDate.Value - apps.StartDate.Value).TotalSeconds
}).ToList();
var result = (from apps in appointments
group apps by apps.SpecialistId into g
select new AppointmentsDurationDailyDto
{
SpecialistId = g.Key ?? 0,
Date = date.Date,
Duration = g.Sum(apps => apps.Duration)
}).ToList();
在此解决方案中,首先 .ToList();
对在客户端上进行下一个分组语句很重要。如果您需要获得 TimeSpan Duration
,您可以使用 TimeSpan.FromSeconds(Duration)
轻松将其转换回来
我的物品具有以下属性:
public int ClientId {get;set;}
public DateTime StartDateTime{get;set;}
public DateTime EndDateTime{get;set;}
我想用 group by 计算每个客户的所有日期时间之间的差异总和,但是这个:
var retVal = (from t items group t by ClientId into z
select new
{
ClientId = z.Key,
TimeSpanClientTotal = z.Sum(h => (h.EndDateTime - h.StartDateTime))
}).ToList();
不起作用,因为 Sum
不适用于 TimeSpan
,这是两个 DateTime
对象之间的差异的 return 值。
关于如何获得每个客户端的总时间跨度的任何建议?
谢谢
您可以使用.TotalMilliseconds 属性
var retVal = (from t items group t by ClientId into z
select new
{
ClientId = z.Key,
TimeSpanClientTotal = z.Sum(h => (h.EndDateTime - h.StartDateTime).TotalMilliseconds)
}).ToList();
你可以这样写:
h.EndDateTime.Subtract(h.StartDateTime).TotalDays();
Enumerable.Sum 只是您在 IEnumerable 上调用的扩展方法。它没有什么特别之处,因此您可以轻松创建另一种扩展方法来计算时间跨度:
static class TimeSpanExtensions
{
public static TimeSpan Sum<TSource>(this IEnumerable<TSource> enumerable,
Func<TSource,TimeSpan?> func )
{
return enumerable.Aggregate(TimeSpan.Zero, (total, it) =>
total+=(func(it)??TimeSpan.Zero);
}
}
假设您的 class 定义是
class Record
{
public int ClientId { get; set; }
public DateTime StartDateTime { get; set; }
public DateTime EndDateTime { get; set; }
public Record(int clientId, DateTime startDateTime, DateTime endDateTime)
{
ClientId = clientId;
StartDateTime = startDateTime;
EndDateTime = endDateTime;
}
}
您可以编写与数字类型相同的代码:
var items = new[] {
new Record(1, DateTime.Now, DateTime.Now.AddHours(1)),
new Record(1, DateTime.Now, DateTime.Now.AddHours(1)),
new Record(1, DateTime.Now, DateTime.Now.AddHours(1))};
var total=items.Sum(h=>(h.EndDateTime-h.StartDateTime));
var grouped= (from t in items
group t by t.ClientId into z
select new
{
ClientId = z.Key,
TimeSpanClientTotal = z.Sum(h => (h.EndDateTime - h.StartDateTime))
}).ToList();
也可以直接使用Enumerable.Aggregate:
var total= items.Aggregate(TimeSpan.Zero, (current, it) =>
current += (it.EndDateTime-it.StartDateTime));
代码可能更丑陋,但您可以做的不仅仅是简单的加法。
就我而言,所有建议的解决方案均无效。它们导致了与 LINQ 限制相关的错误。所以,我的解决方法是这样的:
var appointments = (from apps in DbContext.ClientAppointments
where apps.StartDate.Value.Date == date.Date
select new
{
SpecialistId = apps.SpecialistId,
Duration = (apps.EndDate.Value - apps.StartDate.Value).TotalSeconds
}).ToList();
var result = (from apps in appointments
group apps by apps.SpecialistId into g
select new AppointmentsDurationDailyDto
{
SpecialistId = g.Key ?? 0,
Date = date.Date,
Duration = g.Sum(apps => apps.Duration)
}).ToList();
在此解决方案中,首先 .ToList();
对在客户端上进行下一个分组语句很重要。如果您需要获得 TimeSpan Duration
,您可以使用 TimeSpan.FromSeconds(Duration)