Home:ALL Converter>DateTime Comparison Precision

DateTime Comparison Precision

Ask Time:2010-06-02T18:22:32         Author:akif

Json Formatter

I'm doing DateTime comparison but I don't want to do comparison at second, millisecond and ticks level. What's the most elegant way?

If I simply compare the DateTime, then they are seldom equal due to ticks differences.

Author:akif,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/2956748/datetime-comparison-precision
ChrisF :

One approach could be to create two new DateTimes from your values you want to compare, but ignore anything from the seconds on down and then compare those:\n\nDateTime compare1 = new DateTime(year1, month1, day1, hour1, minute1, 0);\nDateTime compare2 = new DateTime(year2, month2, day2, hour2, minute2, 0);\n\nint result = DateTime.Compare(compare1, compare2);\n\n\nI'd be the first to admit it's not elegant, but it solves the problem.",
2010-06-02T10:31:25
hoang :

Using a TimeSpan you get all the granularity you want :\n\nDateTime dt1, dt2;\ndouble d = (dt2 - dt1).TotalDays;\ndouble h = (dt2 - dt1).TotalHours;\ndouble m = (dt2 - dt1).TotalMinutes;\ndouble s = (dt2 - dt1).TotalSeconds;\ndouble ms = (dt2 - dt1).TotalMilliseconds;\ndouble ticks = (dt2 - dt1).Ticks;\n",
2010-06-02T10:50:24
ALZ :

public class DateTimeComparer : Comparer<DateTime>\n{\n private Prescision _Prescision;\n\n public enum Prescision : sbyte\n {\n Millisecons,\n Seconds,\n Minutes,\n Hour,\n Day,\n Month,\n Year,\n Ticks\n }\n\n Func<DateTime, DateTime>[] actions = new Func<DateTime, DateTime>[]\n {\n (x) => { return x.AddMilliseconds(-x.Millisecond);},\n (x) => { return x.AddSeconds(-x.Second);},\n (x) => { return x.AddMinutes(-x.Minute);},\n (x) => { return x.AddHours(-x.Hour);},\n (x) => { return x.AddDays(-x.Day);},\n (x) => { return x.AddMonths(-x.Month);},\n };\n\n public DateTimeComparer(Prescision prescision = Prescision.Ticks)\n {\n _Prescision = prescision;\n }\n\n public override int Compare(DateTime x, DateTime y)\n {\n if (_Prescision == Prescision.Ticks)\n {\n return x.CompareTo(y);\n }\n\n for (sbyte i = (sbyte)(_Prescision - 1); i >= 0; i--)\n {\n x = actions[i](x);\n y = actions[i](y);\n }\n\n return x.CompareTo(y);\n }\n}\n\n\nUsage example:\n\nnew DateTimeComparer(DateTimeComparer.Prescision.Day).Compare(Date1, Date2)\n",
2015-10-23T09:57:20
Oliver :

How about this ComparerClass?\n\npublic class DateTimeComparer : Comparer<DateTime>\n{\n private string _Format;\n\n public DateTimeComparer(string format)\n {\n _Format = format;\n }\n\n public override int Compare(DateTime x, DateTime y)\n {\n if(x.ToString(_Format) == y.ToString(_Format))\n return 0;\n\n return x.CompareTo(y);\n }\n}\n\n\nThis can be used by\n\nList.Sort(new DateTimeComparer(\"hh:mm\"));\n",
2010-06-02T10:45:50
The King :

You can convert them to String format and compare the string with each other. \n\nThis also gives freedom to choose your comparison parameters, like only the time without the date, etc.\n\nif (String.Format(\"{0:ddMMyyyyHHmmss}\", date1) == String.Format(\"{0:ddMMyyyyHHmmss}\", date2))\n{\n // success\n}\n",
2010-06-02T10:31:40
Sprague :

I've written this to help myself:\n\n internal class ImpreciseCompareDate : IComparer<DateTime>\n{\n private readonly double _Tolerance;\n\n public ImpreciseCompareDate(double MillisecondsTolerance)\n {\n _Tolerance = MillisecondsTolerance;\n }\n\n public int Compare(DateTime x, DateTime y)\n {\n return Math.Abs((x - y).TotalMilliseconds) < _Tolerance ? 0 : x.CompareTo(y);\n }\n}\n\n\nTolerance can be set to (10d/3d) to account for SQL servers 1/300th of a ms. If tolerance is exceeded, delegate to default comparer.",
2015-01-16T09:54:33
Bart Verkoeijen :

Another way is to convert first by processing on ticks level with a simple (non-rounding) calculation:\n\nvar now = DateTime.UtcNow;\n// 636340541021531973, 2017-06-26T06:08:22.1531973Z\n\nvar millisecondsPrecision = new DateTime(now.Ticks / 10000 * 10000, now.Kind);\n// 636340541021530000, 2017-06-26T06:08:22.1530000Z\n\nvar secondsPrecision = new DateTime(now.Ticks / 10000000 * 10000000, now.Kind);\n// 636340541020000000, 2017-06-26T06:08:22.0000000Z\n\nvar minutePrecision = new DateTime(now.Ticks / (10000000*60) * (10000000*60), now.Kind);\n// 636340541000000000, 2017-06-26T06:08:00.0000000Z\n",
2017-06-26T06:24:52
Szybki :

@ALZ's solution looks nice but it's too complicated and has a bug.\nSo I decided to combine it with @ChrisF's solution.\n\n public class DateTimeComparer : Comparer<DateTime>\n {\n public enum Precision\n {\n Years = 0,\n Months,\n Days,\n Hours,\n Minutes,\n Seconds,\n Millisecons,\n Ticks\n }\n\n private Precision _precision;\n\n public DateTimeComparer(Precision precision = Precision.Ticks)\n {\n _precision = precision;\n }\n\n public override int Compare(DateTime x, DateTime y)\n {\n if (_precision == Precision.Ticks)\n {\n return x.CompareTo(y);\n }\n\n var xx = AssembleValue(x, _precision);\n var yy = AssembleValue(y, _precision);\n\n return xx.CompareTo(yy);\n }\n\n private static DateTime AssembleValue(DateTime input, Precision precision)\n {\n var p = (int)precision;\n var i = 1;\n return new DateTime(input.Year,\n p >= i++ ? input.Month : 1,\n p >= i++ ? input.Day : 1,\n p >= i++ ? input.Hour : 0,\n p >= i++ ? input.Minute : 0,\n p >= i++ ? input.Second : 0,\n p >= i++ ? input.Millisecond : 0);\n }\n }\n",
2017-12-30T18:53:28
GeorgiG :

Very simple solution from my own code:\n\nTimeSpan timeDifference = presentLastSavedDate.Subtract(previousLastSavedDate);\nif (timeDifference.Seconds > 0)\n{\n return Content(HttpStatusCode.Conflict, ALREADY_CHANGED_MSG);\n}\n",
2018-10-02T11:23:38
James Barrass :

What about using a timespan.\n\nif (Math.Truncate((A - B).TotalMinutes) == 0)\n{\n //There is less than one minute between them\n}\n\n\nProbably not the most elegant way, but it allows for cases which are one second apart and yet have different days/hours/minutes parts such as going over midnight.\n\nEdit: it occured to me that the truncate is unecessary...\n\nif (Math.Abs((A - B).TotalMinutes) < 1)\n{\n //There is less than one minute between them\n}\n\n\nPersonally I think this is more elegant...",
2010-06-02T10:45:14
yy