【发布时间】:2013-07-25 08:59:46
【问题描述】:
我有一份清单
*startTime (datetime)
*endTime (datetime)
并且需要计算出列表中所有内容的平均时间。
所以我猜我需要类似的东西
long averageTime =
Convert.ToInt64(listOfStartEndTimes.Average(timeSpan => timeSpan.Ticks))
有什么想法吗?
【问题讨论】:
我有一份清单
*startTime (datetime)
*endTime (datetime)
并且需要计算出列表中所有内容的平均时间。
所以我猜我需要类似的东西
long averageTime =
Convert.ToInt64(listOfStartEndTimes.Average(timeSpan => timeSpan.Ticks))
有什么想法吗?
【问题讨论】:
long averageTime = listOfStartEndTimes
.Select(se => se.End - se.Start)
.Average(t => t.Ticks);
或者,分辨率稍低(unix 纪元日期):
long averageTime = listOfStartEndTimes
.Select(se => se.End - se.Start)
.Average(t => (t.Ticks – 621355968000000000) / 10000000);
【讨论】:
var secsSinceMidnight = (DateTime.Now - DateTime.Today).TotalSeconds;
其他答案是正确的,您可以使用简单的 LINQ 平均 TimeSpan 属性。我更喜欢让 TimeSpan 类来确定精度,例如 Uffe 所示。但请确保您使用的是正确的属性。 .Seconds 将返回不到一分钟的秒数余数。你想要.TotalSeconds 属性。
使用.Ticks 可能很诱人,但如果您有很多值并且它们之间的距离足够远,您可以轻松获得OverflowException。我的建议是在结果中使用比您需要的小一个单位。因此,如果您关心精确到分钟的平均精度,那么.TotalSeconds 应该可以正常工作。然后,您可以根据需要将结果返回到TimeSpan。
var sec = yourList.Select(p => p.Stop - p.Start).Average(p => p.TotalSeconds);
var avg = TimeSpan.FromSeconds(sec);
另外,由于您的Start 和Stop 值的类型为DateTime,那么您真的需要注意它们的.Kind。只有在yourDateTime.Kind == DateTimeKind.Utc 时才能保证这样的操作是准确的。
如果它们是Local种,那么结果将受到运行代码的本地计算机的时区的影响。如果它们是Unspecified,则数据可能已记录在本地时区或其他时区的上下文中。如果您工作的时间包含夏令时转换,那么您的减法结果可能不正确。
例如,如果您在美国太平洋时区运行此代码,并且您有 Local 种类的 DateTime,那么减去 2013-11-03 06:00 - 2013-11-03 00:00 将得到 6 小时的 TimeSpan .但实际上,7 个小时已经过去,因为那是 DST 结束的那一天,时钟在 1:00 和 2:00 之间重复这个小时。
为避免此问题,您应该只使用 Utc 中的 DateTime 值进行数学运算,或者您应该改用 DateTimeOffset 值。
【讨论】:
如果你有课
public class Time
{
public DateTime Start;
public DateTime Stop;
public Time(DateTime start, DateTime stop)
{
this.Start = start;
this.Stop = stop;
}
}
如果您填写日期时间值,您可能会得到平均值...
var avg = Times.Select(p => p.Stop - p.Start).Average(p => p.Seconds);
您可以在其中将 p.Seconds 替换为您想要的任何内容.. 小时、分钟等... 注意:未经测试,但我认为它可能有效
编辑:啊,已经回答了:)
【讨论】:
.TotalSeconds,而不是.Seconds。