Link to home
Start Free TrialLog in
Avatar of programmerist 1983
programmerist 1983Flag for Türkiye

asked on

How can i use linq for parsing string datetime to real datetime?

Hi; my ExpiryDate is "10/31/2015 12:00:00 AM" means MM/dd/YYYY hh:mm:ss AM but it is string from SAP. How can i convert it MM/dd/YYYY
below codes not working.error : "String was not recognized as a valid DateTime."  How can i do that by using linq?

    var query = deliveriesItemsbypaging.Select(tb => tb.ExpiryDate)
                  .AsEnumerable() // Do the rest of the processing locally
                  .Select(x => DateTime.ParseExact(x.Split(new char[0])[0], "MM/dd/yyyy", CultureInfo.InvariantCulture));

this blog  code is working :
 var r =   DateTime.ParseExact("10/31/2015 12:00:00 AM".Split(new char[0])[0], "MM/dd/yyyy", CultureInfo.InvariantCulture);
Avatar of Shaun Vermaak
Shaun Vermaak
Flag of Australia image

Change model or get the value as string with Linq and convert to Date.
Do not think you can do it directly via Linq
Avatar of programmerist 1983

ASKER

Generally problem is : "7/31/2014 12:00:00 AM" when it happened. but if date is : "07/31/2014 12:00:00 AM", it is working good.
Not Working below Code:
 var list = new List<MyClass>() {new MyClass() { Id=1, Name="test", ExpiryDate = "7/31/2014 12:00:00 AM" },
                                            new MyClass() { Id=1, Name="test", ExpiryDate = "10/31/2015 12:00:00 AM" }};


            var query = list.Select(tb => tb.ExpiryDate)
                .AsEnumerable() // Do the rest of the processing locally
                .Select(x => DateTime.ParseExact(x.Split(new char[0])[0], "MM/dd/yyyy", CultureInfo.InvariantCulture));

BUT it is working below code:

 var list = new List<MyClass>() {new MyClass() { Id=1, Name="test", ExpiryDate = "07/31/2014 12:00:00 AM" },
                                            new MyClass() { Id=1, Name="test", ExpiryDate = "10/31/2015 12:00:00 AM" }};


            var query = list.Select(tb => tb.ExpiryDate)
                .AsEnumerable() // Do the rest of the processing locally
                .Select(x => DateTime.ParseExact(x.Split(new char[0])[0], "MM/dd/yyyy", CultureInfo.InvariantCulture));
The following doesn't compile (because you seem to select a DateTime in your LINQ processing)
            DateTime x = DateTime.Now;
            var r = DateTime.ParseExact(x.Split(new char[0])[0], "MM/dd/yyyy", CultureInfo.InvariantCulture);
BUT the following does compile but fails with the same error you get
            DateTime x = DateTime.Now;
            var r = DateTime.ParseExact(x.ToString().Split(new char[0])[0], "MM/dd/yyyy", CultureInfo.InvariantCulture);

I suspect your 'x' value is not what you think it is.  


Try this
var query = deliveriesItemsbypaging.Select(tb => tb.ExpiryDate).AsEnumerable();
and then inspect what is in the variable query.
Use "M/d/yyyy" instead of "MM/DD/yyyy".  The second - your current format - says the string always has two digits for the month and two for the day.  Using "M/d/yyyy" means either one or two digit for the month and day
This is one of those cases where it might be simpler to not ParseExact and just Parse:

    var r = DateTime.Parse("10/31/2015 12:00:00 AM", CultureInfo.InvariantCulture);

or to be specific:

    CultureInfo cultureInfo = new CultureInfo("en-US");
    var r = DateTime.Parse("10/31/2015 12:00:00 AM", cultureInfo);

/gustav
You can use your DateTime.ParseExact, I would just recommend using an array of custom formats to ensure that you can parse any of the anticipated custom strings; e.g. -
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace EE_Q28995477
{
	class Program
	{
		static List<MyClass> set;

		static void Main(string[] args)
		{
			string[] formats = new[] {"M/d/yy", "MM/dd/yy", "M/d/yyyy", "MM/dd/yyyy" };
			set = new List<MyClass>(from i in Enumerable.Range(0, 20) select new MyClass() { ID = i, Name = string.Format("Name{0}", i), ExpiryDate = DateTime.Now.AddDays(-(i * 9)).ToString("M/d/yyyy h:m:s tt")});
			var dates = (from c in set select DateTime.ParseExact(c.ExpiryDate.Split(new char[0])[0], formats, CultureInfo.InvariantCulture, DateTimeStyles.None));
			foreach (var d in dates)
				Console.WriteLine(d.ToString("MM/dd/yyyy"));
			Console.ReadLine();
		}
	}

	class MyClass
	{
		public int ID { get; set; }
		public string Name { get; set; }
		public string ExpiryDate { get; set; }
	}
}

Open in new window

Which produces the following output -User generated image
But it really seems as if you are doing more than is needed in the long run as your incoming string is already parsable without a split requirement; e.g. -
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace EE_Q28995477
{
	class Program
	{
		static List<MyClass> set;

		static void Main(string[] args)
		{
			string[] formats = new[] {"M/d/yy h:m:s tt", "MM/dd/yy hh:mm:ss tt", "M/d/yyyy h:m:s tt", "MM/dd/yyyy hh:mm:ss tt" };
			set = new List<MyClass>(from i in Enumerable.Range(0, 20) select new MyClass() { ID = i, Name = string.Format("Name{0}", i), ExpiryDate = DateTime.Now.AddDays(-(i * 9)).ToString("M/d/yyyy h:m:s tt")});
			var dates = (from c in set select DateTime.ParseExact(c.ExpiryDate, formats, CultureInfo.InvariantCulture, DateTimeStyles.None));
			foreach (var d in dates)
				Console.WriteLine(d.ToString("MM/dd/yyyy"));
			Console.ReadLine();
		}
	}

	class MyClass
	{
		public int ID { get; set; }
		public string Name { get; set; }
		public string ExpiryDate { get; set; }
	}
}

Open in new window

Which produces the exact same output as above.

-saige-
.. you can parse any of the anticipated custom strings

But none of the format are custom, so isn't that exactly what the Parse method does?

/gustav
ASKER CERTIFIED SOLUTION
Avatar of it_saige
it_saige
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I believe IT_Saige answer more complete, in very least IT_Saige should share points
My comment starting with:  Use "M/d/yyyy" instead of "MM/DD/yyyy" will work - it was related to something I pointed out even earlier namely the value being parsed was NOT what had been expected.  The date was appearing in a slightly different format.
Then I believe point should be split between you three but not just Gustav
ps.  Don't confuse simpler with better.  There has been nothing mentioned about the advantages of your original method (which would work with a simple change) when compared to the change you have accepted.
Well, here simpler - or rather even simpler - is better.
I couldn't have found a better example for where to use Parse in favour of ParseExact.

/gustav
Hmmm.  Even when it **could ** result in incorrect operation.  (We do not know what else is done in the program.)  I can also see another advantage with the original code apart from that.
True, other information could change the picture.

/gustav