Din*_*nah 121 .net c# datetime timespan
在C#/.NET TimeSpan
有TotalDays
,TotalMinutes
等等,但我无法弄清楚总月差的公式.每月可变天数和闰年一直让我失望.我如何获得TotalMonths?
编辑抱歉没有更清楚:我知道我实际上无法得到这个,TimeSpan
但我想使用TotalDays
,TotalMinutes
并将是一个很好的例子来表达我正在寻找...除了我想要得到总月.
示例:2009年12月25日 - 2009年10月6日= 2 TotalMonths.10月6日至11月5日等于0个月.11月6日,1个月.12月6日,2个月
Ada*_*son 216
你将无法从a获得TimeSpan
,因为"月"是一个可变的度量单位.你必须自己计算它,你必须弄清楚你希望它是如何工作的.
例如,要日期喜欢July 5, 2009
并August 4, 2009
产生一个月或零月区别?如果你说这应该产生一个,然后怎么样July 31, 2009
和August 1, 2009
?是那一个月?它只是Month
日期值的差异,还是与实际的时间跨度更相关?确定所有这些规则的逻辑非常重要,因此您必须确定自己的规则并实施适当的算法.
如果您只想要几个月的差异 - 完全忽略日期值 - 那么您可以使用:
public static int MonthDifference(this DateTime lValue, DateTime rValue)
{
return (lValue.Month - rValue.Month) + 12 * (lValue.Year - rValue.Year);
}
Run Code Online (Sandbox Code Playgroud)
请注意,这会返回相对差异,这意味着如果rValue
大于lValue
,则返回值将为负数.如果你想要一个绝对差异,你可以使用这个:
public static int MonthDifference(this DateTime lValue, DateTime rValue)
{
return Math.Abs((lValue.Month - rValue.Month) + 12 * (lValue.Year - rValue.Year));
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 51
(我意识到这是一个老问题,但......)
在纯.NET中这是相对痛苦的.我推荐自己的Noda Time库,它专门用于这样的事情:
LocalDate start = new LocalDate(2009, 10, 6);
LocalDate end = new LocalDate(2009, 12, 25);
Period period = Period.Between(start, end);
int months = period.Months;
Run Code Online (Sandbox Code Playgroud)
(还有其他选择,例如,如果您只需要数月甚至数年,您可以使用Period period = Period.Between(start, end, PeriodUnits.Months);
)
Rub*_*ias 28
也许你不想知道月份; 这段代码怎么样?
public static class DateTimeExtensions
{
public static int TotalMonths(this DateTime start, DateTime end)
{
return (start.Year * 12 + start.Month) - (end.Year * 12 + end.Month);
}
}
// Console.WriteLine(
// DateTime.Now.TotalMonths(
// DateTime.Now.AddMonths(-1))); // prints "1"
您必须先定义TotalMonths的含义.
一个简单的定义是将月份定为30.4天(365.25/12).
除此之外,任何包含分数的定义似乎都是无用的,更常见的整数值(日期之间的整月)也取决于非标准业务规则.
你需要在日期之前自己解决这个问题.如何处理最后的存根天数将取决于您想要使用它的目的.
一种方法是计算月份,然后在结束时校正数天.就像是:
DateTime start = new DateTime(2003, 12, 25);
DateTime end = new DateTime(2009, 10, 6);
int compMonth = (end.Month + end.Year * 12) - (start.Month + start.Year * 12);
double daysInEndMonth = (end - end.AddMonths(1)).Days;
double months = compMonth + (start.Day - end.Day) / daysInEndMonth;
Run Code Online (Sandbox Code Playgroud)
我已经编写了一个非常简单的扩展方法DateTime
并DateTimeOffset
执行此操作.我希望它的工作方式与工作中的TotalMonths
属性完全相同TimeSpan
:即返回两个日期之间完整月份的计数,忽略任何部分月份.因为它基于DateTime.AddMonths()
它,它尊重不同的月份长度,并返回人类在几个月的时间段内理解的东西.
(遗憾的是,您无法将其作为TimeSpan上的扩展方法实现,因为它不会保留所使用的实际日期的知识,并且几个月它们很重要.)
代码和测试都可以在GitHub上找到.代码很简单:
public static int GetTotalMonthsFrom(this DateTime dt1, DateTime dt2)
{
DateTime earlyDate = (dt1 > dt2) ? dt2.Date : dt1.Date;
DateTime lateDate = (dt1 > dt2) ? dt1.Date : dt2.Date;
// Start with 1 month's difference and keep incrementing
// until we overshoot the late date
int monthsDiff = 1;
while (earlyDate.AddMonths(monthsDiff) <= lateDate)
{
monthsDiff++;
}
return monthsDiff - 1;
}
Run Code Online (Sandbox Code Playgroud)
它通过了所有这些单元测试用例:
// Simple comparison
Assert.AreEqual(1, new DateTime(2014, 1, 1).GetTotalMonthsFrom(new DateTime(2014, 2, 1)));
// Just under 1 month's diff
Assert.AreEqual(0, new DateTime(2014, 1, 1).GetTotalMonthsFrom(new DateTime(2014, 1, 31)));
// Just over 1 month's diff
Assert.AreEqual(1, new DateTime(2014, 1, 1).GetTotalMonthsFrom(new DateTime(2014, 2, 2)));
// 31 Jan to 28 Feb
Assert.AreEqual(1, new DateTime(2014, 1, 31).GetTotalMonthsFrom(new DateTime(2014, 2, 28)));
// Leap year 29 Feb to 29 Mar
Assert.AreEqual(1, new DateTime(2012, 2, 29).GetTotalMonthsFrom(new DateTime(2012, 3, 29)));
// Whole year minus a day
Assert.AreEqual(11, new DateTime(2012, 1, 1).GetTotalMonthsFrom(new DateTime(2012, 12, 31)));
// Whole year
Assert.AreEqual(12, new DateTime(2012, 1, 1).GetTotalMonthsFrom(new DateTime(2013, 1, 1)));
// 29 Feb (leap) to 28 Feb (non-leap)
Assert.AreEqual(12, new DateTime(2012, 2, 29).GetTotalMonthsFrom(new DateTime(2013, 2, 28)));
// 100 years
Assert.AreEqual(1200, new DateTime(2000, 1, 1).GetTotalMonthsFrom(new DateTime(2100, 1, 1)));
// Same date
Assert.AreEqual(0, new DateTime(2014, 8, 5).GetTotalMonthsFrom(new DateTime(2014, 8, 5)));
// Past date
Assert.AreEqual(6, new DateTime(2012, 1, 1).GetTotalMonthsFrom(new DateTime(2011, 6, 10)));
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
133119 次 |
最近记录: |