I need to compare two dates including the seconds. I searched the web and got two methods. One is import Microsoft.VisualBasic dll. The result is not same when it runs the same data. I think C# should do the same thing without import VisualBasic. Can someone point the way to me to made it work in C#?
Thanks in advance.
There is one using Microsoft.VisualBasic
if (Math.Abs(DateAndTime.DateDiff(DateInterval.Second,
Conversions.ToDate(colFilesFound[RuntimeHelpers.GetObjectValue(rw["file_path"])]),
Conversions.ToDate(rw["last_modified_timestamp"]),
FirstDayOfWeek.Sunday, FirstWeekOfYear.Jan1)) == 0L)
{
unchangedFileNum++;
Console.WriteLine("unchange");
}
else
{
modifiedFileNum++;
Console.WriteLine("change");
}
There is another method not using Visual.dll:
DateTime fileLastModifiedDate = Conversions.ToDate(colFilesFound[rw["file_path"]]);
DateTime dataLastModifiedDate = Conversions.ToDate(rw["last_modified_timestamp"]);
if (Math.Abs((fileLastModifiedDate - dataLastModifiedDate).TotalSeconds) == 0L)
{
Console.WriteLine("File Date: " + colFilesFound[rw["file_path"]] +
" <> Database Date: " + Conversions.ToString(rw["last_modified_timestamp"]));
unchangedFileNum++;
Console.WriteLine("unchange");
}
else
{
modifiedFileNum++;
Console.WriteLine("change");
}
The correct way to compare DateTimes in .NET is using the == operator or calling the DateTime.Compare() method:
DateTime fileLastModifiedDate = ...;
DateTime dataLastModifiedDate = ...;
if (fileLastModifiedDate == dataLastModifiedDate)
{
...
}
You need to take into account the precission. Sometimes, you cannot have enough precission to consider milliseconds. In this case you need to compare the dates without having into account the milliseconds:
public static bool IsSameDateWithoutMilliseconds(DateTime d1, DateTime d2)
{
return d1.Subtract(d2).TotalSeconds == 0;
}
Your problem is probably the milliseconds since those are probably not equal the way you check the DateTimes.
DateTime fileLastModifiedDate = Conversions.ToDate(colFilesFound[rw["file_path"]]);
DateTime dataLastModifiedDate = Conversions.ToDate(rw["last_modified_timestamp"]);
fileLastModifiedDate = fileLastModifiedDate.AddMilliseconds(-fileLastModifiedDate.Millisecond);
dataLastModifiedDate = dataLastModifiedDate.AddMilliseconds(-dataLastModifiedDate.Millisecond);
if (DateTime.Compare(fileLastModifiedDate, dataLastModifiedDate) == 0)
{
// dates are equal
}
else
{
// dates are not equal
}
Related
I have a 'simple' requirement - a quick check to see if an object is a valid DateTime and, if not, return a known default date.
There are a number of alternative solution:
Use the VB function directly by adding a reference to the VB library - simple but adding an additional library to the solution feels like bloat
Using DateTime.TryParse() - need to convert to object to string first and don't need the result
try catch block around Convert.ToDateTime() - feels clumsy but simple
They each have different pros and cons and they all have overheads - have a missed a simpler solution
Use the is operator:
Object foo = new DateTime();
if( foo is DateTime dt )
{
Console.WriteLine( "The date is: {0:yyyy-MM-dd}", dt );
return dt;
}
else
{
return someDefaultDate;
}
If you want the same behaviour as VB's IsDate function, add a call to DateTime.TryParse if the is DateTime check evaluates to false:
static DateTime GetDateOrDefault( Object o, DateTime defaultValue )
{
if( o is DateTime dt )
{
return dt;
}
else if( DateTime.TryParse( o?.ToString(), out dt ) )
{
return dt;
}
else
{
return defaultValue;
}
}
I am using the following code in order to substract a day of the DateTime until I am getting Monday:
DateTime currentWeek = new DateTime(beginDate.Year, beginDate.Month, beginDate.Day);
while (currentWeek.DayOfWeek.ToString() != "Monday")
{
currentWeek.AddDays(-1);
MessageBox.Show(currentWeek.Day.ToString());
MessageBox.Show(currentWeek.DayOfWeek.ToString());
}
beginDate is in the first run set to the current Date of DateTime.Now.
For me this loops forever, and the day of currentWeek always stays the same (29) even though I am substracting 1 everytime I am looping through.
I am already using another function that takes a DateTime and a bool Parameter, which does pretty much the same and works:
private void ErstenTagDerWocheAuswaehlen(DateTime date, bool anfangDerWoche = true)
{
string wochentagName;
int incrementor;
if(anfangDerWoche == true)
{
wochentagName = "Monday";
incrementor = -1;
}
else
{
wochentagName = "Friday";
incrementor = 1;
}
while(date.DayOfWeek.ToString() != wochentagName)
{
date = date.AddDays(incrementor);
}
}
Can someone explain to me why the upper code doesn't work whilst the lower one does?
You have to assign the resulting value, DateTime is immutable.
currentWeek = currentWeek.AddDays(-1);
About your 2nd question:
Use the enum for day of the week, do not try to convert a day of the week to a string for a comparison. The type is DayOfWeek.
Again, a DateTime is not mutable so you have to return a DateTime instance as you can't mutate the one that was passed in (without passing it as ref)
Code change
private DateTime ErstenTagDerWocheAuswaehlen(DateTime date, bool anfangDerWoche = true)
{
System.DayOfWeek wochentagName;
int incrementor;
if(anfangDerWoche == true)
{
wochentagName = System.DayOfWeek.Monday;
incrementor = -1;
}
else
{
wochentagName = System.DayOfWeek.Friday;
incrementor = 1;
}
while(date.DayOfWeek != wochentagName)
{
date = date.AddDays(incrementor);
}
return date;
}
DateTime is an immutable struct, so you need to store the value returned from AddDays():
var t2 = currentWeek.AddDays(-1);
Then use t2. The call to AddDays() doesn't actually change currentWeek.
As DateTime is immutable, when using the AddDays it returns a new DateTime structure with the new information and does not change the given one.
Method documentation states:
Returns a new System.DateTime that adds the specified number of days to the value of this instance.
You must assign it to a variable:
currentWeek = currentWeek.AddDays(-1);
This is my problem, i want to write a basic console application where i enter a date as input, if that date hasnt been entered the application then allow a time to enter a note, i.e for 07/08/2013 for time 5:00 - 7:00 pm enter text blah blah
then application will keep looping, if i enter the same date, i shouldnt be able to enter
the same times as above, but i should be able to enter 7:00 to 8 for example.
i was thinking of using dictionary :
Dictionary<string, Booking> BookingDict = new Dictionary<string, Booking>();
and adding date as id, but it seems only one element id can be entered uniquely
can some one please help
Do you have to use a list or dictionary? If you will not be searching in it alot and do not have a lot of elements, you are probably best going with a generic list: List<Booking>
Then you can use LINQ to search through the list to retrieve the bookings that you need.
i would recommend a dictionary with the key being the date and the value be an array of 24 booleans represent hours. that is only if the booking is for full hours. if it's by the minute then the array will be too big and then another option might be needed.
each cell in the array is true if the hour is booked, for example if <07/08/13, booked[2] = true> means that hour 2-3 is booked on 07/08/13 is booked.
when you get a new booking you'll need to check each hour between the two. if you got hours 4-10 you'll need to check the value in 4,5,6,7,8,9. not the best efficiency i think, but not that bad if no one is booking a full week or so.
sum it up my answer is using
Dictionary<string/DateTime, bool[24]> bookingTbl
create a key with two dateTime (the start and end dateTime). When you want to enter a new booking, check (with linq for instance) if there's a known end Datetime that is between your new start and end datetime and do the same with the known start datetime. If there is no overlap, add it.
Here's an example:
Dictionary<TwoUintsKeyInfo,object> test = new Dictionary<TwoUintsKeyInfo, object>();
test.Add(new TwoUintsKeyInfo { IdOne = 3, IdTwo = 9 }, new object());
test.Add(new TwoUintsKeyInfo { IdOne = 10, IdTwo = 15 }, new object());
uint newStartPoint1 = 16,newEndPoint1=20;
bool mayUse = (from result in test
let newStartPointIsBetweenStartAndEnd = newStartPoint1.Between(result.Key.IdOne,result.Key.IdTwo)
let newEndPointIsBetweenStartAndEnd = newEndPoint1.Between(result.Key.IdOne,result.Key.IdTwo)
let completeOverlap = result.Key.IdOne < newStartPoint1 && result.Key.IdTwo > newEndPoint1
let oldDateWithingNewRange = result.Key.IdOne.Between(newStartPoint1, newEndPoint1) || result.Key.IdTwo.Between(newStartPoint1, newEndPoint1)
let FoundOne = 1
where newStartPointIsBetweenStartAndEnd || newEndPointIsBetweenStartAndEnd || completeOverlap || oldDateWithingNewRange
select FoundOne).Sum()==0;
using:
public static class LinqExtentions
{
/// <summary>
/// Note: For the compare parameters; First the low, than the High
/// </summary>
/// <returns>Bool</returns>
public static bool Between<T1, T2, T3>(this T1 actual, T2 lowest, T3 highest)
where T1 : IComparable
where T2 : IConvertible
where T3 : IConvertible
{
return actual.CompareTo(lowest.ToType(typeof(T1), null)) >= 0 &&
actual.CompareTo(highest.ToType(typeof(T1), null)) <= 0;
}
}
public class TwoUintsKeyInfo
{
public uint IdOne { get; set; }
public uint IdTwo { get; set; }
public class EqualityComparerTwoUintsKeyInfo : IEqualityComparer<TwoUintsKeyInfo>
{
public bool Equals(TwoUintsKeyInfo x, TwoUintsKeyInfo y)
{
return x.IdOne == y.IdOne &&
x.IdTwo == y.IdTwo;
}
public int GetHashCode(TwoUintsKeyInfo x)
{
return (Math.Pow(x.IdOne, Math.E) + Math.Pow(x.IdTwo, Math.PI)).GetHashCode();
}
}
}
I tested it, seems to be working.
Good luck!
I was wondering if there is any neat way to check is data is in allowed range. I mean in c# we can represent data from 0001-01-01 to (I think) 9999-01-01. However if we try to do something like that
DateTime result = DateTime.Parse("0001-01-01").Subtract(TimeSpan.FromDays(1))
I get an exception. Is there any neat way to check is it is possible to do DateTime operations (addition subtraction etc)
Just use the comparison operators (>, <, >=, <=, == and !=), as they are implemented in DateTime.
Example:
DateTime lowerAllowedDate = new DateTime(1,1,1); // 01/01/0001
DateTime upperAllowedDate = new DateTime(3000, 12, 31) // 31/12/3000
DateTime now = DateTime.Now
if (lowerAllowedDate <= now && now < upperAllowedDate)
{
//Do something with the date at is in within range
}
Consider these extension methods.
public static class ValidatedDateTimeOperations
{
public static bool TrySubtract (this DateTime dateTime, TimeSpan span, out DateTime result)
{
if (span < TimeSpan.Zero)
return TryAdd (dateTime, -span, out result);
if (dateTime.Ticks >= span.Ticks)
{
result = dateTime - span;
return true;
}
result = DateTime.MinValue;
return false;
}
public static bool TryAdd (this DateTime dateTime, TimeSpan span, out DateTime result)
{
if (span < TimeSpan.Zero)
return TrySubtract (dateTime, -span, out result);
if (DateTime.MaxValue.Ticks - span.Ticks >= dateTime.Ticks)
{
result = dateTime + span;
return true;
}
result = DateTime.MaxValue;
return false;
}
}
The can be called like this:
DateTime result;
if (DateTime.MinValue.TrySubtract (TimeSpan.FromDays(1), out result)
{
// Subtraction succeeded.
}
Checking for an overflow in a given operation beforehand is cumbersome and I'm not really sure it's really worth it against simply handling the exception.
You could for example do the following when subtracting:
DateTime date;
TimeSpan subtractSpan;
if ((date - DateTime.MinValue) < subtractSpan)
{
//out of range exception: date - subtractSpan
}
Worth it? Your call.
Take a look at the DateTime structure documentation in MSDN.
In particular, you can take a look at:
TryParse and TryParseExact
The comparison operators
MinValue and MaxValue
You can also put try..catch (ArgumentOutOfRangeException) around the DateTime values you are trying to use.
However, if you are consistently (or ever?) running into this kind of exception, I'd take a closer look at your design. Unless you are doing some serious date-crunching, I don't know of any instance where I would be bumping into the min and max values.
I'm reading Fowler Clean Code book and I think that my code is a little messy, I want some suggestions:
I have a simple business requirement that is return the date of new execution of my Thread.
I've two class fields: _hour and _day.
If actual day is higher than my _day field I must return true, so I'll add a month to "executionDate"
If the day is the same, but the actual hour is higher than _hour I should return true too.
So I did this simple method:
private bool ScheduledDateGreaterThanCurrentDate (DateTime dataAtual) {
if (dateActual.Day > _day) {
return true;
}
if (dateActual.Day == _day && dateActual.Hour > _hour) {
return true;
}
if (dateActual.Day == _day && dateActual.Hour == _hour)
if (dateActual.Minute>0 || dateActual.Second>0)
return true;
return false;
}
I'm programming with TDD, so I know that the return is correct, but this is bad maintain code right?
var compareDate = new DateTime(
dateActual.Year,
dateActual.Month,
_day,
_hour,
0,
0);
return dateActual> compareDate;
DateTime objects can be compared against one another.
For example, say my class has this field:
// Using DateTime.Today as an example
DateTime _date = DateTime.Today;
I can then do this instead of a method call
if (dataAtual > _date) {
// logic here
}
If you use the datetime object in .NET it will do all this logic for you.