How do I add TimeSpan in C# inside Loop? - c#

Can anyone please tell me I need to add time with interval with in the for loop. This is my C# code.
var t1 = selectedTime.TimeOfDay;
t1 = 8.00 //assum time is 8.00
for (int i = 0; i <=5; i++) {
var duration = TimeSpan.FromMinutes(15);
var t3 = duration;
}
My output should be:
8.00
8.15
8.30
8.45
9.00

The gotcha in your original code is increment and persist the new value; in this snippet I updated the t1 variable:
var selectedTime = DateTime.Today.AddHours(8);
var t1 = selectedTime.TimeOfDay; //assume time is 8.00
for (int i = 0; i <=5; i++)
{
Console.WriteLine(t1);
t1 += TimeSpan.FromMinutes(15);
}

Try like this:
var t1 = DateTime.Now.TimeOfDay;
//t1 = 8.00 //assum time is 8.00
var duration = TimeSpan.FromMinutes(15);
Console.WriteLine(t1); // print current time
for (int i = 0; i <=4; i++)
{
t1 += duration; // add timespan 4 times
Console.WriteLine(t1);
}
You can add TimeSpan to the DateTime easily. You just need to make sure you are remembering the previous value or by increasing the time span (eg. 15 min, 30 min etc) in each loop cycle.

Alternatively, you could use the DateTime.AddMinutes() method:
DateTime t1 = DateTime.Now.AddHours(8);
for(int i = 0; i < 5; i++) {
Console.WriteLine(t1.AddMinutes(15 * i).ToString("HH:mm"));
}

TimeSpan is added using the + operator with another TimeSpan, for example, I can implement this 15 seconds interval loop using Linq as the following:
TimeSpan initialTimeSpan = new TimeSpan(0, 4, 2);
IEnumerable<TimeSpan> spans = Enumerable.Range(0, 5)
.Select(x => x * 15)
.Select(x => initialTimeSpan + TimeSpan.FromSeconds(x));
foreach (TimeSpan span in spans)
{
Console.WriteLine(span);
}
To add it to a DateTime use the Add method:
DateTime date = DateTime.Now;
TimeSpan initialTimeSpan = new TimeSpan(0, 4, 2);
date = date.Add(initialTimeSpan);
Or you can just add the period you wish without using TimeSpan by using the AddSeconds/AddMinutes/AddHours/AddMilliseconds/AddTicks/AddYears/AddDays/AddMonths methods:
DateTime date = DateTime.Now;
TimeSpan initialTimeSpan = new TimeSpan(0, 4, 2);
date = date.AddSeconds(5);
You can use everything in a loop like that:
DateTime initialTime = DateTime.Now;
for (DateTime loopTime = initialTime; loopTime < initialTime.AddMinutes(2); loopTime = loopTime.AddSeconds(15))
{
Console.WriteLine(loopTime);
}
And you will get the following output:
26/09/2015 13:00:33
26/09/2015 13:00:48
26/09/2015 13:01:03
26/09/2015 13:01:18
26/09/2015 13:01:33
26/09/2015 13:01:48
26/09/2015 13:02:03
26/09/2015 13:02:18
To get the output in the format you wanted you can change the printing to the following:
Console.Write(loopTime.Minute + ".");
if (loopTime.Second < 10)
{
Console.Write(0);
}
Console.WriteLine(loopTime.Second);
And you will get this output for the same hours shown above:
0.33
0.48
1.03
1.18
1.33
1.48
2.03
2.18

Related

Error accessing DateTime List. "Index out of bounds" or "contains no elements"

