我正在尝试使用以下方法转换以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
。
答案 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倍乘法那么快。