How to Calculate with TimeSpan in c# - c#

I need to divide two TimeSpan.
I have one TimeSpan "worktime" and the other TimeSpan "productive"
What i want is to get as result of worktime/productive is a percentage. I need to get the "added value" (<- I think this is how it's called in english :)),

In .NET Core you can simply divide the TimeSpans. TimeSpan has a division operator.
This works:
var t1=TimeSpan.FromTicks(1000);
var t2=TimeSpan.FromTicks(100);
Console.WriteLine(t2/t1);
---------------------
0.1 ```

A Simple example:
DateTime d1 = DateTime.Parse("10:00:00");
DateTime d2 = DateTime.Parse("13:00:00");
TimeSpan t1 = d2 - d1; // three hours
TimeSpan t2 = new TimeSpan(0,15,0); // 15 minutes
Console.WriteLine(t1/t2);
This outputs: 12
see: https://onlinegdb.com/ImxwiWk37

var addedValue = (decimal)workTime.Ticks/productive.Ticks * 100;
The decimal cast is needed or the division will automatically round and you'll get very inaccurate percentages in certain cases.

I need to get the "added value"
By this, do you mean you want the percentage expressed as a percentage of the overall work time that was productive?
So if the total work time was 10 hours and the productive work time was 9 hours, the percentage of productive work time would be 90%?
If so, the answer is:
double percentage = double percentage = 100.0 - 100.0 * (worktime.Ticks - productive.Ticks) / worktime.Ticks;

Related

How to multiply a timespan by a decimal?

I'm working on a project which calculates a cost of calls from two different times entered by the user. I've parsed the data into the code as DateTime.
DateTime starttime = new DateTime(Convert.ToDateTime(cal1.SelectedDate).Year,Convert.ToDateTime(cal1.SelectedDate).Month,Convert.ToDateTime(cal1.SelectedDate).Day,
Convert.ToInt32(drpdwn1.SelectedValue),
Convert.ToInt32(drpdwn2.SelectedValue),
Convert.ToInt32(drpdwn3.SelectedValue));
DateTime endtime = new DateTime(Convert.ToDateTime(cal1.SelectedDate).Year, Convert.ToDateTime(cal1.SelectedDate).Month, Convert.ToDateTime(cal1.SelectedDate).Day,
Convert.ToInt32(drpdwn4.SelectedValue),
Convert.ToInt32(drpdwn5.SelectedValue),
Convert.ToInt32(drpdwn6.SelectedValue));
And subtracts the two to get a timespan.
TimeSpan duration3 = (endtime - starttime);
txtDisplay.Text = duration3.ToString();
Can someone help me find a way to multiply $0.35 to the timespan duration3?
Here is what I'm using right now but the textbox keeps displaying 0
double mins = duration3.Minutes;
double hrs = duration3.Hours;
double cost = ((hrs * 60) + mins) * 0.35;
txtCost.Text = cost.ToString();
//$0.35/min
// ((0.35*60)*hr + 0.35*min)
Possibly something like:
static decimal Foo(TimeSpan duration, decimal perMinuteRate)
=> ((decimal)duration.TotalMinutes) * perMinuteRate;
although note that TotalMinutes is a double, so this could have unexpected rounding if your duration is very fractional.
Better to do it this way, so you don't interfer with double precision errors:
public static decimal MultiplyPerMinute(TimeSpan a, decimal b)
{
return a.Ticks * b / TimeSpan.TicksPerMinute;
}
When you work with decimal, only double or float should scare you off in any possible operator. Decimal is a type made specificaly for digital, and precision durable operations.
As written, the question is not very clear. There are two questions really:
How to multiply a TimeSpan by a decimal?
Why is my TextBox always displaying zero?
Question 1 is not clear - it can be interpreted in many ways. From reading the posted code, comments and other answers it is possible to see that you are trying to calculate the "cost of a TimeSpan given the cost per minute". Why not ask this question?
But that isn't really your question - your posted code does indicate that you have an idea about how to calculate the "cost of a TimeSpan given the cost per minute", the problem is that your "textbox keeps displaying 0".
From the code posted, I don't know why this is. However, following some good debugging practices should fairly quickly help you narrow down the problem yourself.
See this link to a post by Eric Lippert that you should find useful:
How to debug small programs
No need to calculate the minutes yourself - and multiplying is easy:
TimeSpan ts = DateTime.Now - DateTime.Today;
var cost = ((int)ts.TotalMinutes) * 0.35m; // cost per minute, edited wrongly used 0.63m
I am int ing out the decimals of TotalMinutes to avoid billing for 23.2832s as well ;)

Someone stole my minute :/

I am trying to convert a time represented in double, something like 23.40 which means 23 hours and 40 minutes, using the following method:
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;
}
When testing it on some times, like 23.40 for example:
Console.WriteLine(DoubleToTimeSpan(23.40));
It shows 23:39:00, a whole minute has been stolen by the system! Where is my minute?
Note: I know about TimeSpan.FromHours, this doesn't help me because this method considers the minutes as percentage, so 23.40 is 23 hours and 40% of an hour, which is 23:24:00.
Since 0.4 cannot be exactly represented in the Double floating-point format, you get its nearest representation, which in the case of (23.4-23)*100 is probably something like 39.999999999999858. When you use (int), you truncate the fraction, leaving you with 39.
You need to round instead of truncate, so use (int)Math.Round(minute).
Alternatively, you can use the Decimal type, which can exactly represent decimal numbers like 23.40.
Try rounding it instead of 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;
}
If you do just (int)minute it will take the integer part of your double.
When you cast from a double to an int, it's truncating your value for minute -- thus your lost minute.
(time - hour) * 100d
Will evaluate to 39.999999999999858, and thus 39 when casting to int.
You've used Math.Floor for the hour, so use Math.Ceiling for the minute. It seems to work ok.
private static TimeSpan DoubleToTimeSpan(double time)
{
return new TimeSpan((int)Math.Floor(time), (int)Math.Ceiling((time - Math.Floor(time)) * 100d), 0);
}
Another option to use decimals. This will prevent precision loss.
decimal minute = ((decimal)time)-((decimal)hour)*100;
Not sure if it's a better solution, but if you're on .NET 4.0 or later, you can also go through a string. It seems like "23.40" is a sequence of characters with one interpretation as a double, and another one as a TimeSpan.
If you like that idea, use:
TimeSpan DoubleToTimeSpan(double time)
{
string str = time.ToString("F2", CultureInfo.InvariantCulture);
TimeSpan ts = TimeSpan.ParseExact(str, "h'.'mm", CultureInfo.InvariantCulture);
return ts;
}
Maybe not as fast as the multiply-by-100-and-round approach, though I haven't tested that.

C# midpointrounding down to zero

I know about MidpointRounding.AwayFromZero and MidpointRounding.ToEven, but I think I want something inbetween. It is for a promotions module, so discounted prices must round down if the value is .5.
For example, I would like:
£1.244 to round to £1.24
£1.245 to round to £1.24
£1.246 to round to £1.25
As I understand it, .AwayFromZero would round the middle value to £1.25 and .ToEven would round correctly to £1.24, but £1.335 would be rounded to £1.34, rather than £1.33 which is what I want.
Does anyone know how to accomplish this?
Thanks, Jon
There is a lot of unspecified behavior. Let's keep it safe and do the rounding explicitly, ignoring negatives since this is about money:
public static decimal Promotion(decimal value) {
decimal unround = decimal.Floor(value * 100m);
decimal fraction = value * 100m - unround;
if (fraction <= 0.5m) return unround / 100m;
else return (unround + 1m) / 100m;
}
Math.ceiling(x - 0.5)
Should do the trick.
Ussually to do something like this you subtract .001 from your value, then round normally.
1.244 - .001 = 1.243 = 1.24
1.245 - .001 = 1.244 = 1.24
1.246 - .001 = 1.245 = 1.25
1.300 - .001 = 1.299 = 1.3
In this case, you REALLY want to put this in it's own function/extrension method, whatever, and document with a function WHY you subtract .001 before rounding.

Time difference is zero in second calculation of division in c#

I need to calculate the time difference faken for division most accurately in nano seconds. Please tell me to do this.
At Present i'm using a lower accuracy method in which the problem is that : when the first calculation is performed it shows 87 milliseconds or 65 milliseconds as answer. But when the function is called again second time or more, it only show 0 milliseconds.
The code is :
long startTick = DateTime.Now.Ticks;
double result = (double)22 / 7;
result = System.Math.Round(result, digit);
long endTick = DateTime.Now.Ticks;
long tick = endTick - startTick;
double milliseconds = tick / TimeSpan.TicksPerMillisecond;
time.Text = result + "\nThe division took " + milliseconds + " milliseconds to complete.";
digit is the parameter of function which is variable. No matter what the value of digit is the milliseconds value remains 0 after first calling of function....
Please suggest more accurate way in which calling the same function with different decimal digits will result in different time interval in c# for windows Phone.
I think the memory flush should be done before and after each calculation. But i dont know how to do this.
I don't like this tick method personally for accuracy. I've tried stopwatch also but its not working. Please suggest another method best suited in my case. I want result like : 0.0345 or 0.0714 seconds.
Thanks
You are performing integer division on this line:
double milliseconds = tick / TimeSpan.TicksPerMillisecond;
Even though you are declaring it as a double, a long divided by a long will truncate the decimal. You are better off doing:
double milliseconds = (double)tick / TimeSpan.TicksPerMillisecond;
Or better yet, just ditch the tick stuff all together:
DateTime start = DateTime.Now;
double result = (double)22 / 7;
result = System.Math.Round(result, digit);
DateTime end = DateTime.Now;
double milliseconds = (end - start).TotalMilliseconds;
time.Text = result + "\nThe division took " + milliseconds + " milliseconds to complete.";
You won't be able to get micro or nano level precision, but you will get millisecond precision with a margin of error.
You still may get zero, however. You are trying to time how long a simple division operation takes. You could do millions of division operations in less than a second. You may want to do it 1,000,000 times, then divide the result by a 1,000,000:
DateTime start = DateTime.Now;
for (var i = 0; i < 1000000; i++)
{
double result = (double)22 / 7;
result = System.Math.Round(result, digit);
}
DateTime end = DateTime.Now;
double milliseconds = (end - start).TotalMilliseconds / 1000000;
This still won't be completely realistic, but should get you an actual number.
Since you have the time in ticks, just increase the resolution by multiplying the denominator:
double microseconds = tick / (TimeSpan.TicksPerMillisecond * 1000.0);
Why are you not using StopWatch Class to do your time calulation.
It is meant to the calculate the time the you want ..
Here is a link for your reference.
http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx
//if you want to get the full milliseconds you could also do something like this.
dateStartTime = Convert.ToDateTime(DateTime.Now.TimeOfDay.ToString());
//then where you end the code do this
dateEndTime = Convert.ToDateTime(DateTime.Now.TimeOfDay.ToString());
ddateDuration = (TimeSpan)(dateEndTime - dateStartTime);
then to display out what you are actually looking for in terms of miliseconds do
Console.WriteLine(ddateDuration.ToString().Substring(0, 8));
// or some other method that you are using to display the results

Calculating the difference between 2 times, and then compare the difference to see if it is less than 5 minutes

I want to calculate the difference between two times and then compare difference is less than 5 MIN..
Please note I want difference in min. using c#.net
Just use the subtraction operator, and use the Duration method to get the absolute value
DateTime dt1 = ...;
DateTime dt2 = ...;
TimeSpan diff = (dt2 - dt1).Duration();
if (diff.TotalMinutes < 5)
{
// do something
}
Here is one way of doing it:
TimeSpan span = firstDate - secondDate;
return span.TotalMinutes < 5;
Almost identical to #Thomas, but another method -
Assuming that dt1 is greater than dt2
if(dt1.Sutract(dt2).TotalMinutes < 5)
{
// do
}
The primary difference is that it uses the dt1 memory space to perform the subtraction.
Edit: To use the TotalMinutes correction. The substract method is still present in the datetime object though so I'll leave it here.

Categories

Resources