C# DateTime ParseExact exception - c#

I'm having problems with DateTime.ParseExact method which is throwing exceptions that my input string is not in correct format.
Code follows :
class Program
{
static void Main(string[] args)
{
var rawDate = "Thu, 08 nov 2012 15:19:18 0";
var _format = "ddd, dd MMM yyyy HH:mm:ss K";
var date = DateTime.ParseExact(rawDate, _format, CultureInfo.InvariantCulture);
}
}
I found a few similar threads here on SO with exact date format and nobody reports any problem there.
I followed this as my guide :
ddd = Three letter Day of week
MMM = Three letter month
dd = Two digit day of month 01-31 (use "d" for 1-31)
HH = Hours using 24-hour clock. 00-24 (use "H" for 0-24)
mm = Minutes. 00-59
ss = Seconds. 00-59
K = Time zone information
yyyy = 4-digit year
What can be cause of exceptions?
Thank you in advance!

I think your 'K' might be a bit off.
The link here might give an explanation: http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx#KSpecifier
You can leave this blank and drop the 0 - K

You timezone is wrong in your input string - it needs to be in the format +00:00.
To test your datetime format strings, run them in reverse:
Console.WriteLine(DateTime.Now.ToString(_format));
which gives
Thu, 08 Nov 2012 15:50:58 +00:00

Time zone information looks like the most likely suspect to me.

Try this:
var _format = "ddd, dd MMM yyyy HH:mm:ss 0";
You will lose the timezone information, though.

Related

How to parse custom string to DateTime C#?

I need to parse to following Date Aug 20 11:38:43 2017 GMT
I'm trying to use DateTime.TryParseExact but can't find the correct format.
my latest format is MMM dd hh:mm:ss yyyy
my code :
string nextUpdate; //Next Update: Aug 20 11:38:43 2017 GMT
string dateTimeFormat = "MMM dd hh:mm:ss yyyy";
DateTime crldt;
DateTime.TryParseExact(nextUpdate.Split(':')[1].Trim(), dateTimeFormat, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out crldt);
when I run the code I get crldt ~ Date = {1/1/01 12:00:00 AM}
my question : what format should I use or what alternative way can I use to parse this string to DateTime
UPDATE
using suggestions from : #Sergey Berezovskiy
I've updated the code to :
string nextUpdate; // Next Update: Oct 7 06:16:18 2017 GMT
string dateTimeFormat = #"MMM dd HH:mm:ss yyyy \G\M\T";
Regex r =new Regex(".*Next Update:.*");
nextUpdate = r.Match(Crltext).Value;
DateTime crldt;
DateTime.TryParseExact(nextUpdate.Substring(nextUpdate.IndexOf(':')+1).Trim(),
dateTimeFormat, System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.AssumeUniversal, out crldt);
int intDTComp = DateTime.Compare(crldt, DT_now);
I've found a date that doesn't fit this format : Next Update: Oct 7 06:16:18 2017 GMT
what is the issue now ?
UPDATE 2
I've found the issue , but can't find a clean solution.
The issue is that the problematic date is Oct 7 ... ,
while the format is MMM dd ...
my workaround is adding another format MMM d hh:mm:ss yyyy and using it if date = {1/1/01 12:00:00 AM}
what other solution may I use in this scenario
First of all, don't forget that your string contains "GMT". You should either remove it from the string, or add to format pattern:
string nextUpdate = "Next Update: Aug 20 11:38:43 2017 GMT";
string format = #"MMM dd hh:mm:ss yyyy \G\M\T";
Next - don't split input string by : because there is another : symbols in the string. And you will get array with parts ["Next Update", " Aug 20 11", "38", "43 2017 GMT"]. Taking the second item from array gives you " Aug 20 11". Instead, you should just take substring after first : occurance:
string s = nextUpdate.Substring(nextUpdate.IndexOf(':') + 1).Trim();
And finally parse that string using your format:
IFormatProvider provider = CultureInfo.InvariantCulture;
DateTime date = DateTime.ParseExact(s, format, provider, DateTimeStyles.AssumeUniversal);
Output will depend on your time zone. E.g. for my time zone GMT+3 it will be:
8/20/2017 14:38:43
If this is your string:
"Next Update: Aug 20 11:38:43 2017 GMT"
Then when you do this:
nextUpdate.Split(':')[1].Trim()
You get this:
"Aug 20 11"
Which doesn't match your date format. I suspect you don't just want the second split value, but also all remaining split values. You can re-join them. Something like this:
string.Join(":", nextUpdate.Split(':').Skip(1)).Trim()
This would split them by the ":" character, skip the first one but keep all remaining ones, and re-join the remaining ones into another string with the ":" character again.
Note: You may also need to account for that time zone value. There are some helpful ideas on this question for how to do that.
If that's the input, I propose that you take the format exactly as the input
string nextUpdate = "Next Update: Aug 20 11:38:43 2017 GMT";
string dateTimeFormat = #"\N\e\x\t\ \U\p\d\a\t\e\:\ MMM dd hh:mm:ss yyyy\ \G\M\T";
DateTime crldt;
crldt = DateTime.ParseExact(nextUpdate, dateTimeFormat , System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None);
This way, when reading the code it's very clear what the expected format is, and you don't have code with Split() or other items that need explanation.
Also note that if you leave the colons (:) like that, they may be replaced by .NET to match the hour separator. Use \: if you always require a literal colon.
As I wrote in the comments before, note that you're ignoring the time zone.
Use following code
CultureInfo provider = CultureInfo.InvariantCulture;
DateTime givenDate = DateTime.ParseExact("Aug 20 14:38:43 2017 GMT", "MMM dd HH:mm:ss yyyy GMT", provider); // here HH is for 24 hour format . use hh for 12 hour format
string expectedDate = givenDate.ToString("dd/MM/yy hh:mm:ss tt"); // tt is for AM or PM (no need to use tt if you use hour as HH I mean 24 hour format)
Your Output will be 20/08/17 11:38:43 AM

