How can I round down DateTime but 23 times? - c#

for (int i = 0; i < 23; i++)
{
var dt = RoundDown(DateTime.Now, TimeSpan.FromMinutes(5));
datestimes.Add(dt);
}
And
DateTime RoundDown(DateTime date, TimeSpan interval)
{
return new DateTime(
(long)Math.Floor(date.Ticks / (double)interval.Ticks) * interval.Ticks
);
}
datestimes is List<DateTime>
I need to make that the first time to be rounded will be the current DateTime.Now for example if it's 23:44 then round it down to 23:40 and this is what happens now.
But from this point I want to round down more 22 times for example 23:40, 23:35, 23:30, 23:25 like that more 22 times and to add each time the rounded date time to the List

Only do the round down once. Then, subtract the interval instead of rounding.
DateTime dt = RoundDown(DateTime.Now, TimeSpan.FromMinutes(5));
while ( dt.Minutes != 0 )
{
// your code
dt = dt.AddMinutes(-5);
}

Declare the DateTime.Now variable before the loop. Get the minutes and get the rounded value. And then run a for loop and keep on decreasing the minutes by 5 and add to your list.
To get the largest number smaller than or equal to a number N and divided by K you can write the simple method.
int findNum(int N, int K)
{
    int rem = N % K;
 
    if (rem == 0)
        return N;
    else
        return N - rem;
}
In your case K is 5.

You forgot to actually decrease the date value that is being rounded down, which can be done with .AddMinutes(-5 * i).
Besides that, it's also more efficient to calculate the date only once. Doing so then also prevents race conditions in case your code runs while the clock changes behind the scenes to the next 5-minute interval.
Improved code:
var startDate = DateTime.Now;
for (int i = 0; i < 23; i++)
{
var dt = RoundDown(startDate.AddMinutes(-5 * i), TimeSpan.FromMinutes(5));
Console.WriteLine(dt);
}
Working demo: https://dotnetfiddle.net/6o5HyW

Related

How to get time in milliseconds?

I want to calculate the time of bubble sort algorithm in C#. But it always give 0. This is my code.
public void bubbleSort(int[] arr, ref double time)
{
var sp = new Stopwatch();
sp.Start();
int temp = 0;
for (int i = 0; i < arr.Length; i++)
{
for (int sort = 0; sort < arr.Length - 1; sort++)
{
if (arr[sort] > arr[sort + 1])
{
temp = arr[sort + 1];
arr[sort + 1] = arr[sort];
arr[sort] = temp;
}
}
}
sp.Stop();
time = sp.Elapsed.Milliseconds*1000;
}
in main the time is always 0. What mistake i have done in this code.
When you get Milliseconds, you're only getting the millisecond component of the time. Thus, 1.0501s will only be listed as 50ms, not 1050.1ms. Also, since this returns an int, you will not see fractional milliseconds, which may be the case for such a short algorythm.
Instead, use TotalMilliseconds, which will return the entire time in units of milliseconds, as well as retuning a double - which includes the fractional parts.
You need to use TotalMilliseconds property
Gets the value of the current TimeSpan structure expressed in whole and fractional milliseconds.
time = sp.Elapsed.TotalMilliseconds * 1000;

Calculate Time Logic rounding to nearest factor c#

I have two properties of time stamp without AM/PM. What's needed is to find the total time spent in quarter unit determined by _factor. Then there is a rounddown & roundup concept which is determined by _roundDown value as cut off point. Finally, returning a decimal value back after the calculation.
This resides in a class definition that sets up a property TotalTime. Because of this reason, I would like the code to be efficient. Excuse my code as this is the last piece of the project and want to get it done.
How can I improve the code: I am using mod calculation.
private decimal ComputeTotalTime(int _increment)
{
decimal _TotalHours = 0;
int _roundDown = 7, _factor = 15;
int int_TotalHours = 0;
if (String.IsNullOrEmpty(StartTime) || String.IsNullOrEmpty(EndTime)) return _TotalHours;
DateTime timeFromInput = DateTime.ParseExact(StartTime, "H:m", null);
DateTime timeToInput = DateTime.ParseExact(EndTime, "H:m", null);
//Here found a problem that we need to ensure that EndTime is greater than StartTime
//In one run, StartTime is 10:30 and EndTime is 2:32
//but the DateTime variables took is as 10:30 PM and 2:32 PM hence producing negative difference
TimeSpan ts = timeToInput.Subtract(timeFromInput)
int_TotalHours = ts.Hours * 60 + ts.Minutes;
if (int_TotalHours % _factor == 0) { /*I'm Perfect, no need to round*/ }
else if (int_TotalHours % _factor <= _roundDown) {
//Round down to nearest 15th, quarter
int_TotalHours = int_TotalHours - (int_TotalHours % _factor); }
else { //Round up to nearest quarter
int_TotalHours = int_TotalHours + (_factor - int_TotalHours % _factor); }
_TotalHours = Convert.ToDecimal(int_TotalHours / 60.00);
_TotalHours = (_TotalHours * 100) / 100;
return _TotalHours;
}
Thank you for your help.

