DateTime difference in ticks does not match - c#

I have the following code:
var a = (DateTime.Now.Subtract(DateTime.Now.AddTicks(8))).Ticks;
var b = (DateTime.Now - DateTime.Now.AddTicks(8)).Ticks;
When I check the values I see that:
a = -78
b = -20
How come? Shouldn't both be -8?

You are depending on the system to do everything at the same time, which it cannot. Each time you get DateTime.Now, it has a different value.
A quick experiment reveals that capturing the value of DateTime.Now in the beginning, and then performing operations on that:
var d = DateTime.Now;
var a = (d.Subtract(d.AddTicks(8))).Ticks;
var b = (d - d.AddTicks(8)).Ticks;
Yields the result you were expecting. a and b have the same value, -8.

Those lines of code take time to execute. It's never good to use Now more than once in single method or operation. Or Today, for that matter.

Related

Get time difference between am and pm using time span

need to get time difference between 10 pm and 4 am. below is my code
_firstShiftStartTime = new TimeSpan(_oOrgShiftDetailDTO.StartTime.Value.Hour,_oOrgShiftDetailDTO.StartTime.Value.Minute, _oOrgShiftDetailDTO.StartTime.Value.Second);
_firstShiftEndTime = new TimeSpan(_ShiftDetailDTO.EndTime.Value.Hour, _ShiftDetailDTO.EndTime.Value.Minute, _ShiftDetailDTO.EndTime.Value.Second);
this returns two timespans 22.00.00 and 6.00.00. i need to get time difference between these two.
Using Stefano's Solution of using Subtract and then handling negative values
var difference = _firstShiftEndTime.Subtract(_firstShiftStartTime);
if (difference.Ticks < 0)
{
difference = new TimeSpan(TimeSpan.TicksPerDay - difference.Negate().Ticks);
}
Well i think you can do this
_firstShiftEndTime.Subtract(_firstShiftStartTime);
Like explained in the documentation
EDIT:
since you consider the negative values a not valid value I will do this
if (_firstShiftEndTime < _firstShiftStartTime)
_firstShiftEndTime.Add(TimeSpan.FromDays(1));
var myResult = _firstShiftEndTime.Subtract(_firstShiftStartTime);

TimeSpan.TotalMinutes without seconds

I am using the code
var minutesPassed = (DateTime.UtcNow - conversionsList.Last().DateStamp).TotalMinutes;
to calculate how much minutes passed between two dates. The result which I get looks like
254.54445556
I get minutes and seconds. How to get result which would contain only minutes like this
254
?
Just explicitly convert the result to int:
var minutesPassed = (int)(DateTime.UtcNow - conversionsList.Last().DateStamp).TotalMinutes;
Use Math.Floor() to convert 254.xxxx to 254:
var minutesPassed = Math.Floor((DateTime.UtcNow - conversionsList.Last().DateStamp).TotalMinutes);
You can just get the int part
int minutes = (int) (DateTime.UtcNow - conversionsList.Last().DateStamp).TotalMinutes;
this will get you the int part of the value.
EDIT: as far as rounding of value is considered. That is not true. Consider the following:
double d = 254.99999999999d;
int test = (int)d;
Here test will hold 254, not 255
The only problem with the explicit cast is OverFlowException

Calculate difference between 2 datetimes (Timespan + double)