Parse date and Convert W. Europe Standard Time to UTC

TL:DR: I have the following input string:
Thu Mar 09 2017 18:00:00 GMT+0100
And I am trying to convert it to a DateTime object using the format:
"ddd MMM dd yyyy HH:mm:ss"
This obviously doesn't work as I am ignoring the GMT+0100 part. How can I include this?
I don't manage to parse and convert following input to a correct UTC DateTime object:
input string selectedDate:
1,Thu Mar 09 2017 18:00:00 GMT+0100 (W. Europe Standard Time)
function:
var splittedValues = selectedDate.Split(',');
var selectDayOfWeek = (DayOfWeek)int.Parse(splittedValues[0]);
var selectedTime = DateTime.ParseExact(splittedValues[1].Substring(0, 24),
"ddd MMM d yyyy HH:mm:ss",
CultureInfo.InvariantCulture);
DateTime today = new DateTime(DateTime.Today.Ticks, DateTimeKind.Unspecified);
// The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
int daysUntilNextTargetDay = ((int)selectDayOfWeek - (int)today.DayOfWeek + 7) % 7;
DateTime nextTargetDay = today.AddDays(daysUntilNextTargetDay).AddHours(selectedTime.Hour).AddMinutes(selectedTime.Minute);
return nextTargetDay.ToUniversalTime();
results time portion is always 18:00:00
should be 17:00 as the input was actually GMT +01
Whats the issue here?
update:
as others pointed out there were mistakes so I updated my code to:
var splittedValues = selectedDate.Split(',');
var selectDayOfWeek = (DayOfWeek)int.Parse(splittedValues[0]);
var selectedTime = DateTime.ParseExact(splittedValues[1].Substring(0, 33),
"ddd MMM dd yyyy HH:mm:ss",
CultureInfo.InvariantCulture).ToUniversalTime();
// The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
int daysUntilNextTargetDay = ((int)selectDayOfWeek - (int)DateTime.Today.DayOfWeek + 7) % 7;
DateTime nextTargetDay = DateTime.Today.AddDays(daysUntilNextTargetDay).AddHours(selectedTime.Hour).AddMinutes(selectedTime.Minute);
return nextTargetDay;
but now the parsing fails as the substring does not match "ddd MMM dd yyyy HH:mm:ss"
how does the GMT+0100 has to be included here?
Use TimeZoneInfo when converting between specific time zones:
TimeZoneInfo westInfo =
TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
DateTime westTime = DateTime.Parse("2012.12.04T08:35:00");
DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(westTime, westInfo);
To address your confusion:
DateTime.Parse as used here makes no assumptions about the timezone of the given value. IT stores it with a DateTimeKind of Unspecified.
TimeZoneInfo.ConvertTimeToUtc as used here expects an Unspecified datetime, reads it as if it is in the explicitly specified time zone, and converts it to UTC.
Changing your code to this (adding ToUniversalTime() before adding days) fixed it for me.
DateTime nextTargetDay = today.ToUniversalTime().AddDays(daysUntilNextTargetDay).AddHours(selectedTime.Hour).AddMinutes(selectedTime.Minute);
Then of course you can just return nextTargetDay; at the end.
Looking into MSDN I can spot an initial problem with your code. This is that you are using d where you should be using dd as the day is 09 not 9.
d: The day of the month, from 1 through 31.
dd: The day of the month, from 01 through 31.
Secondly, the reason the +1 is "ignored" is that you exclude it in the substring, i.e.
splittedValues[1].Substring(0, 24) == "Thu Mar 09 2017 18:00:00";
So essentially you need to include that part of the string with the correct format specifier (I'm not sure which one). Or interrogate it yourself and subtract one hour off of the result as needed.
Side note: The following code is weird (in my opinion, there may be a reason for it):
DateTime today = new DateTime(DateTime.Today.Ticks, DateTimeKind.Unspecified);
You can either use DateTime.Today or DateTime.Now.Date.
As mentioned in the answer by #calypso you can use the TimeZoneInfo class. Their answer goes over a general approach of how to use it. But for your particular example you can do (code is untested but looks like it should work):
var selectedTime = DateTime.ParseExact(splittedValues[1].Substring(0, 24), "ddd MMM dd yyyy HH:mm:ss", CultureInfo.InvariantCulture);
TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(splittedValues[1].Substring(splittedValues[1].IndexOf("(") + 1).TrimEnd(")"));
DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(selectedTime, timeZoneInfo);

Date Formatting C#

I am having an issue converting this date format into another format. I was hoping that somebody on here would be able to help me out.
Here is my code:
string fromFormat = "ddd, dd MM yyyy HH:mm:ss zzz";
string toFormat = "yyyy-MM-dd";
DateTime newDate = DateTime.ParseExact("Mon, 25 03 2013 00:00:00 GMT", fromFormat, null);
Console.WriteLine(newDate.ToString(toFormat));
-------EDIT--------
I was able to get rid of my errors by changing the day from 22 to 25. My new issue is trying to get the timezone to convert from GMT to EST. Would anyone have any ideas?
-------EDIT #2-------
Here is my current code as it stands. I am still having issues with a timezone conversion.
var date = "Mon, 25 03 2013 00:00:00 GMT";
// Cuts off "GMT" portion of string
string newdate = date.Substring(0, 24);
// Switches the output of date
string fromFormat = "ddd, dd MM yyyy HH:mm:ss";
string toFormat = "yyyy-MM-dd";
DateTime newDate = DateTime.ParseExact(newdate, fromFormat, null);
string finaldate = newDate.ToString(toFormat);
// Output final date
Console.WriteLine(finaldate);
-------EDIT #3-------
The code:
var input = "Mon, 25 03 2013 00:00:00 GMT";
var inner = input.Substring(0, 24);
var format = "ddd, dd MM yyyy HH:mm:ss";
var zoneId = "Eastern Standard Time";
var parsed = DateTime.ParseExact(inner, format, CultureInfo.InvariantCulture);
var utcDateTime = DateTime.SpecifyKind(parsed, DateTimeKind.Utc);
var eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcDateTime, zoneId);
Console.WriteLine(eastern);
The error:
Unhandled Exception: System.TimeZoneNotFoundException: Exception of type
'System.TimeZoneNotFoundException' was thrown.
at System.TimeZoneInfo.FindSystemTimeZoneByFileName (System.String id, System.String
filepath) [0x00000] in :0
at System.TimeZoneInfo.FindSystemTimeZoneById (System.String id) [0x00000] in :0
at System.TimeZoneInfo.ConvertTimeBySystemTimeZoneId (DateTime dateTime, System.String
destinationTimeZoneId) [0x00000] in :0
at Program.Main () [0x00000] in :0
Any help would be much appreciated! Thanks!
-------FINAL EDIT-------
This is what ended up changing the timezone and converting to the format that I needed. Special thanks to #MattJohnson for all of his help!
// Cuts off 'GMT' portion of string
var newdate = date.Substring(0, 24);
var fromFormat = "ddd, dd MM yyyy HH:mm:ss";
var toFormat = "yyyy-MM-dd";
var zoneId = "Eastern Standard Time";
var parsed = DateTime.ParseExact(newdate, fromFormat, CultureInfo.InvariantCulture);
// Specifies UTC time and converts it to EST timezone
var utcDateTime = DateTime.SpecifyKind(parsed, DateTimeKind.Utc);
var eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcDateTime, zoneId);
// Converts date to final format needed
var finaldate = eastern.ToString(toFormat);
string fromFormat = "ddd, dd MM yyyy HH:mm:ss zzz";
The error is your zzz, it is expecting the numerical representation of the timezone, not the abbreviation of the timezone.
So a acceptable version would be
DateTime newDate = DateTime.ParseExact("Mon, 22 03 2013 00:00:00 +0:00", fromFormat, null);
but that would throw a different FormatExecption with the message "String was not recognized as a valid DateTime because the day of week was incorrect." If you make the Monday to Friday correction the parse works
DateTime newDate = DateTime.ParseExact("Fri, 22 03 2013 00:00:00 +0:00", fromFormat, null);
I don't think there is a format specifier that can take in the textual abbreviation version of the timezone.
As others pointed out, the input value you have is self-inconsistent. It refers to a March 22 2013 as a Monday when it is actually a Friday. So you should go back to your source data and figure out why that happens. I'm sure you have heard the saying, "Garbage In, Garbage Out".
If you are sure you want to ignore the day of week, and you are certain that the time zone will always be GMT, then you can do this:
var input = "Mon, 22 03 2013 00:00:00 GMT";
var inner = input.Substring(5, 19);
var format = "dd MM yyyy HH:mm:ss";
var parsed = DateTime.ParseExact(inner, format, CultureInfo.InvariantCulture);
var utcDateTime = DateTime.SpecifyKind(parsed, DateTimeKind.Utc);
Note that I explicitly set the kind to UTC, because you are bringing in GMT values. GMT and UTC are identical for all practical purposes.
If it's possible that other time zone values will be passed, then please provide a sampling of different possible inputs and perhaps we can find a way to accommodate that.
As an aside - this string looks very similar to RFC822/RFC1123 formatted dates, except you are passing the month as a number instead of one of the three-letter abbreviations. Did you do this intentionally? If so, you have broken the spec for this format. If your intention was to remove potentially localizable strings from the data, then please use a format that is already designed for that, such as ISO8601/RFC3339.
On Time Zones
You said you want to convert to EST, You probably mean "US Eastern Time", which alternates between EST and EDT for daylight saving time. Despite this, the Windows Time Zone database uses the id of "Eastern Standard Time" to refer to both values - so try not to get confused on that point.
Once you have the date as a DateTime of Utc kind, as I showed above, you can convert that to Eastern Time with the following:
var zoneId = "Eastern Standard Time"; // don't get confused here! :)
var eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcDateTime, zoneId);
Just be careful what you do with this value. If you are displaying it to an user, then you are ok. Just do this:
var s = eastern.ToString("g"); // or whatever format you want.
But if you do math with this, or store it as an recorded event time, you are potentially introducing errors into your results. This is due to daylight saving time transitions. One way to avoid this is to use a DateTimeOffset type instead:
var utcDateTimeOffset = new DateTimeOffset(utcDateTime, TimeSpan.Zero);
var eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcDateTimeOffset, zoneId);
Now when you work with these values, any ambiguities are captured by the offset.
If this seems very confusing to you, don't worry - you're not alone. You might want to try using Noda Time instead. It will prevent you from shooting yourself in the foot.
To see what's wrong, print a DateTime using your fromString:
DateTime dt = new DateTime(2013, 3, 22);
string s = dt.ToString(fromFormat);
you'll see that the output is:
Fri, 22 03 2013 00:00:00 -04:00
so that is the format it would be expecting.
You might be able to get some help on the abbreviations from this article.
There are two issues:
1) The day selected was a Friday not a Monday
2) The 'zzz' wants a plus or minus 0:00
So, to get it to work would be:
string fromFormat = "ddd, dd MM yyyy HH:mm:ss zzz";
string toFormat = "yyyy-MM-dd";
DateTime newDate = DateTime.ParseExact("Fri, 22 03 2013 00:00:00 +0:00", fromFormat, null);
Console.WriteLine(newDate.ToString(toFormat));
There's no simple, built-in way to convert from a Time Zone abbreviation to an offset or proper name. This is discussed in this topic here:
Timezone Abbreviations
You'll either need to create a table of the abbreviations you want to use, mapped to an offset or proper name, or you'll need to change the format of your incoming date/time string to use offsets.
string fromFormat = "ddd, dd MM yyyy HH:mm:ss zzz";
string toFormat = "yyyy-MM-dd";
DateTime newDate = DateTime.ParseExact("Mon, 22 03 2013 00:00:00 +00:00", fromFormat, null);
Console.WriteLine(newDate.ToString(toFormat));
22 03 2013 00:00:00 GMT is not Monday it's Friday
try
string fromFormat = "ddd, dd MM yyyy HH:mm:ss zzz";
string toFormat = "yyyy-MM-dd";
Console.WriteLine(DateTime.ParseExact("Fri, 22 03 2013 00:00:00 +00:00", fromFormat,
CultureInfo.InvariantCulture).ToString(toFormat));

