C# 时间跨度年和月(十进制c)
我有两个十进制值 我试图将这些值相加,结果是5.9,这是不正确的 预期的结果应该是C# 时间跨度年和月(十进制c),c#,datetime,timestamp,C#,Datetime,Timestamp,我有两个十进制值 我试图将这些值相加,结果是5.9,这是不正确的 预期的结果应该是 6.6m = 6 years 6 months 任何人都可以建议我们如何使用TimeSpan或C中的任何其他方法来实现这一点。首先,我要避免使用那样的小数来表示年/月值。如评论中所述,您将无法轻松区分1个月和10个月。。。虽然十进制可以表示3.1和3.10之间的差异,但这将是一个非常奇怪的用法。只需将这两个值保持在单独的整数中 接下来,你不能用TimeSpan做这样的算术。TimeSpan只存储一定数量的滴答声
6.6m = 6 years 6 months
任何人都可以建议我们如何使用TimeSpan或C中的任何其他方法来实现这一点。首先,我要避免使用那样的小数来表示年/月值。如评论中所述,您将无法轻松区分1个月和10个月。。。虽然十进制可以表示3.1和3.10之间的差异,但这将是一个非常奇怪的用法。只需将这两个值保持在单独的整数中 接下来,你不能用TimeSpan做这样的算术。TimeSpan只存储一定数量的滴答声——它不会处理像1个月或1年这样的想法,因为这些并不代表固定数量的滴答声 我建议改用我的图书馆。您可以将这些值表示为周期对象。您仍然无法直接将年和月相加-周期不采用公历系统,这样的算法对某些非公历日历不起作用,尤其是那些根据年份改变月数的日历。但是,您可以轻松编写自己的周期规范化方法:
using System;
using NodaTime;
class Test
{
static void Main()
{
Period p1 = new PeriodBuilder { Years = 3, Months = 10 }.Build();
Period p2 = new PeriodBuilder { Years = 5, Months = -12 }.Build();
Period sum = p1 + p2;
Period normalized = NormalizeYearsAndMonths(sum);
Console.WriteLine($"{normalized.Years} years; {normalized.Months} months");
}
static Period NormalizeYearsAndMonths(Period period)
{
// TODO: Handle negative years and months however you want.
int years = period.Years;
int months = period.Months;
years += months / 12;
months = months % 12;
var builder = period.ToBuilder();
builder.Years = years;
builder.Months = months;
return builder.Build();
}
}
当然,你可以把所有的东西都保留在两个整数中——使用句点的好处是,你可以很容易地将它添加到LocalDate或LocalDateTime等中。如果你愿意的话,你甚至可以一开始就不进行规范化。首先,我要避免使用像那样的小数来表示年/月值。如评论中所述,您将无法轻松区分1个月和10个月。。。虽然十进制可以表示3.1和3.10之间的差异,但这将是一个非常奇怪的用法。只需将这两个值保持在单独的整数中 接下来,你不能用TimeSpan做这样的算术。TimeSpan只存储一定数量的滴答声——它不会处理像1个月或1年这样的想法,因为这些并不代表固定数量的滴答声 我建议改用我的图书馆。您可以将这些值表示为周期对象。您仍然无法直接将年和月相加-周期不采用公历系统,这样的算法对某些非公历日历不起作用,尤其是那些根据年份改变月数的日历。但是,您可以轻松编写自己的周期规范化方法:
using System;
using NodaTime;
class Test
{
static void Main()
{
Period p1 = new PeriodBuilder { Years = 3, Months = 10 }.Build();
Period p2 = new PeriodBuilder { Years = 5, Months = -12 }.Build();
Period sum = p1 + p2;
Period normalized = NormalizeYearsAndMonths(sum);
Console.WriteLine($"{normalized.Years} years; {normalized.Months} months");
}
static Period NormalizeYearsAndMonths(Period period)
{
// TODO: Handle negative years and months however you want.
int years = period.Years;
int months = period.Months;
years += months / 12;
months = months % 12;
var builder = period.ToBuilder();
builder.Years = years;
builder.Months = months;
return builder.Build();
}
}
现在,您当然可以将所有内容保留为两个整数-使用句点的好处是,您可以轻松地将其添加到LocalDate或LocalDateTime等中。如果您愿意,您甚至可以在不进行规范化的情况下开始操作。不要这样做!小数不代表年。月。从技术上讲,你可以解决这个问题,并区分3.1m和3.10m十进制;以下代码仅供学术使用:
演示:
我希望,我吓坏了你,使你不再使用十进制。作为一个快速而肮脏的补丁,如果您不能使用标准库以外的任何库,您可以尝试DateTime类:
不要这样做!小数不代表年。月。从技术上讲,你可以解决这个问题,并区分3.1m和3.10m十进制;以下代码仅供学术使用:
演示:
我希望,我吓坏了你,使你不再使用十进制。作为一个快速而肮脏的补丁,如果您不能使用标准库以外的任何库,您可以尝试DateTime类:
为什么要对DateTime使用十进制响应?如何区分3.1 3年1个月和3.10 3年10个月?我认为3.10=3年10个月的标识是错误的。根据这一逻辑,3.12将是3年12个月或4年。我们如何使用TimeSpan或C中的任何其他方法来实现这一点?使用TimeSpan,您只需执行TimeSpan total=span1+span2;其中span1和span2也是TimeSpan类型。@马修·沃森:是的,你说得很对:在2018年1月30日之前加上一个月是个问题,是2018年2月28日吗?如果我们减去1个月的时间呢?;但是,通常情况下,业务请求应在一个月内发出。为什么要对DateTime使用十进制响应?如何区分3.1 3年1个月和3.10 3年10个月?标识3.10=3年10个月在我看来是错误的。根据时间跨度4.3年或12年的逻辑,我们将如何实现?使用TimeSpan,您只需执行TimeSpan total=span1+span2;其中span1和span2也是TimeSpan类型。@马修·沃森:是的,你说得很对:在2018年1月30日之前加上一个月是个问题,是2018年2月28日吗?如果我们减去1个月的时间呢?;然而,通常情况下,业务请求应该在一个月内发出,等等。
private static decimal EerieArithmetics(decimal d1, decimal d2) {
int y1 = (int)d1;
int m1 = (int)((d1 % 1m) * ((((decimal.GetBits(d1)[3] >> 16) & 31) == 2) ? 100m : 10m));
int y2 = (int)d2;
int m2 = (int)((d2 % 1m) * ((((decimal.GetBits(d2)[3] >> 16) & 31) == 2) ? 100m : 10m));
int y = y1 + y2 + (m1 + m2) / 12;
int m = (m1 + m2) % 12;
return y + (m == 10 ? 0.10m : m > 10 ? m / 100.00m : m / 10.0m);
}
Tuple<decimal, decimal>[] tests = new Tuple<decimal, decimal>[] {
Tuple.Create(3.10m, 2.8m),
Tuple.Create( 3.1m, 2.8m),
Tuple.Create( 3.0m, 2.8m),
Tuple.Create( 3.0m, 2.0m),
Tuple.Create( 3m, 2m),
Tuple.Create( 3.8m, 2.4m),
Tuple.Create(3.10m, 3.10m),
Tuple.Create( 2.8m, 2.2m),
Tuple.Create(2.11m, 2.2m),
};
string report = string.Join(Environment.NewLine, tests
.Select(test =>
$"{test.Item1,5} + {test.Item2,5} == {EerieArithmetics(test.Item1, test.Item2),5}"));
Console.Write(report);
3.10 + 2.8 == 6.6
3.1 + 2.8 == 5.9
3.0 + 2.8 == 5.8
3.0 + 2.0 == 5
3 + 2 == 5
3.8 + 2.4 == 6
3.10 + 3.10 == 7.8
2.8 + 2.2 == 4.10
2.11 + 2.2 == 5.1
DateTime d1 = new DateTime(3, 10, 1); // 1 Oct 3 AD
DateTime d2 = new DateTime(2, 8, 1); // 1 Aug 2 AD
DateTime result = d1
.AddYears(d2.Year)
.AddMonths(d2.Month); // 1 Jun 6 AD
// 6.6
Console.Write($"{result.Year}.{result.Month}");