Manipulating DateTime values not working as expected when using DateTime as loop index

I need to produce a list of date ranges, so that the output will eventually be:
0 – 28/02/2009 to 31/02/2010
1 – 31/03/2009 to 31/03/2010
2 – 30/04/2009 to 30/04/2010
3 – 31/05/2009 to 31/05/2010
4 – 30/06/2009 to 30/06/2010
5 – 31/07/2009 to 31/07/2010
6 – 31/08/2009 to 31/08/2010
7 – 30/09/2009 to 30/09/2010
8 – 31/10/2009 to 31/10/2010
9 – 30/11/2009 to 30/11/2010
10 – 31/12/2009 to 31/12/2010
11 – 31/01/2010 to 31/01/2011
12 – 28/02/2010 to 28/02/2011
So I've created a for loop to start with the latestDate - 1 year as the first element's end date, and a start date of the end date - 1 year, and then to incremement the loop's index by 1 month each iteration, as follows:
DateTime latestDate = new DateTime(2011, 2, 28);
int noOfYears = 1; // could vary
int shift = 1; // could vary
Dictionary<DateTime, DateTime> dateRanges = new Dictionary<DateTime, DateTime>();
for (var currentDate = latestDate.AddYears(noOfYears *= -1);
currentDate <= latestDate; currentDate.AddMonths(shift))
{
dateRanges.Add(currentDate.AddYears(noOfYears *= -1), currentDate);
}
I thought this would work smashingly but for some reason that I don't understand currentDate.AddYears(noOfYears *= -1) doesn't seem to be working, because the first entry in the dictionary is:
28/02/2011 , 28/02/2010 // the first date here should be minus 2 years!?
Where I would have expected
28/02/2009 , 28/02/2010 // the first in the list above
When the loop iterates for the second time the second entry to the dictionary is:
28/02/2009 , 28/02/2010 // this should be first in the dictionary!
Is there something obviously wrong with my logic that I'm not seeing?
You're constantly multiplying the noOfYears variable by -1, so it keeps switching between -1 and 1. Try using noOfYears * -1 instead (without the equals-sign).
currentDate.AddYears(noOfYears *= -1)
will flip the value of noOfYears back and forth from 1 to -1, to 1, to -1, ...
I'm not sure why you need to do this.
Also you are not changing the value of currentDate. Try this:
// note the new start date
DateTime latestDate = new DateTime(2011, 3, 1);
// could vary
int noOfYears = 1;
// could vary
int shift = 1;
var dateRanges = new Dictionary<DateTime, DateTime>();
for (var currentDate = latestDate.AddYears(noOfYears * -1);
currentDate <= latestDate; currentDate = currentDate.AddMonths(shift))
{
dateRanges.Add(currentDate.AddYears(noOfYears *= -1).AddDays(-1),
currentDate.AddDays(-1));
}

how to get datetime with +- 10 seconds Buffer?

