2

I've looked at a bunch of questions regarding parsing strings into a DateTime object, but none seem to have the same format as I do. The strings that I need to parse into a DateTime object are in this format:

Jun 29 2016 12:57PM
Jan 1 1900 12:00AM

The format I am trying is the following:

DateTime.ParseExact(date, "MMM dd yyyy hh:mmtt", CultureInfo.InvariantCulture)

but this throws a FormatException. Any suggestions?

pcoonan
  • 67
  • 8
  • Can you please clarify which part of [Custom Date and Time Format strings](https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx) is not clear about day format (like `"d"` vs. `"dd"` difference)? – Alexei Levenkov Sep 22 '16 at 17:33
  • Note that title of the post has absolutely nothing to do with the problem you have - you may want to re-read [MCVE] guidance on creating sample code for posts. – Alexei Levenkov Sep 22 '16 at 17:37
  • 1
    Check trailing spaces in your strings of date – Fabio Sep 22 '16 at 17:39
  • Tried trimming whitespace, still throwing the error. Could this have to do with the AM/PM part being right after the minutes? – pcoonan Sep 22 '16 at 17:45
  • "Tried trimming whitespace, still throwing the error." -- which string is throwing the error? You have two strings, but your format will only work with one of them. It is entirely expected that you will get a `FormatException` when using `"MMM dd yyyy hh:mmtt"` format on the string `Jan 1 1900 12:00AM`. Use this format: `"MMM d yyyy hh:mmtt"` instead, then trim whitespace, then tell us if you are still getting format exception on *both* strings. – Quantic Sep 22 '16 at 17:52
  • I've been testing this just on Jan 1 1900 12:00AM, the other date was just for reference to the overall formatting scheme. I changed my format string to `MMM d yyy h:mmtt` and when the Jan 1 date is passed in, with trailing spaces trimmed, the FormatException is thrown. – pcoonan Sep 22 '16 at 17:56

4 Answers4

3

You might want to look over the Custom Date and Time Format Strings page on MSDN. I think your issue is that your current format is requiring leading zeros on both your day and hour. For example, this would look like

Jan 01 1900 01:00PM

You are probably wanting to use the format

DateTime.ParseExact(date, "MMM d yyyy h:mmtt", CultureInfo.InvariantCulture)

which does not require the leading zeros for the day and hour positions. This would match values such as

Jan 1 1900 1:00PM

I hope this helps.