I have some trouble and i don't really understand why, nor can I seem to find a solution.
I have a list of datetime values. I'm trying to extract the first and last value from the list in order to calculate the total amount of hours between them. Below is the code that shows how the list is generated. The rest of the code works, thus I know that the list contains elements. The problem occurs at the 5 lines of code at the bottom.
List<DateTime> datesList = new List<DateTime>();
List<string> distancesList = new List<string>();
DateTime dateFromDb = new DateTime();
string distanceFromDb;
int distancesCounter1 = 0;
int distancesCounter2 = 0;
double numberOfDistances;
double sittingPercentage;
double standingPercentage;
SqlDataReader reader;
dbConnection.Open();
using (SqlCommand selectCmd =
new SqlCommand("SELECT * FROM Measurements where DateTime between #fromTime And #now ORDER BY DateTime DESC", dbConnection))
{
selectCmd.Parameters.AddWithValue("now", now);
selectCmd.Parameters.AddWithValue("fromTime", fromTime);
reader = selectCmd.ExecuteReader();
while (reader.Read())
{
dateFromDb = reader.GetDateTime(reader.GetOrdinal("DateTime"));
distanceFromDb = reader.GetString(reader.GetOrdinal("Distance"));
datesList.Add(dateFromDb);
distancesList.Add(distanceFromDb);
}
reader.Close();
dbConnection.Close();
}
foreach (var dist in distancesList)
{
if (Convert.ToInt16(dist) <= 85)
{
distancesCounter1++;
}
else
{
distancesCounter2++;
}
}
numberOfDistances = distancesList.Count;
sittingPercentage = distancesCounter1 / numberOfDistances * 100;
standingPercentage = distancesCounter2 / numberOfDistances * 100;
chartPositions.Series["Sitting"].Points.AddXY("Position", sittingPercentage);
chartPositions.Series["Standing"].Points.AddXY("Position", standingPercentage);
TimeSpan totalHours = new TimeSpan();
DateTime time1 = datesList.First();
DateTime time2 = datesList.Last();
totalHours = time1 - time2;
textBoxTime.Text = totalHours.TotalHours.ToString();
I have tried the above example and the below example:
TimeSpan totalHours = new TimeSpan();
DateTime time1 = datesList[0];
DateTime time2 = datesList[datesList.Count - 1];
totalHours = time1 - time2;
textBoxTime.Text = totalHours.TotalHours.ToString();
With a foreach loop i print the elements of the List to a listbox:
foreach (var date in datesList)
{
listBox1.Items.Add(date);
}
//TimeSpan totalHours = new TimeSpan();
//DateTime time1 = datesList.First();
//DateTime time2 = datesList.Last();
//totalHours = time1 - time2;
//textBoxTime.Text = totalHours.TotalHours.ToString();
I hope you can help me, thanks in advance!
The items in a List are numbered from 0 to Count - 1.
So, to access the last item, do not use datesList[datesList.Count], but datesList[datesList.Count - 1];
Your code should always be prepared to handle an empty list. So, first check whether the list is empty before trying to access it's contents.
TimeSpan totalHours = new TimeSpan();
if (datesList.Any())
{
DateTime time1 = datesList.First();
DateTime time2 = datesList.Last();
totalHours = time1 - time2;
}
else
{
totalHours = TimeSpan.Zero;
}

Calculating next time and rounding date-time

I have datetime like 2019-02-10 20:39:23 and I want to round this time to the next one apart 15 min to the closest one. So it means the next one should be 2019-02-10 21:45:00 or another example 21:24:17 should became 21:45:00... The code below works fine until I have datetime like 2019-02-10 23:54:20. Then the next one rounded should be 2019-03-10 00:00:00 but I get 2019-02-10 00:00:00.
Here is how I'm doing it:
static void Main(string[] args)
{
DateTime dt = DateTime.Parse("2019-02-10 23:54:23");
var interval = TimeSpan.FromMinutes(15);
DateTime last = NextTime(dt, interval);
Console.WriteLine(last);
}
private static DateTime NextTime(DateTime value, TimeSpan interval)
{
var temp = value.Add(new TimeSpan(interval.Ticks / 2));
var time = new TimeSpan((temp.TimeOfDay.Ticks / interval.Ticks) * interval.Ticks);
return value.Date.Add(time);
}
For output I get 2019-02-10 00:00:00 instead of 2019-03-10 00:00:00
Can't figure out why doesn't turn to next day...
The return value is being calculated from the wrong variable. Use temp instead of value:
private static DateTime NextTime(DateTime value, TimeSpan interval)
{
var temp = value.Add(new TimeSpan(interval.Ticks / 2));
var time = new TimeSpan((temp.TimeOfDay.Ticks / interval.Ticks) * interval.Ticks);
return temp.Date.Add(time);
}
The reason for this is because you're adding your interval to the value. If it rolls over a midnight/end of day your value.Date will return the wrong day. Since you store temp, you can return temp.Date.Add(time)
Using DateTime.Add(TimeSpan) the time is concat in the date.
I'v changed your code in this way and it did the trick:
private static DateTime NextTime(DateTime value, TimeSpan interval)
{
var temp = value.Add(new TimeSpan(interval.Ticks / 2));
var time = new TimeSpan((temp.TimeOfDay.Ticks / interval.Ticks) * interval.Ticks);
if (time == new TimeSpan(0, 0, 0)) { time = new TimeSpan(24, 0,0); }
var timeDiff = time - value.TimeOfDay;
var finalDate = value.AddHours(timeDiff.Hours);
finalDate = finalDate.AddMinutes(timeDiff.Minutes);
finalDate = finalDate.AddSeconds(timeDiff.Seconds);
return finalDate;
}
I believe that must have some way more beautifull to do that but it works.