C# DateTime.ParseExact throwing format exception

I'm developing an .NET4 webapplication using MVC3.
Let's say i'm getting the following DateTime as string from an XML-feed. The xml feed is being read by my application and i'm looping through all it's descendants. The DateTime i'm receiving is begin returned in the following format (as string);
var myDateTime = "Sun Dec 19 11:45:45 +0000 2010"
I'm using the piece of code below to try and parse the DateTime string i mentioned above to a valid DateTime format (preferably dutch)
var CorrectDateTime = DateTime.ParseExact(myDateTime , "dd MMM yyyy HH:mm:ss", CultureInfo.InvariantCulture);
When trying to execute this code i'm facing an formatexception. Somebody has got any ideas?
--UPDATE--
This is what i've got after various answers. Still throwing the same exception though.
var correctedDateTime = DateTime.ParseExact(latestTweetTime, "ddd MMM HH:mm:ss K yyyy", CultureInfo.InvariantCulture);
string display = correctedDateTime.ToString("dd MMM yyyy HH:mm:ss");
Try changing your parsing format to this:
"ddd MMM HH:mm:ss K yyyy"
If you wish to reformat the DateTimethen specify that format string when you call DateTime.ToString on your parsed DateTime:
string display = CorrectedDateTime.ToString("dd MMM yyyy HH:mm:ss");
If you're trying to read this:
"Sun Dec 19 11:45:45 +0000 2010"
You need an additional "d" or "dd" like so:
"ddd MMM d HH:mm:ss K yyyy"
or
"ddd MMM dd HH:mm:ss K yyyy"
depending on whether the input zero-prefixed.
You need each piece of the input string to be accounted for, here is a summary of the different components from MSDN: http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx
ddd = Three letter Day of week
MMM = Three letter month
dd = Two digit day of month 01-31 (use "d" for 1-31)
HH = Hours using 24-hour clock. 00-24 (use "H" for 0-24)
mm = Minutes. 00-59
ss = Seconds. 00-59
K = Time zone information
yyyy = 4-digit year
According to the date you've specified (assuming the time is in 24 hour) your input format string should be:
ddd MMM d H:mm:ss K yyyy.
Sun Dec 19 11:45:45 +0000 2010
So:
var correctedDateTime = DateTime.ParseExact(myDateTime, "ddd MMM d H:mm:ss K yyyy", CultureInfo.InvariantCulture);
string display = correctedDateTime.ToString("dd MMM yyyy HH:mm:ss");
A couple of things to note, the extra single d to capture the date and I would use a single H to allow for '01' and '1'. See http://msdn.microsoft.com/en-us/library/az4se3k1(v=VS.100).aspx for the full format details.

