有人偷走了我的一分钟:/

时间:2013-08-02 12:54:16

标签: c# time timespan

我正在尝试使用以下方法转换以double表示的时间,例如23.40,这意味着23小时40分钟:

private TimeSpan DoubleToTimeSpan(double time)
{
    double hour = Math.Floor(time);
    double minute = (time - hour) * 100d;
    TimeSpan ts = new TimeSpan((int)hour, (int)minute, 0);
    return ts;
}

在某些时候进行测试时,例如23.40

Console.WriteLine(DoubleToTimeSpan(23.40));

它显示23:39:00,整整一分钟都被系统偷走了!我的分钟在哪里?

注意:我知道TimeSpan.FromHours,这对我没有帮助,因为此方法将分钟视为百分比,因此23.40是23小时40%的小时,23:24:00

7 个答案:

答案 0 :(得分:9)

由于0.4无法以Double浮点格式精确表示,因此您可以获得最近的表示形式,在(23.4-23)*100的情况下可能类似于39.999999999999858 。当您使用(int)时,您会截断该分数,并为您留下39。

您需要舍入而不是截断,因此请使用(int)Math.Round(minute)

或者,您可以使用Decimal类型,可以完全代表23.40等十进制数字。

答案 1 :(得分:2)

尝试将其舍入而不是int

private TimeSpan DoubleToTimeSpan(double time)
{
    double hour = Math.Floor(time);
    hour.Dump();
    double minute = (time - hour) * 100d;
    minute.Dump();
    TimeSpan ts = new TimeSpan((int)hour, (int)Math.Round(minute), 0);
    return ts;
}

如果你只做(int)分钟,它将占用你的双倍的整数部分。

答案 2 :(得分:0)

当你从double投射到int时,它会截断你的分钟价值 - 因此你失去了分钟。

答案 3 :(得分:0)

(time - hour) * 100d

将评估为39.999999999999858,因此在转换为int时为39。

答案 4 :(得分:0)

您已使用Math.Floor作为小时,因此请使用Math.Ceiling作为分钟。它似乎工作正常。

private static TimeSpan DoubleToTimeSpan(double time)
{
    return new TimeSpan((int)Math.Floor(time), (int)Math.Ceiling((time - Math.Floor(time)) * 100d), 0);
}

答案 5 :(得分:0)

使用小数的另一个选项。这样可以防止精度损失。

decimal minute = ((decimal)time)-((decimal)hour)*100;

答案 6 :(得分:0)

不确定它是否是更好的解决方案,但如果您使用的是.NET 4.0或更高版本,则还可以通过string。似乎"23.40"是一系列字符,其中一种解释为double,另一种解释为TimeSpan

如果你喜欢这个想法,请使用:

TimeSpan DoubleToTimeSpan(double time)
{
    string str = time.ToString("F2", CultureInfo.InvariantCulture);
    TimeSpan ts = TimeSpan.ParseExact(str, "h'.'mm", CultureInfo.InvariantCulture);
    return ts;
}

虽然我没有测试过,但可能没有100倍乘法那么快。