Adding Duration that contains frames

I have a duration that contains frames:
e.g1: 00:00:00:00
hh:mm:ss:FR
FR - stands for frames which is 25 frames for the middleast/asia region.
But in C# it takes the last FR as seconds (which is 60seconds).
e.g2: 00:00:00:00
DD:hh:mm:ss
Now how do I add e.g1 in C#
Can I know with this format how do I add two duration.
TimeSpan t1 = TimeSpan.Parse(duration);
TimeSpan t2 = TimeSpan.Parse("00:00:30:18");
TimeSpan t3 = t1.Add(t2);
in this duration "00:00:30:18" 18 is considered as milliseconds and not frames, so Timespan.Duration won't work for you, and you need something custom (for displaying might work but not adding and subtracting):
public static class Extensions
{
public static TimeSpan AddWithFrames(this TimeSpan x, TimeSpan ts)
{
int fr = ts.Seconds + x.Seconds;
TimeSpan result = x.Add(ts).Add(new TimeSpan(0,0,fr/25,0));
return new TimeSpan(result.Days, result.Hours, result.Minutes, fr % 25);
}
}
And use it like:
TimeSpan t1 = TimeSpan.Parse(duration);
TimeSpan t2 = TimeSpan.Parse("00:00:30:18");
TimeSpan t3 = t1.AddWithFrames(t2);
you can use a custom class that handles operations with SMPTE timecodes.
you do not need to reinvent the wheel, as this project handles all different kinds of framerates and frame drops:
https://github.com/ailen0ada/Timecode4net
using Timecode4net;
var start = Timecode.FromString(input: "00:00:05:15", frameRate: FrameRate.fps25, isDropFrame: false);
var end = Timecode.FromString("00:00:10:22", FrameRate.fps25, false);
Console.WriteLine((end.TotalFrames - start.TotalFrames)/25.0);
gives you 5,28
Here is how I did it unless someone has a better way to simplify this, kindly please share
string timecode1 = "00:05:00:04";
string timecode2 = "00:06:00:24";
int hours1 = Int32.Parse(timecode1.Substring(0,2))*90000;
int minutes1 = Int32.Parse(timecode1.Substring(3, 2))*1500;
int seconds1 = Int32.Parse(timecode1.Substring(6, 2))*25;
int frames1 = Int32.Parse(timecode1.Substring(9, 2));
int hours2 = Int32.Parse(timecode2.Substring(0, 2)) * 90000;
int minutes2 = Int32.Parse(timecode2.Substring(3, 2)) * 1500;
int seconds2 = Int32.Parse(timecode2.Substring(6, 2)) * 25;
int frames2 = Int32.Parse(timecode2.Substring(9, 2));
int time1 = hours1 + minutes1 + seconds1 + frames1;
int time2 = hours2 + minutes2 + seconds2 + frames2;
int totaltime = time1 + time2;
int hours = totaltime / 90000;
int minutes = ((totaltime % 90000)) / 1500;
int seconds = ((totaltime % 90000) % 1500 )/ 25;
int frames = ((totaltime % 90000) % 1500) % 25;

Sum all the Timespan per row in DataGridView