I have a list that holds Datetimes.
To calculate the difference between 2 DateTime i use TimeSpan.
public static List<DateTime> list = new List<DateTime>();
TimeSpan ts = new TimeSpan();
double result = 0;
ts = DateTime.Now - list[list.Count-1];
result = ts.TotalSeconds;
When debugging this code both the DateTime.Now and the list[list.Count-1] have DateTimes where the DateTime.Now is off course higher then the value of the list.
But for some reason i keep getting 0 in the variable result, how come exactly?
Best regards, Pete
I just tried the following, works perfectly okay.
List<DateTime> list = new List<DateTime>();
list.Add(DateTime.Now.AddDays(-1));
list.Add(DateTime.Now);
list.Add(DateTime.Now.AddDays(1));
TimeSpan ts = new TimeSpan();
double result = 0;
ts = DateTime.Now - list[list.Count - 1];
result = ts.TotalSeconds;
Attached the debbuging picture:
Reasons for not working could be:
Either your list is not being populated
Or the value of ts.TotalSeconds is smaller than double range (Which can be practically not possible.)
First comment, you don't need = new TimeSpan(); - you're only discarding this anyway when you set ts again further down.
What line is your debugger on when you see the value of 0 for result? Have you stepped over the line where result is set? If you are on the line, then that line has not yet actually run...
Instead of using
ts = DateTime.Now - list[list.Count-1];
use
ts=DateTime.Now.Subtract(list[list.Count-1]
I think time difference is to small for seconds, it might be in mili seconds or even smaller. Try ticks like this.
result = ts.Ticks;
There is nothing wrong with the code you have posted (except I would suggest that you join declaration and initialization of your variables). I have to guess but perhaps you are "swallowing" exceptions and pass the empty list?
Then the line
ts = DateTime.Now - list[list.Count-1];
will throw an exception and result will retain it's value of 0.
list doesn't have any elements, so list.Count - 1 doesn't hit anything. also, there might not be an entire second to calculate. i added a time (using ticks) to subtract with. other than that, there's nothing wrong with what you have.
double result = 0;
List<DateTime> list = new List<DateTime>();
list.Add(new DateTime(123456));
TimeSpan ts = DateTime.Now - list[list.Count - 1];
result = ts.TotalSeconds;

Check difference in seconds between two times

Hi all I am currently working on a project where when a certain event happens details about the event including the time that the event occurred is added into a list array.
Once the method has finished I then pass on the list to another method that checks its values. Before I go through the loop I check the current time of my PC and I need to check whether the difference between the time saved in the list array and the current time is greater than 5 seconds.
How would I go about doing this.
Assuming dateTime1 and dateTime2 are DateTime values:
var diffInSeconds = (dateTime1 - dateTime2).TotalSeconds;
In your case, you 'd use DateTime.Now as one of the values and the time in the list as the other. Be careful of the order, as the result can be negative if dateTime1 is earlier than dateTime2.
DateTime has a Subtract method and an overloaded - operator for just such an occasion:
DateTime now = DateTime.UtcNow;
TimeSpan difference = now.Subtract(otherTime); // could also write `now - otherTime`
if (difference.TotalSeconds > 5) { ... }
This version always returns the number of seconds difference as a positive number (same result as #freedeveloper's solution):
var seconds = System.Math.Abs((date1 - date2).TotalSeconds);
I use this to avoid negative interval.
var seconds = (date1< date2)? (date2- date1).TotalSeconds: (date1 - date2).TotalSeconds;
The built-in DateTime.Subtract method can be used as follows
double diffInSeconds = dateTime1.Subtract(dateTime2).TotalSecond;
if (diffInSeconds > 5) { /* do stuff */ } ;

Find the closest time from a list of times

So, here's the scenario. I have a file with a created time, and I want to choose a time from a list of times that that file's created time is closest or equal too...what would be the best way to accomplish this?
var closestTime = listOfTimes.OrderBy(t => Math.Abs((t - fileCreateTime).Ticks))
.First();
If you don't want the performance overhead of the OrderBy call then you could use something like the MinBy extension method from MoreLINQ instead:
var closestTime = listOfTimes.MinBy(t => Math.Abs((t - fileCreateTime).Ticks));
Something like this:
DateTime fileDate, closestDate;
ArrayList theDates;
long min = long.MaxValue;
foreach (DateTime date in theDates)
if (Math.Abs(date.Ticks - fileDate.Ticks) < min)
{
min = Math.Abs(date.Ticks - fileDate.Ticks);
closestDate = date;
}
The accepted answer is completely wrong. What you want is something like this:
DateTime fileDate, closestDate;
List<DateTime> theDates;
fileDate = DateTime.Today; //set to the file date
theDates = new List<DateTime>(); //load the date list, obviously
long min = Math.Abs(fileDate.Ticks - theDates[0].Ticks);
long diff;
foreach (DateTime date in theDates)
{
diff = Math.Abs(fileDate.Ticks - date.Ticks);
if (diff < min)
{
min = diff;
closestDate = date;
}
}
var closestTime = (from t in listOfTimes
orderby (t - fileInfo.CreationTime).Duration()
select t).First();
How often will you be doing this with the same list of times? If you're only doing it once, the fastest way is probably to just scan through the list and keep track of the closest time you've seen yet. When/if you encounter a time that's closer, replace the "closest" with that closer time.
If you're doing it very often, you'd probably want to sort the list, then use a binary search.
get the difference of your file creatime and every time in your list and sort the absolute value of each time difference. the first one should be the answer you are looking for.
Use the minimum absolute time difference between the file time and the time in the list. You might get 2 entries being the same, and then you would need a different method to differ between these.
Not an answer, but a question regarding the various LINQ solutions proposed above. How efficient is LINQ? I have not written any "real" programs with LINQ yet, so I'm not sure on the performance.
In this example, the "listOfTimes" collection implies that we have already iterated over some file system based objects to gather the times. Would it have been more efficient to do the analysis during the iteration instead of later in LINQ? I recognize that these solutions may be more "elegant" or nicely abstract the "collection as database" idea, but I tend to choose efficiency (must be readable though) over elagance in my programming. Just wondering if the cost of LINQ might outweigh the elegance here?
var creationTimes = new [] {DateTime.Now.AddDays(-1), DateTime.Now.AddDays(-2)};
FileInfo fi = new FileInfo("C:/test.xml");
var closestTime = creationTimes
.OrderBy(c => Math.Abs(c.Subtract(fi.CreationTime).Days))
.First();
var min = listoftimes.Select(
x => new { diff = Math.Abs((x - timeoffile).Ticks), time = x}).
OrderBy(x => x.diff).
First().time;
Note: Assumes at least 1 entry in listoftimes.
I thought I would update this post to include a real world scenario. I wanted this sort of function as I have a blog showing news of the latest movie screenings.
However I don't want to list screening in the past (ie screening date past the current date) and as I wanted to show a record I needed some sort of ID passed to pick up the record.
I have left if simple so that you can follow the process and no doubt make it more efficient with LINQ et al.
First the model
public class LatestScreeeningsModel
{
public int Id { get; set; }
public DateTime Date { get; set; }
}
Then the code block you can call from your controller
private static LatestScreeeningsModel GetLatestScreening(IPublishedContent currentNode)
{
LatestScreeeningsModel latestScreening = new LatestScreeeningsModel();
DateTime fileDate;
// get a list of screenings that have not shown yet
var screenings = currentNode.AncestorsOrSelf("siteLanguage")
.FirstOrDefault().Descendants("screening")
.Select(x => new LatestScreeeningsModel() { Id = x.Id, Date = x.GetPropertyValue<DateTime>("date") })
.Where(x => x.Date > DateTime.Now).ToList();
fileDate = DateTime.Today;
long min = Math.Abs(fileDate.Ticks - screenings[0].Date.Ticks);
long diff;
foreach (var comingDate in screenings)
{
diff = Math.Abs(fileDate.Ticks - comingDate.Date.Ticks);
if (diff <= min)
{
min = diff;
latestScreening = comingDate;
}
}
return latestScreening;
}
I am using Umbraco to get the date items but it would work with any custom model, List et al.
Hope it helps
This is a generalized solution to the question, "Find the closest time from a list of times". This solution finds the closest time before and after a given search time.
//For finding the closest time in a list using a given search time...
var listOfTimes = new List<DateTime>();
listOfTimes.Add(DateTime.Parse("1/1/2000"));
listOfTimes.Add(DateTime.Parse("1/2/2000"));
listOfTimes.Add(DateTime.Parse("1/3/2000"));
listOfTimes.Add(DateTime.Parse("1/4/2000"));
listOfTimes.Add(DateTime.Parse("1/5/2000"));
var searchTime = DateTime.Parse("1/3/2000");
var closestBefore = listOfTimes.LastOrDefault(t => t < searchTime);
var closestAfter = listOfTimes.FirstOrDefault(t => t > searchTime);
Console.WriteLine(closestBefore);
Console.WriteLine(closestAfter);
/*
searchTime: 1/3/2000
before: 1/2/2000 12:00:00 AM
after: 1/4/2000 12:00:00 AM
searchTime: 1/1/1900 (edge case)
before: 1/1/0001 12:00:00 AM (DateTime.MinValue)
after: 1/1/2000 12:00:00 AM
searchTime: 1/1/2001 (edge case)
before: 1/5/2000 12:00:00 AM
after: 1/1/0001 12:00:00 AM (DateTime.MinValue)
*/

Categories