2

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.

Matthew
  • 3,976
  • 15
  • 66
  • 130
  • 5
    Any reasons why you use a string for that and not manipulate `DateTime` directly ? – Simon Belanger Jul 04 '13 at 16:28
  • If you get a string that includes seconds, what will happen to values on the same second? What about dates from different time zones? – Jodrell Jul 04 '13 at 16:56
  • I have changed from saving my DateTaken property from type string to type DateTime. However, I do wish to not include time zones, as a user may be in different time zones and I would like to perform the sort strictly based on the DateTime property. – Matthew Jul 04 '13 at 16:59
  • @Matthew You can always store the DateTime as a UTC DateTime. See http://msdn.microsoft.com/en-us/library/system.datetime.touniversaltime.aspx – Reed Copsey Jul 04 '13 at 17:00
  • What about http://msdn.microsoft.com/en-us/library/az4se3k1.aspx#Roundtrip using the `u` format specifier? How is this different? – Matthew Jul 04 '13 at 17:09

8 Answers8

1

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.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • +1 as this would be the most ideal solution since the type already supports it. Nice job reading between the lines! – Mike Perrenoud Jul 04 '13 at 16:34
  • I can't think of a realistic atypical scenario but I guess some people "know better". `DateTime`s `IComparable` implementation must surely surpass anything based on alphanumeric coincidence. – Jodrell Jul 04 '13 at 16:58
1

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.

Community
  • 1
  • 1
Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • What exactly does the `"o"` do in this instance? I do need a sortable string, because I am sorting items in a collection based on the DateTime parameter which I save as a string in IsolatedStorage. Just using `DateTime.Now.ToString()` gives a string, but the sort still does not work. – Matthew Jul 04 '13 at 16:38
  • @Matthew, seek and ye shall find http://msdn.microsoft.com/en-us/library/az4se3k1.aspx#Roundtrip – Jodrell Jul 04 '13 at 16:39
  • 1
    @Matthew, as I say in the start of my answer, it more effienct and simpler to sort directly on `DateTime` structs directly rather than cast to string and relying on a alphanumeric comparison. The `DateTime` implmentation of `IComparable` is suitably specialzed. – Jodrell Jul 04 '13 at 16:44
  • I did convert from saving my DateTime from string to the DateTime format, although performing `listItems.OrderByDescending(x => x.DateTaken);` on the DateTaken property (of type DateTime) does not change the sort order? – Matthew Jul 04 '13 at 16:56
  • What values are out of sequence? you should amend the question so we all get to help. – Jodrell Jul 04 '13 at 17:01
  • THanks, I did in fact change `DateTime.Now` to `DateTime.UtcNow`, my issue still arises with my sort method though. I edited my original question above to reflect this. For some reason, the sort is not working although during debugging I see no errors, its just that the sort never occurs? – Matthew Jul 04 '13 at 17:16
  • @Matthew updated again, I think this nails your underlying problem. – Jodrell Jul 04 '13 at 17:26
  • Yes, actually I just happened to solve this right before I saw your answer, except I got away without using the `.ToList()` function at the end. Much appreciated, I chose your answer as the correct one. – Matthew Jul 04 '13 at 17:30
1

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);
DGibbs
  • 14,316
  • 7
  • 44
  • 83
  • 1
    @ReedCopsey Pedantic? You know exactly what I meant. Edited anyway. – DGibbs Jul 05 '13 at 08:12
  • I didn't downvote you - but did mention it, since it's actually a fairly common issue on forums, etc - newer users often expect there to be a "date only" type ;) – Reed Copsey Jul 05 '13 at 16:15
0

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.

Mike Dinescu
  • 54,171
  • 16
  • 118
  • 151
0

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.

Community
  • 1
  • 1
welegan
  • 3,013
  • 3
  • 15
  • 20
0

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.

Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
0

You can use DateTime.Now.ToString("YYYYMMddHHmmss") or DateTime.Now.Ticks

Toto
  • 7,491
  • 18
  • 50
  • 72
0

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.

Vignesh
  • 1,458
  • 12
  • 31
  • 59