How to parse DateTime in this format? "Sun May 23 22:00:00 UTC+0300 2010"

This is a quick one, i wanna parse a date that comes in this format "Sun May 23 22:00:00 UTC+0300 2010"
Is this a valid UTC DateTime? And how to parse it? I tried :
DateTime newStartTime = DateTime.ParseExact(hdnNewStartTime.Value, "ddd MM dd HH:mm:ss UTC+0300 yyyy", CultureInfo.CurrentCulture);
However, this didn't work, any help appreciated!
DateTime dt = DateTime.ParseExact(s,"ddd MMM dd HH:mm:ss UTCzzzz yyyy", System.Globalization.CultureInfo.InvariantCulture);
Its not a standard format, but you can still parse it.
string format = "ddd mmm dd HH:mm:ss zzzzz yyyy";
string temp = "Sun May 23 22:00:00 UTC+0300 2010";
DateTime time = DateTime.ParseExact(temp, format, CultureInfo.InvariantCulture);
This isn't in a standard .NET format, so you'll probably have to parse it by hand. The UTC+0300 bit indicates the timezone, everything else is part of the date and time.
I tried the solution presented by #johncatfish and it does what I expect. I would presume that you actually want to keep the timezone information.
[Test()]
public void TestCaseWorks ()
{
string format = "ddd MMM dd HH:mm:ss UTCzzzzz yyyy";
string temp = "Sun May 23 22:00:00 UTC+0300 2010";
DateTime time = DateTime.ParseExact(temp, format, CultureInfo.InvariantCulture);
Assert.AreEqual(DayOfWeek.Sunday, time.DayOfWeek);
Assert.AreEqual(5, time.Month);
Assert.AreEqual(23, time.Day);
Assert.AreEqual(0, time.Minute);
Assert.AreEqual(0, time.Second);
Assert.AreEqual(2010, time.Year);
// Below is the only actually useful assert -- making sure the
// timezone was parsed correctly.
// In my case, I am GMT-0700, the target time is GMT+0300 so
// 22 + (-7 - +3) = 12 is the expected answer. It is an exercise
// for the reader to make a robust test that will work in any
// timezone ;).
Assert.AreEqual(12, time.Hour);
}
Sorry for my previous answer which was quite simplistic.
Replace MM by MMM in your date format and it should be fine.
From the example given, it isn't possible to tell if the month should be in the 3 letter form (Jan, Feb, May etc.) or in the full form (January, February, May etc.).
If it should be in the short form, use:
ddd MMM dd HH:mm:ss UTCzzz yyyy
If it should be in the long form, use:
ddd MMMM dd HH:mm:ss UTCzzz yyyy
Details of the formatting specifiers available can be found at http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx

Categories