十进制的时间跨度年和月C#

时间:2018-09-26 07:57:57

标签: c# datetime timestamp

我有两个decimal

3.10m = 3 years 10 months 
 2.8m = 2 years  8 months.

我正在尝试sum这些值,结果是5.9,这是不正确

预期结果应为

6.6m = 6 years 6 months

任何人都可以建议我们如何使用TimeSpan或C#中的任何其他方法来实现此目标吗?在此先感谢

2 个答案:

答案 0 :(得分:5)

首先,我避免使用类似这样的小数来表示年/月值。如评论中所述,您将无法轻松区分1个月和10个月...而decimal 可以代表3.1和3.10,这将是一个非常奇怪的用法。只需将两个值保存在单独的整数中即可。

接下来,您无法使用TimeSpan进行这样的算术运算。 TimeSpan仅存储“一定数量的滴答声”-它不能处理“ 1个月”或“ 1年”之类的想法,因为它们不代表固定的滴答声数量。

我建议改为使用我的Noda Time库。您可以将这些值表示为Period对象。您仍然无法直接将年和月加在一起-Period并没有采用格里高利历系统,并且这样的算术不适用于某些非格里高利历,尤其是那些基于年份的月数。但是,您可以轻松编写自己的Period规范化方法:

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();
    }
}

现在您当然可以将所有内容保留为两个整数了-使用Period的好处是您可以轻松地将其添加到LocalDate或{ {1}}等。如果需要,您甚至可以不进行标准化就可以这样做。

答案 1 :(得分:2)

请勿执行此操作! app.get("/issues", function(req, res) { Issue.find({}) .exec(function (err, issues) { if (err) console.log(err); else console.log("successfully requested"); res.json(issues); }); }); 不适用于decimal。从技术上讲,您可以解决问题并区分 year.month3.1m3.10m可以解决);这是仅用于学术用途的代码:

decimal.GetBits

演示:

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 。作为一个快速又肮脏补丁(如果您只能使用标准库,则不能使用任何库),可以尝试decimal类:

DateTime