I have one strange problem that I'm trying to understand.
In my controller there are 2 DateTime objects that I want to compare.
You can see screenshot from a debugger in my controller. I create one date time and get another one from a model.
At this step you can see in debugger that date1 differs from date2 for 2 seconds
At the next step I remove 2 seconds from date2 and compare it with date1
Cay you explain me why is it false? In debugger I see both of them the same.
Solution: As it was told in the comment, the idea was to check also milliseconds, I completely forgot about it!
As you can see in the reference source, a comparison of two DateTime objects is done through their respective ticks, which is their internal representation.
Comparing two DateTime values is a bit like comparing two floating point values: the difference might be so small that you're likely to not get what you want. Perhaps you need to check if they're on the same date, or if one falls in a specific range of the other.
The way to compare Datetimes is done by comparing their Tick property:
bool r = date1.Ticks == date2.Ticks;
Try this.
You can use DateTime.Compare to see which time is earlier/later. Also like people have already mentioned difference could be in e.g. milliseconds
How to use DateTime.Compare:
https://msdn.microsoft.com/en-us/library/system.datetime.compare(v=vs.110).aspx
Related
Currently I am using DateTime.Now.ToLongDateString() to set a date property, although I would like to be more detailed in the date. The purpose is to perform a sort based on the date of an item, and this currently will give a date in the format Thursday, July 4, 2013. If several items have this same date property on the same day, the sort is not performed. Is there a function of DateTime.Now that will allow a date property with seconds?
To note, the day and year must still be included because the sort may happen over several days, in several years, but there may also be several instances of the item on the same day. What recommendation would you suggest, or is there a better way to go about this? Also, this must work for any culture and any time zone.
EDIT
In my MainPage I am populating a ListBox named Recent with a collection of pictures. From my Settings page, a user may choose ascending or descending sort order, and based on this the collection must be sorted accordingly before populating the listbox.
MainPage.xaml.cs
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ObservableCollection<Selfie.Models.Picture> listItems = new ObservableCollection<Selfie.Models.Picture>(PictureRepository.Instance.Pictures);
if (Settings.AscendingSort.Value)
{
listItems.OrderBy(x => x.DateTaken);
Recent.ItemsSource = listItems;
}
else
{
listItems.OrderByDescending(x => x.DateTaken);
Recent.ItemsSource = listItems;
}
}
I have a class that Serializes and Deserializes the DateTime as a property of the Picture, which is applied to DateTaken, which I am trying to sort by.
EDIT 2
Okay,
you need to use the result of the OrderByDescending function.
// listItems remains unaffected.
var sorted = listItems.OrderByDescending();
Many functions, especially extensions that act upon structures with a level of immutablity, do not effect the source. The pure function should be used in a "fluent" style. The return value needs to be assinged to be utilized.
So, you need to do,
Recent.ItemsSource = listItems.OrderBy(x => x.DateTaken).ToList();
Its worth considering a tool like Resahrper to catch issues like this. They are common with the DateTime Add functions.
EDIT
Because you are working in a multi cultural situation, ensure that all your dates are instantiated and stored with a UTC kind, this is going to help you massively. Even if working in a single time-zone but sorting across Day light Saving Time boundries.
Instead of DateTime.Now use DateTime.UtcNow and leave all values as UTC DateTimes until they are exported or presented on the GUI.
This way you will be comparing apples with apples, and your sorting will work as expected and your data will be much easier to debug.
If you start to do anything sophisticated, you're going to find the cracks in .Nets DateTime implementation. It's considering using Jon Skeet and other's work on noda time which should overcome many pit falls.
This will not work across time zones, calendars or just Day light Saving
If you did need a sortable String for some reason, use DateTime.Now.ToString("o"); this makes a string with in the Round-trip format,
yyyy-MM-ddTHH:mm:ss.fffffff
which is nicely sortable, including a fractional portion. Assuming all the values come from the same timezone and calendar.
Just sort by DateTime.Now directly, without converting to a string. If you store the DateTime directly in your property, this will not be an issue.
The DateTime type supports dates and times down to the tick.
You can also format the date however you choose for display, but it is typically better to store, internally, the actual DateTime.
Just use the DateTime object directly. It will give you the day, month, year, hour, mins, seconds which is enough to do your sort.
For example: -
var foo = collection.OrderBy(d => d.Date);
The DateTime.Now.ToString() method will give you a string formatted with everything included.
But as #SimonBelanger pointed out, you should probably sort directly on the DateTime, not on the string representation.
If you need to serialize the date, as opposed to just sorting on the DateTime object, you can try converting it to unix time (the number of milliseconds since the start of the Unix Epoch).
stackoverflow.com/questions/9814060/...
Since it's just a long, you can sort it easily as well as storing it in a string or long or whatever.
If you can sort by the DateTime directly as Reed stated do that. However, if you can't, you'll want to string it out a very specific way. Maybe something like this:
date.ToString("YYYYMMddHHmmss")
because to sort dates in a character fashion you need to sort the parts of the date in the right order.
You can use DateTime.Now.ToString("YYYYMMddHHmmss") or DateTime.Now.Ticks
If you Add this piece of code DateTime.Now.ToString(); it will print 7/4/2013 10:05:18 PM ,
If you Add string time = DateTime.Now.ToString("hh-mm-ss"); it will print(10-07-36).
In the tostring method you can format the date based on your requirement.
I am trying to calculate if the given specified date is at least six months old. I am doing this:
if(DateTime.Now.AddMonths(-6)>date)
{
//Do something
}
Is this correct?
Some people say that this approach is wrong and will not give accurate results. Is the above is correct?
"6 months" is not a precise amount of time. It depends on the length of the months. In particular, you may well get different results from your calculation compared with date.AddMonths(6) < DateTime.Now. (Consider adding 6 months from August 30th vs taking away 6 months from February 28th... You may be okay, but you need to think about this carefully.)
You need to consider a few things carefully:
You're currently using DateTime.Now instead of DateTime.Today; how do you want the current time of day to affect things?
Is the "kind" of date UTC, unspecified or local? It makes a difference - DateTime is confusing, unfortunately.
How do you want to handle situations like the ones in the first paragraph?
Ultimately, if people are telling you it will not give accurate results, you should ask them for specific examples - you need to get a wealth of input data and desired results, add automated tests for them, and get them to pass. Then if anyone claims your code isn't working correctly, you should be able to challenge them to create another test case which fails, and justify their decision.
If you are only concerned about the date and not the time, use DateTime.Now.Date instead. Apart from that, I do not see any problems with the code you already have.
I'm using free-form dates as part of a search syntax. I need to parse dates from strings, but only preserve the parts of the date that are actually specified. For instance, "november 1, 2010" is a specific date, but "november 2010" is the range of dates "november 1, 2010" to "november 30, 2010".
Unfortunately, DateTime.Parse and friends parse these dates to the same DateTime:
DateTime.Parse("November 1, 2010") // == {11/1/2010 12:00:00 AM}
DateTime.Parse("November, 2010") // == {11/1/2010 12:00:00 AM}
I need to know which parts of the DateTime were actually parsed and which were guessed by the parser. Essentially, I need DateTime.Parse("November, 2010") == {11/-1/2010 -1:-1:-1}; I can then see that the day portion is missing and calculate the range of dates covering the whole month.
(Internally, C# has the DateTimeParse and DateTimeResult classes that parse the date and preserve exactly the information I need, but by the time the date gets back to the public interfaces it's been stripped off. I'd rather avoid reflecting into these classes, unless that's really the only route.)
Is there some way to get DateTime.Parse to tell me which format it used to parse the date? Or can the returned DateTime have placeholders for unspecified parts? I'm also open to using another date parser, but I'd like it to be as reliable and locale-flexible as the internal one. Thanks in advance.
EDIT: I've also tried ParseExact, but enumerating all of the formats that Parse can handle seems nearly impossible. Parse actually accepts more formats than are returned by DateTimeFormatInfo.GetAllDateTimePatterns, which is about as canonical a source as I can find.
You could try using TryParseExact(), which will fail if the data string isn't in the exact format specified. Try a bunch of different combinations, and when one succeeds you know the format the date was in, and thus you know the parts of the date that weren't there and for which the parser filled in defaults. The downside is you have to anticipate how the user will want to enter dates, so you can expect exactly that.
You could also use a Regex to digest the date string yourself. Again, you'll need different regexes (or a REALLY complex single one), but it is certainly possible to pull the string apart this way as well; then you know what you actually have.
Parse parses a whole lot of stuff that no sane person would enter as a date, like "January / 2010 - 21 12: 00 :2". I think you'll have to write your own date parser if you want to know what exactly the user entered.
Personally I would do it like KeithS suggested: Parse the string with Parse and only call your own parse function if there's a 0 in one of the fields of the DateTime object. There are not that that possibilities you need to check for, because if the day is 0, the time will be 0, too. So start checking year, month, day, etc..
Or simply instruct the user to use specific formats you recognize.
Essentially, I need
DateTime.Parse("November, 2010") ==
{11/-1/2010 -1:-1:-1}; I can then see
that the day portion is missing and
calculate the range of dates covering
the whole month.
What you want is an illegal DateTime because you cannot have a negative hours/seconds/minute/day values. If you want to return something else other then a legal DateTime you have to write your own method which does NOT return a DateTime.
Is there some way to get
DateTime.Parse to tell me which format
it used to parse the date? Or can the
returned DateTime have placeholders
for unspecified parts? I'm also open
to using another date parser, but I'd
like it to be as reliable and
locale-flexible as the internal one.
Take a look here http://msdn.microsoft.com/en-us/library/w2sa9yss.aspx
You are going to have to manually keep track of what is entered to do this task. The only solution is to make sure the input is in the correct format.
I used this method that goes back to the original string in order to check for existence of the day and the year:
For days, the original string must contain a 1 as integer if the day was specified. So, split the string and look for a 1. The only exception occurs when the month is January (#1 month), so you should check for two 1s or a 1 and "January" or "Jan" in the original string.
For years, the original string must contain a number that can be a year (say, from 1900 to 2100). Other possibilities may be the use of an apostrophe, or things like 02-10-16, which you can recognize by the fact that there are exactly three numbers.
I know that this is pretty heuristic, but it's a fast and simple solution that works in most cases. I coded this algorithm in C# in the DateFinder.DayExists() and DateFinder.YearExists() methods in the sharp-datefinder library.
I have been working on a .NET/C# form that contains two time fields that are built out of dropdowns. Time A is made up of two dropdowns for Hours and Minutes and Time B is made up of two drop downs for hours and minutes too. I need to compare the two in order to ensure that Time A is always greater than B.
I could just use a CompareValidator to check the hours, that works BUT doesn't take into account the minutes. So lets assume the following scenarios:
A = 11:00 B = 12:15 is fine my validation accepts this as it should do
A = 11:15 B = 11:00 is accepted because the hours are equal but otherwise shouldn't pass as the minutes aren't validated
How would you ensure B is always equal to or greater than A where dropdowns are used? I would if I could change this but not permitted to do so.
I believe the best way is to have a method which encapsulates the comparison and internally is creating two DateTime values, a and b, and comparing them.
Such method will initialize a and b with the values of the UI.
Why not add a CustomValidator and write a little javascript function to compare the dates?
Working on an application where we would like the user to be able to enter incomplete dates.
In some cases there will only be a year - say 1854, or there might be a year and a month, for example March 1983, or there may be a complete date - 11 June 2001.
We'd like a single 'date' attribute/column - and to be able to sort on date.
Any suggestions?
Store the date as an integer -- yyyymmdd.
You can then zero out any month or day component that has not been entered
Year only: 1954 => 19540000
Year & Month: April 2004 => 20040400
January 1st, 2011 => 20110101
Of course I am assuming that you do not need to store any time of day information.
You could then create a struct to encapsulate this logic with useful properties indicating which level of granularity has been set, the relevant System.DateTime, etc
Edit: sorting should then work nicely as well
I can't think of a good way of using a single date field.
A problem you would get if you used January as the default month and 1 as the default day like others have suggested is, what happens when they actually pick January? How would you track if it's a selected January or a defaulted January.
I think you're going to have to store a mask along with the date.
You would only need a bit per part of the date, which would only be 6 bits of data.
M|D|Y|H|Min|S
Month Only 1|0|0|0|0|0 = 32
Year Only 0|0|1|0|0|0 = 8
Month+Year 1|0|1|0|0|0 = 40
AllButMinSec 1|1|1|1|0|0 = 60
You could put this into a Flag Enum to make it easier to use in code.
Well, you could do it via a single column and field that says 'IsDateComplete'.
If you only have the date field, then you'll need to encode the "incompleteness" in the date format itself, such that if the date is, say, < 1900, it's considered "Incomplete".
Personally, I'd go with an field on the side, that marks it as such. Easier to follow, easier to make decisions on, and allows for any dates.
It goes without saying, perhaps, that you can just create a date from DateTime.MinValue and then set what you "know".
Of course, my approach doesn't allow you to "know" what you don't know. (That is, you don't know that they've set the month). You could perhaps use a date-format specifier to mask that, and store it alongside as well, but it's potentially getting cumbersome.
Anyway, some thoughts for you.
One option is to use January as the default month, 1 as the default day, and 1900 or something like that as the default year. Incomplete dates would get padded out with those defaults, and incomplete dates would sort before complete ones in the same year.
Another, slightly more complex option is to use -1 for default day and year, and -1, 'NoMonth', or some such as the default month. Pad incomplete dates as above. This may make sorting a little hard depending on how you do it, but it gives you a way of telling which parts of the date are valid.
I know you'd rather have 1 column but, Instead of a single column one can always have a separate column for day, month and year. Not very difficult to do queries against, and it allways any of the components to be null.
Smehow encoding these states in the datetime itself will be harder to query.
What I did when last solving this problem, was to create a custom date type that kept track of which date parts was actually set and provided conversions to and from a DateTime. For storing in database i used one date field and then one boolean/bit to keep track of which date components that were actually set by the user.