i have:
jobElement.CreationDate = jobElement.CreationDate + TimeSpan.FromHours(24.0);
i would like to have not strictly 24 hours, but with +- 10 seconds Buffer. like 23.59.10 and 00.00.10
hot to reach that with c#?
This will generate CreationDate + 23:50 and CreationDate + 24:10 with equal probability:
Random random = new Random();
TimeSpan buffer = TimeSpan.FromSeconds(10);
TimeSpan span = TimeSpan.FromHours(24.0);
// 50% of the time do this
if(random.Next() % 2 == 0)
{
span += buffer;
}
// The rest of the time do this
else
{
span -= buffer;
}
jobElement.CreationDate = jobElement.CreationDate + span;
What do you need to do with that?
If you need to any comparison create custom class with overwritten equality operators.
I'm not 100% sure what you want here but I'll give it a shot
DateTime dt1 = DateTime.Now;
DateTime dt2 = DateTime.Now.AddDays(1).AddSeconds(8);
These two are now 24 hours and 8 seconds apart.
Then if you want to see if they are "almost" 24 hour appart, you can do something like this:
if( Math.Abs((dt1-dt2.AddDays(-1))) < 10 ){
//dt2 is 24 after dt1 +- 10 seconds
}else{
//they are not
}
First time (00.00.00) of current date -/+ 10 secs would be:
DateTime dateFrom = jobElement.CreationDate.Date.AddSeconds(-10);
DateTime dateTo = jobElement.CreationDate.Date.AddSeconds(10);
Is that it?
I'll add this variant. It's different from others because it isn't "second based" but "tick" based (the tick is the smallest time that a TimeSpan/DateTime can compute)
const int sec = 10; // +/- seconds of the "buffer"
const int ticksSec = 10000000; // There are 10000000 Ticks in a second
Random r = new Random();
int rng = r.Next(-sec * ticksSec, sec * ticksSec + 1); // r.Next is upper-bound exclusive
var ts = TimeSpan.FromHours(24) + TimeSpan.FromTicks(rng);
jobElement.CreationDate = jobElement.CreationDate + ts;
There are limits in the Random class (it can't generate a long, and generating a "constrained" long (a long with maxValue = x) is non-trivial based only on the Random class, so this will work for up to 3 minutes and something of "buffer" (214 seconds to be more exact).
If you want +/- 10 with all numbers between
Random r = new Random();
int x = r.Next(-10, 11);
var ts = TimeSpan.FromHours(24).Add(TimeSpan.FromSeconds((double)x));
jobElement.CreationDate = jobElement.CreationDate + ts;

Brain storm: How to arrange DateTime to particular interval frame?

Suppose i have a DateTime, e. g. 2010.12.27 12:33:58 and i have an interval frames of, suppose, 2 seconds, excluding the last border.
So, i have the following frames:
12:33:58(incl.)-12:34:00(excl.) - let it be interval 1
12:34:00(incl.)-12:34:02(excl.) - let it be interval 2
12:34:02(incl.)-12:34:04(excl.) - let it be interval 3
and so on.
I'm given a random DateTime value and i have to correlate that value according the above rules.
E. g. the value "12:33:58" falls into interval 1, "12:33:59" falls into interval 1, "12:34:00" falls into interval 2 and so on.
In code it should look like the following:
var dt = DateTime.Now;
DateTime intervalStart = apply_the_algorythm(dt);
It seems to be some simple arithmetic action(s) with float or something, any decisions are welcome!
If the interval is only second resolution and always divided 86400, then take the number of seconds that have passed today, divide it by the interval, round it to an integer value, multiply it, and add it back to today. Something like dateinquestion.Subtract(dateinquestion.Date).TotalSeconds, ((int)seconds/interval)*interval, dateinquestion.Date.AddSeconds(...)
If you want the range of all your intervals to span several days, possibly a long time, you might want to express your DateTime values in UNIX-seconds (the number of seconds since 1970-01-01). Then you just find out when your very first interval started, calculate how many seconds passed since then, and divide by two:
int secondsSinceFirstInterval = <currDate in UNIX time>
- <start of first interval in UNIX time>;
int intervalIndex = secondsSinceFirstInterval / 2;
Otherwise you're better off just counting from midnight.
Use TimeSpan.TotalSeconds and divide the result by the size of the interval.
const long intervalSize = 2;
DateTime start = new DateTime(2010, 12, 27, 12, 33, 58);
TimeSpan timeSpan = DateTime.Now - start;
long intervalInSeconds = (long)timeSpan.TotalSeconds;
long intervalNumber = 1 + intervalInSeconds / intervalSize;
DateTime start = new DateTime(2010, 12, 31, 12, 0, 0);
TimeSpan frameLength = new TimeSpan(0, 0, 3);
DateTime testTime = new DateTime(2010, 12, 31, 12, 0, 4);
int frameIndex = 0;
while (testTime >= start)
{
frameIndex++;
start = start.Add(frameLength);
}
Console.WriteLine(frameIndex);
dates = new List<DateTime>
{
DateTime.Now.AddHours(-1),
DateTime.Now.AddHours(-2),
DateTime.Now.AddHours(-3)
};
dates.Sort((x, y) => DateTime.Compare(x.Date, y.Date));
DateTime dateToCheck = DateTime.Now.AddMinutes(-120);
int place = apply_the_algorythm(dateToCheck);
Console.WriteLine(dateToCheck.ToString() + " is in interval :" +(place+1).ToString());
private int apply_the_algorythm(DateTime date)
{
if (dates.Count == 0)
return -1;
for (int i = 0; i < dates.Count; i++)
{
// check if the given date does not fall into any range.
if (date < dates[0] || date > dates[dates.Count - 1])
{
return -1;
}
else
{
if (date >= dates[i]
&& date < dates[i + 1])
return i;
}
}
return dates.Count-1;
}

Categories