Noda Time:Period.Between 返回不正确的值
Noda Time: Period.Between returning incorrect value
我在使用 NodaTime 库时遇到了问题。我的目标:计算两个日期之间的 Year/Month/Date。所以,这是我的测试示例:
private static void Main()
{
var list = new List<Tuple<DateTime, DateTime>>
{
new Tuple<DateTime, DateTime>(new DateTime(1980, 1, 1), new DateTime(1983, 12, 31)),
new Tuple<DateTime, DateTime>(new DateTime(2009, 1, 1), new DateTime(2015, 01, 23))
};
var totalPeriod = Period.Zero;
foreach (var tuple in list)
{
var dateFrom = tuple.Item1;
var dateTo = tuple.Item2;
var ld1 = new LocalDate(dateFrom.Year, dateFrom.Month, dateFrom.Day);
var ld2 = new LocalDate(dateTo.Year, dateTo.Month, dateTo.Day);
var period = Period.Between(ld1, ld2, PeriodUnits.YearMonthDay);
totalPeriod += period;
}
Console.WriteLine("Years: {0}, Months: {1}, Days: {2}",
totalPeriod.Years,
totalPeriod.Months,
totalPeriod.Days);
Console.Read();
}
输出为:
年:9,月:11,天:52
这对我来说是错误的。例如,我想得到下一个输出(当然,输出取决于一个月的天数,假设我们这个月有 31 天):
年:10,月:0,天:21
所以,我希望天数四舍五入为年和月。我怎样才能得到这个?
答案:
使用 Matt 的回答,我创建了下一个解决方案:
foreach (var tuple in list)
{
var dateFrom = tuple.Item1;
var dateTo = tuple.Item2;
var period = Period.Between(LocalDateTime.FromDateTime(dateFrom).Date, LocalDateTime.FromDateTime(dateTo).Date, PeriodUnits.YearMonthDay);
totalPeriod += period;
}
// trying clarify the period
while(totalPeriod.Days >= 30)
{
totalPeriod = totalPeriod - Period.FromDays(30);
totalPeriod = totalPeriod + Period.FromMonths(1);
while (totalPeriod.Months >= 12)
{
totalPeriod = totalPeriod - Period.FromMonths(12);
totalPeriod = totalPeriod + Period.FromYears(1);
}
}
Richard 对 OP 的评论是正确的。问题是月份和年份本身并不是不同的数量。必须对 "count" 它们有一个参照系。您在执行 Period.Between
操作时拥有该参考,但在您尝试将句点相加时它丢失了。
如果您检查正在添加的期间,这是有道理的:
First: Years: 3, Months: 11, Days: 30
Second: Years: 6, Months: 0, Days: 22
Total: Years: 9, Months: 11, Days: 52
为了按照您的意愿四舍五入,将 22 天添加到 30 天将以某种方式必须知道所引用的月份。即使您保留了原始信息——您会使用哪一个?您很可能在一侧有 28 天的月份,在另一侧有 31 天的月份。
最好的办法是事后自己人为地对结果进行四舍五入,然后选择一个固定值(例如 30 天)来表示所有月份。
哦,一件小事(与您的问题无关)- 要从 DateTime
变为 LocalDate
,请尝试 LocalDateTime.FromDateTime(dt).Date
。 :)
我在使用 NodaTime 库时遇到了问题。我的目标:计算两个日期之间的 Year/Month/Date。所以,这是我的测试示例:
private static void Main()
{
var list = new List<Tuple<DateTime, DateTime>>
{
new Tuple<DateTime, DateTime>(new DateTime(1980, 1, 1), new DateTime(1983, 12, 31)),
new Tuple<DateTime, DateTime>(new DateTime(2009, 1, 1), new DateTime(2015, 01, 23))
};
var totalPeriod = Period.Zero;
foreach (var tuple in list)
{
var dateFrom = tuple.Item1;
var dateTo = tuple.Item2;
var ld1 = new LocalDate(dateFrom.Year, dateFrom.Month, dateFrom.Day);
var ld2 = new LocalDate(dateTo.Year, dateTo.Month, dateTo.Day);
var period = Period.Between(ld1, ld2, PeriodUnits.YearMonthDay);
totalPeriod += period;
}
Console.WriteLine("Years: {0}, Months: {1}, Days: {2}",
totalPeriod.Years,
totalPeriod.Months,
totalPeriod.Days);
Console.Read();
}
输出为: 年:9,月:11,天:52
这对我来说是错误的。例如,我想得到下一个输出(当然,输出取决于一个月的天数,假设我们这个月有 31 天): 年:10,月:0,天:21
所以,我希望天数四舍五入为年和月。我怎样才能得到这个?
答案: 使用 Matt 的回答,我创建了下一个解决方案:
foreach (var tuple in list)
{
var dateFrom = tuple.Item1;
var dateTo = tuple.Item2;
var period = Period.Between(LocalDateTime.FromDateTime(dateFrom).Date, LocalDateTime.FromDateTime(dateTo).Date, PeriodUnits.YearMonthDay);
totalPeriod += period;
}
// trying clarify the period
while(totalPeriod.Days >= 30)
{
totalPeriod = totalPeriod - Period.FromDays(30);
totalPeriod = totalPeriod + Period.FromMonths(1);
while (totalPeriod.Months >= 12)
{
totalPeriod = totalPeriod - Period.FromMonths(12);
totalPeriod = totalPeriod + Period.FromYears(1);
}
}
Richard 对 OP 的评论是正确的。问题是月份和年份本身并不是不同的数量。必须对 "count" 它们有一个参照系。您在执行 Period.Between
操作时拥有该参考,但在您尝试将句点相加时它丢失了。
如果您检查正在添加的期间,这是有道理的:
First: Years: 3, Months: 11, Days: 30
Second: Years: 6, Months: 0, Days: 22
Total: Years: 9, Months: 11, Days: 52
为了按照您的意愿四舍五入,将 22 天添加到 30 天将以某种方式必须知道所引用的月份。即使您保留了原始信息——您会使用哪一个?您很可能在一侧有 28 天的月份,在另一侧有 31 天的月份。
最好的办法是事后自己人为地对结果进行四舍五入,然后选择一个固定值(例如 30 天)来表示所有月份。
哦,一件小事(与您的问题无关)- 要从 DateTime
变为 LocalDate
,请尝试 LocalDateTime.FromDateTime(dt).Date
。 :)