Nathan M.
  • 286
  • 1
  • 9
  • Trying this format with Jan 01 1900 12:00AM still doesn't work. Your answer does seem correct to me. – pcoonan Sep 22 '16 at 17:39
  • @pcoonan It works fine for me. In your post you give two example strings and the first one has a trailing space. In addition to your formatting issues (which can all be solved by using the format given in this answer), you also have trailing spaces that need to be removed becuase they will also cause a `FormatException`. Probably use [`Trim()`](https://msdn.microsoft.com/en-us/library/t97s7bs3(v=vs.110).aspx) to get rid of all leading and trailing whitespace. – Quantic Sep 22 '16 at 17:44
  • Sorry for the confusion. The format I provided isn't intended to work with the value I provided. The value was an example of what values the format that you provided in your question would match. My format should work with values such as Jan 1 1900 1:00AM as opposed to your original format which would match Jan 01 1900 01:00AM. The format I provided does not require leading zeros. Yours does. That's the only difference. – Nathan M. Sep 22 '16 at 17:45
  • @CrossPhyre "The format I provided isn't intended to work with the value I provided" - but, it does work. I can't find explicitly why it works in the MSDN, though, so I can't give an explanation of why `d` works with dates that have `01` or `1` for the day. – Quantic Sep 22 '16 at 17:48
  • My format has no leading zeros on either days or hours, so what you gave should work. I did test it after trimming whitespace and still an exception is thrown. – pcoonan Sep 22 '16 at 17:49
  • @pcoonan Can you provide us with the exception that is being thrown? – Nathan M. Sep 22 '16 at 17:56
  • @Quantic That is interesting. I just tried it parsing strings with leading zeros and without leading zeros using both d and dd. It seems that using d is "intelligent" enough to handle the leading zeros, but dd fails when parsing a string without leading zeros. I'm like you, though, I can't explain why this is. – Nathan M. Sep 22 '16 at 18:02
  • @CrossPhyre what details would help? The exception is a FormatException, where the message is "String was not recognized as a valid DateTime" – pcoonan Sep 22 '16 at 18:03
  • @pcoonan Strange indeed. Assuming your date string is typed correctly, I have no idea why it's not formatting correctly. Here are the three lines of code that I am using to test my format. You may want to compare them to look for any differences that may point us in the right direction. `string s = "Jan 1 1900 12:00AM"; DateTime d = DateTime.ParseExact(s, "MMM d yyyy h:mmtt", null); Console.WriteLine(d);` – Nathan M. Sep 22 '16 at 18:09
  • @pcoonan Where are you getting the the strings from? Are you parsing a file? People end up with "zero length" characters in the source code (or text file) and it screws with all string parsing methods. E.g., see [here](http://stackoverflow.com/questions/39278233/read-text-file-return-system-notsupportedexception-exception/39278485), in that post you can copy and paste OP's text `@"‪D:\links.txt"`, erase the visible text down to `@"‪"`, and do a length check on it and you get `1` when it should be zero. This comment itself has the hidden character, you can see it with `@"‪".Length`. – Quantic Sep 22 '16 at 18:14
  • Strings are coming from a SQL Server db. Pretty sure all extra characters have been removed. – pcoonan Sep 22 '16 at 18:17
  • 1
    Found the bug, the dev that put the strings into the db replaced the leading zero that would have appeared on day or hour with a space, so there was two spaces between Jan and 1. Currently working out a solution. – pcoonan Sep 22 '16 at 18:30
  • 1
    @pcoonan If you haven't noticed my answer, it does solve the problem. – Andrew Morton Sep 22 '16 at 18:34
  • @AndrewMorton Nice one with the DateTimeStyles. Tried it with `DateTime.ParseExact(s, "MMM d yyyy h:mmtt",null, DateTimeStyles.AllowWhiteSpaces);` and everything worked beautifully with the extra whitespace that @pcoonan was mentioning. Nice catch. – Nathan M. Sep 22 '16 at 18:41
  • @CrossPhyre Do note that if you specify `null` for the provider, it uses the current CultureInfo - this may or may not be desirable. OP: it's always worth looking at the documentation as well as questions on a subject. – Andrew Morton Sep 22 '16 at 18:49
1

There is an overload of DateTime.ParseExact which takes an array of formats to try and lets you specify that whitespace is allowed:

string[] ss = new string[] { "Jun 29 2016 6:59PM", "Jan 1  1900 12:00AM " };
string[] formats = new string[] { "MMM dd yyyy h:mmtt", "MMM d yyyy hh:mmtt", "MMM dd yyyy hh:mmtt", "MMM d yyyy h:mmtt" };

foreach (string s in ss)
{
    Console.WriteLine(DateTime.ParseExact(s, formats, null, DateTimeStyles.AllowWhiteSpaces).ToString("yyyy-MM-dd HH:mm:ss"));
}

But if your date strings are a bit lax, you could use TryParse instead:

DateTime d;
foreach (string s in ss)
{
    if (DateTime.TryParse(s, out d))
    {
        Console.WriteLine(d.ToString("yyyy-MM-dd HH:mm:ss"));
    }
}

You should probably specify a System.IFormatProvider.

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
0

First string will be parsed successfully.

Second string needs to use d specifier instead of dd specifier since single day number does not have a leading zero.

DateTime.ParseExact("Jun 29 2016 12:57PM", 
                    "MMM dd yyyy hh:mmtt", 
                     CultureInfo.InvariantCulture).Dump();

and

DateTime.ParseExact("Jan 1 1900 12:00AM ", 
                    "MMM d yyyy hh:mmtt", 
                     CultureInfo.InvariantCulture).Dump();

By the way, you can use MMM d yyyy hh:mmtt format for both of them.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
-1

Here's a cheat sheet for date formatting, courtesy of http://www.mikesdotnetting.com/article/23/date-formatting-in-c

  Example Usage

 <%= String.Format("{specifier}", DateTime.Now) %>
 @DateTime.Now.ToString("F")
 @DateTime.Now.ToString("hh:mm:ss.fff")


Specifier

Description

Output

d Short Date 08/04/2007 
D Long Date 08 April 2007 
t Short Time 21:08 
T Long Time 21:08:59 
f Full date and time 08 April 2007 21:08 
F Full date and time (long) 08 April 2007 21:08:59 
g Default date and time 08/04/2007 21:08 
G Default date and time (long) 08/04/2007 21:08:59 
M Day / Month 08 April 
r RFC1123 date Sun, 08 Apr 2007 21:08:59 GMT 
s Sortable date/time 2007-04-08T21:08:59 
u Universal time, local timezone 2007-04-08 21:08:59Z 
Y Month / Year April 2007 
dd Day 08 
ddd Short Day Name Sun 
dddd Full Day Name Sunday 
hh 2 digit hour 09 
HH 2 digit hour (24 hour) 21 
mm 2 digit minute 08 
MM Month 04 
MMM Short Month name Apr 
MMMM Month name April 
ss seconds 59 
fff milliseconds 120 
FFF milliseconds without trailing zero 12 
tt AM/PM PM 
yy 2 digit year 07 
yyyy 4 digit year 2007 
: Hours, minutes, seconds separator, e.g. {0:hh:mm:ss} 09:08:59 
/ Year, month , day separator, e.g. {0:dd/MM/yyyy} 08/04/2007 
. milliseconds separator 
Shannon Holsinger
  • 2,293
  • 1
  • 15
  • 21