This is my front end, in my case, I would like to add all the total hours of time in and time out of all my rows in my datagridview. My datagridview fields are id, employee code, date, timein and timeout.
Here is my back end, in here I computed the the late, the total hours, the day difference and the night difference. Is it possible to display on my textboxes the total hours, the late, the day diff and night based on the data on my datagridview. Sorry for my english, clarify my questions with yours.
string timeIn = datagridAttendance.CurrentRow.Cells["timeIn"].Value.ToString();
string timeOut = datagridAttendance.CurrentRow.Cells["timeOut"].Value.ToString();
DateTime tIn = Convert.ToDateTime(timeIn);
DateTime tOut = Convert.ToDateTime(timeOut);
TimeSpan span = tOut - tIn;
txtTotalHours.Text = Convert.ToString(span);
DateTime start = Convert.ToDateTime(txtStart.Text);
txtMe.Text = tIn.ToShortTimeString();
DateTime inTime = Convert.ToDateTime(txtMe.Text);
if (inTime > start)
{
TimeSpan late = inTime - start;
txtLate.Text = Convert.ToString(late);
}
else
{
txtLate.Text = "Not Late";
}
TimeSpan passLength = new TimeSpan(0, 0, 0, 1);
TimeSpan nightTime = new TimeSpan();
while (tIn < tOut)
{
tIn = tIn.Add(passLength);
if (tIn.Hour < 6 || tIn.Hour == 23)
{
nightTime = nightTime.Add(passLength);
}
}
txtNightDif.Text = Convert.ToString(nightTime);
TimeSpan day = span - nightTime;
txtDayDif.Text = Convert.ToString(day);
Your code will look like below with the arrays timein[] timeout[] being the values in each row of DataGridView
DateTime[] timein = { DateTime.Parse("1:00"), DateTime.Parse("3:00"), DateTime.Parse("5:00"), DateTime.Parse("7:00") };
DateTime[] timeout = { DateTime.Parse("2:00"), DateTime.Parse("4:00"), DateTime.Parse("6:00"), DateTime.Parse("8:00") };
TimeSpan totalTime = new TimeSpan();
for (int i = 0; i < timein.Count(); i++)
{
totalTime += timeout[i] - timein[i];
}​
You can do this in your database, and then return the sum of timespans as a column. That would be better and far easier.

C# Timer counter in xx.xx.xx format

I have a counter that counts up every 1 second and add 1 to an int.
Question
How can I format my string so the counter would look like this:
00:01:23
Instead of:
123
Things I've tried
Things I've tried so far:
for (int i = 0; i < 1; i++)
{
_Counter += 1;
labelUpTime.Text = _Counter.ToString();
}
My timer's interval is set to: 1000 (so it adds 1 every second).
I did read something about string.Format(""), but I don't know if it is applicable.
Thanks if you can guide me through this :D!
Use a TimeSpan:
_Counter += 1;
labelUpTime.Text = TimeSpan.FromSeconds(_Counter).ToString();
You could make it a TimeSpan (for that's what it is, a span of time), then format that:
labelUpTime.Text = TimeSpan.FromSeconds(_Counter).ToString();
Don't use a counter, and don't rely on the timer firing exactly every second. It won't. Do something like this.
class TimerTest
{
private DateTime _start = DateTime.Now;
private Timer _timer = new Timer(1000);
public TimerTest()
{
// (DateTime.Now - _start) returns a TimeSpan object
// Default TimeSpan.ToString() returns 00:00:00
_timer.Elapsed = (o, e) => labelUpTime.Text = (DateTime.Now - _start).ToString();
}
}
You can adjust the formatting with the TimeSpan.ToString method.
TimeSpan timer = new TimeSpan(0);
and on your interval:
timer += TimeSpan.FromSeconds(1);
Use timespan. To add a second use
mytimespan.Add(new TimespanFromSeconds(1));
Console.WriteLine(mytimespan); //Output in the form of xx:xx:xx
http://www.dotnetperls.com/timespan
it worked well for me
public TimeSpan ElapsedTimeFormatted
{
get
{
if (FinishedOn != null &&
StartedAt != null)
{
TimeSpan durationCount = new TimeSpan();
int hours = 0;
int minutes = 0;
int seconds = 0;
var times = Segments.Select(c => c.ElapsedTimeFormatted).ToList();
foreach (var time in times)
{
TimeSpan timeParse = TimeSpan.Parse(time);
hours = hours + (int)timeParse.Hours;
minutes = minutes + (int)timeParse.Minutes;
seconds = seconds + (int)timeParse.Seconds;
durationCount = new TimeSpan(hours, minutes, seconds);
}
return durationCount;
}
return new TimeSpan();
}
}

Categories

Resources