Sum of 3 numbers representing Hours in linq query or c# - c#

I have column with spent hours values like (10.30,1.45 ...)
I want to sum those numbers to get the total spent hours.
Example:
Values 11.11,
0.50, 0.59
Total spent hours 11 and the sum of minutes
(11 + 50 + 59) = 120 minutes = 2 hour
So my final output should be 11 + 2 = 13.00 hour
but in my c# query I am getting 11.11 + 0.50 + 0.59 = 12.2 which is wrong as i considered it as hour format.
How can get the result 13.00 hours without splitting the numbers.
I Tried:
db.myTable.Where(t => t.is_deleted == false).Sum(t => t.time_spent)
which is giving me 12.2 but i want 13.00 as i considered it as time.
EDIT:
I used
List<string> hoursTemp1 = Model.tblName.Where(t => t.is_deleted == false).Select(p => p.time_spent.ToString()).ToList();
var total_effort_hr = new TimeSpan(hoursTemp1.Sum(x => TimeSpan.ParseExact(x, "h\\.mm", System.Globalization.CultureInfo.InvariantCulture).Ticks)).ToString(#"hh\:mm");
But now I am Getting OverflowException for Hour value Greater then 24 and minute value greater then 60
So can anyone please help me how to resolve this error and get proper result?
Any help will be apreciated.

var times = new string[] { "11.11", "0.50", "0.59" };
var totalTime = new TimeSpan(times.Sum(x => TimeSpan.ParseExact(x, "h\\.mm", CultureInfo.InvariantCulture).Ticks));
Console.WriteLine(totalTime); //13:00:00

public decimal GetHours(IEnumerable<decimal> args)
{
return args.Sum(x=> Math.Truncate(x) + (x-Math.Truncate(x))*100/60);
}
Or with one truncate:
public decimal GetHours(IEnumerable<decimal> args)
{
return args.Sum(x=> (5*x-2*Math.Truncate(x))/3);
}
But seriously, I will cutoff hand for such datetime handling. Almost every database has type that represents date, time or both. Why not to use them to avoid this kind of crap?

Related

Convert Decimal (62.25) to Hours and Minutes String (62 Hours and 15 Minutes)?

Is there a simple way to convert my Decimal value (ex. 62.25) to a returned string like "62 Hours : 15 Minutes"? I have been looking at several posts similar to this one (Decimal Hour into Time?), but even the suggestions that say they work for figures greater than 24hr periods are not working.
This is pretty simple:
var decimal = 62.25;
var hours = Math.floor(decimal);
var mins = 60 * (decimal - hours);
console.log(`${hours} hours, ${mins} minutes`);
In c#, you can likely just leverage the TimeSpan class. See .NET fiddle here:
using System;
public class Program
{
public static void Main()
{
var dec = 62.25m;
var ts = TimeSpan.FromHours((double)dec);
Console.WriteLine("{0} Hours, {1} Minutes", Math.Floor(ts.TotalHours), ts.Minutes);
}
}
This question is really simple and this answer too and has a lot of basic programming on it and there are a lot of different ways of doing it. The simple one is to use cast:
double date = getDate(); //62.25. I don't know where you get date from :P
int hours = (int)date; //62
float minutes = 60* (date - hours); //60 * (62.25 - 62 ) = 15
Write( "Hours: " + hours + "\nMinutes: " + minutes );
Consider doing valdiations if minutes have decimal points (12.3 minutes should be rounded, etc.)
Give this one a try
void Main()
{
Console.WriteLine (DecimalToTime(62.25)); // will output 62 Hours:15
}
string DecimalToTime(double dbTime)
{
int hour = (int)dbTime;
int minute = (int)((dbTime - hour) * 60);
string time = hour + " Hours:" + minute;
return time;
}

How to get the total hours with different dates in C#

This is my problem now, i want to get the total hours and mins of work.
example from jan. 11 2017 22:00 to Jan. 12 2017 7:00.
so far i have it only work when the end date is not change
DateTime pin = today, pout = DateTime.Parse(empTime);
TimeSpan spanMe = pout.Subtract(pin);
spanMe.Hours
spanMe.Minutes
it gives me negative numbers.
it gives me negative numbers.
That is expected if you subtract a larger item from a smaller item (ie. subtracting a more recent time from an older time). If you always want to see the difference as a positive number and do not want to take into account which is larger then wrap the result of the properties (like .Hours) in Math.Abs (absolute value).
var hours = System.Math.Abs(spanMe.Hours);
var minutes = System.Math.Abs(spanMe.Minutes);
Also as pointed out by #stuartd there is a difference between Hours/Minutes and TotalHours/TotalMinutes. Make sure you are using the correct one for your needs.
It should work :
DateTime pin = DateTime.Parse("jan 11 2017 22:00");
DateTime pout = DateTime.Parse("Jan 12 2017 7:00");
TimeSpan spanMe = pout.Subtract(pin);
Console.WriteLine("Hours : {0}, Minutes : {1}", spanMe.Hours, spanMe.Minutes);
Console.ReadLine();
if you know what is the latest date, you need arrange it accordingly. If not, you can not multiply by -1:
double GetHouers(DateTime one, DateTime another)
{
var diff = (one - another).TotalHours;
return diff > 0 ? diff : diff * -1;
}
You can subtract one DateTime Object from another, and then use .TotalHours property of the DateTime class to get the number of hours. It will give you a double value representing the total hours.
DateTime pin = today, pout = DateTime.Parse(empTime);
double hours = (pout - pin).TotalHours;
DateTime pin = today, pout = DateTime.Parse(empTime);
TimeSpan spanMe = pin.Subtract(pout);
var hours = spanMe.TotalHours;
var minutes = spanMe.TotalMinutes;
You want to use TotalHours and TotalMinutes as these will handle fractions thereof, versus Hours and Minutes which return only whole values. You also need to swap the order of your operands as above for the subtraction step.

How to combine integers in c# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Im looking for a way to combine my integers together.
I got 3 integers i want to make one from them.
All the integers are holding a time currency wich looks a little like this:
var date = DateTime.Now;
int timeHours = date.Hour;
I got the Hours, Minutes and Seconds and want to combine so they would look like this:
Hour : Minutes : Seconds
How can i combine the integers together to do that.
Note: I've looked on the internet but i could not get the information i was looking for.
This is what i looked at:
Combine two integers to create a unique number
How to combine 2 integers in order to get 1?
Combining these integers will generate a string, not an another integer. You can easily format your DateTime with ToString() method like;
var str = DateTime.Now.ToString("H':'m':'s"); // eg: 11:0:2
If you wanna get your hour, minute and second part with leading zeros for single digits, you can use HH:mm:ss format instead.
var str = DateTime.Now.ToString("HH':'mm':'ss"); // eg: 11:00:02
DateTime.Now already contains all information you need, date and time. All you need to do is format this information
There're many ways to pack two (or many) integers into one based
on their ranges, e.g.
int i1 = 123;
int i2 = 456;
// two 32-bit integers into 64-bit one
long result = (((long) i1) << 32) | i2;
In your particular case
int hours = 5;
int minutes = 10;
int seconds = 59;
int combined = hours * 3600 + minutes * 60 + seconds;
reverse:
int combined = 12345;
int seconds = combined % 60;
int minutes = (combined / 60) % 60;
int hours = combined / 3600;
you can try the below code i think it's useful
var date = DateTime.Now;
var result = date.Hour + ":" + date.Minute + ":" + date.Second;
Console.WriteLine(result);
A simple way using the base 10 number system is to just
var number = hours * 10000 + minutes * 100 + seconds
this returns a number like 150936 for 15:09:36
To convert back:
seconds = number % 100
minutes = (number / 100) % 100
hours = number / 10000
Note that this is obviously not the most efficient approach, but simple
You should cast to string with format function for example:
string result = string.Format("{0:00}:{1:00}:{2:00}", timeHours, timeMinutes, timeSeconds);
Just to be complete:
format HH:mm:ss:
string result = string.Format("{0:00}:{1:00}:{2:00}", timeHours, timeMinutes, timeSeconds);
string result = DateTime.Now.ToString("HH:mm:ss");
format H:m:s:
string result = string.Format("{0}:{1}:{2}", timeHours, timeMinutes, timeSeconds);
string result = DateTime.Now.ToString("H:m:s");

Converting a double to a time that makes sense

Basically I am setting a limit of hours a user can use. Now every time a button is press, whatever time that person accrued gets taken away from this total value.
However because a limit would be represented as say 156 hours, and the datetime representation of 5 minutes would be 00.05 the result would be 155.95, rather than 155.55 .
I work this out like so
string date2 = TotalMonthlyHours.ToString("HH.mm");
double date = double.Parse(date2);
RunningTotal = date + RunningTotal;
Total = limit - RunningTotal;
Any ideas?
I think you are trying to represent 5 minutes as 0.05. The way to do that is to first of all obtain the minutes as an integer. And then simply convert to double.
double floatmins = minutes/100.0;
And you convert in the other direction like this:
int minutes = (int) (floatmins*100.0);
However, I urge you not to go any further with this. You cannot expect to perform arithmetic on a quantity like that. What is the result of 2.20-1.50? You and I know it's 30 minutes, but the computer says 0.70 which is no use at all.
Store the hours using a true fractional representation. So 5 minutes is 5/60.0. Or store the total minutes in an integer. Or total seconds in an integer. Or a TimeSpan.
The key is that you can write your own helper routines to convert from a sane storage format to a value that is human readable. But you must store the raw data in a representation that will admit arithmetic operations.
I think I worked it out by doing something like this
string[] times = date.ToString().Split('.');
if (date != 0.0)
{
string minutesString = times[1];
string hoursString = times[0];
double minutes = Convert.ToDouble(minutesString);
double hours = Convert.ToDouble(hoursString);
// end of splitting
TimeSpan Limit = TimeSpan.FromHours(limit);
TimeSpan Hours = TimeSpan.FromHours((int)hours);
TimeSpan Minutes = TimeSpan.FromMinutes((int)minutes);
TimeSpan SubTotal = Hours + Minutes;
Time = Limit - SubTotal;
}
Edit: Glad you came up with the same as me,Just read your reply David, let's hope it works
I would convert it to minutes first than add as minutes to the date
var min = Convert.ToDouble(Convert.ToDecimal(textbox.Text) * 60);
DateTimePickerEnd.DbSelectedDate = e.NewDate.Value.AddMinutes(min);

Is this LINQ query with averaging and grouping by hour written efficiently?

This is my first real-world LINQ-to-SQL query. I was wondering if I am making any large, obvious mistakes.
I have a medium-large sized (2M+ records, adding 13k a day) table with data, dataTypeID, machineID, and dateStamp. I'd like to get the average, min, and max of data from all machines and of a specific dataType within a 4 hour period, going back for 28 days.
E.g
DateTime Avg Min Max
1/1/10 12:00AM 74.2 72.1 75.7
1/1/10 04:00AM 74.5 73.1 76.2
1/1/10 08:00AM 73.7 71.5 74.2
1/1/10 12:00PM 73.2 71.2 76.1
etc..
1/28/10 12:00AM 73.1 71.3 75.5
So far I have only been able to group the averages by 1 hour increments, but I could probably deal with that if the alternatives are overly messy.
Code:
var q =
from d in DataPointTable
where d.dateStamp > DateTime.Now.AddDays(-28) && (d.dataTypeID == (int)dataType + 1)
group d by new {
d.dateStamp.Year,
d.dateStamp.Month,
d.dateStamp.Day,
d.dateStamp.Hour
} into groupedData
orderby groupedData.Key.Year, groupedData.Key.Month, groupedData.Key.Day, groupedData.Key.Hour ascending
select new {
date = Convert.ToDateTime(
groupedData.Key.Year.ToString() + "-" +
groupedData.Key.Month.ToString() + "-" +
groupedData.Key.Day.ToString() + " " +
groupedData.Key.Hour.ToString() + ":00"
),
avg = groupedData.Average(d => d.data),
max = groupedData.Max(d => d.data),
min = groupedData.Min(d => d.data)
};
If you want 4 hour increments divide the hour by 4 (using integer division) and then multiply by 4 when creating the new datetime element. Note you can simply use the constructor that takes year, month, day, hour, minute, and second instead of constructing a string and converting it.
var q =
from d in DataPointTable
where d.dateStamp > DateTime.Now.AddDays(-28) && (d.dataTypeID == (int)dataType + 1)
group d by new {
d.dateStamp.Year,
d.dateStamp.Month,
d.dateStamp.Day,
Hour = d.dateStamp.Hour / 4
} into groupedData
orderby groupedData.Key.Year, groupedData.Key.Month, groupedData.Key.Day, groupedData.Key.Hour ascending
select new {
date = new DateTime(
groupedData.Key.Year,
groupedData.Key.Month,
groupedData.Key.Day,
(groupedData.Key.Hour * 4),
0, 0),
avg = groupedData.Average(d => d.data),
max = groupedData.Max(d => d.data),
min = groupedData.Min(d => d.data)
};
To improve efficiency you might want to consider adding an index on the dateStamp column. Given that you're only selecting a potentially small range of the dates, using an index should be a significant advantage. I would expect the query plan to do an index seek for the first date, making it even faster.

Categories