Datetime parsing
-
This is one intriguing error that I do not even know whether to call it a bug or not ... It is fairly likely that this thing is already solved somehow by locale of which I am yet to get the precise clue. OK! all of the contents of this post (rant) revolves around DateTime, something that we, fortunately agree on values but just cannot have uniformity on how we'd like to store, read on screen and pass around. I am writing one .net application in C# that parses dates and times coming in from a ASCII bytestream. This problem only occurs when date is sent as ASCII string. As a part of early design decision,I had decided that I decided to keep will only keep one dedicated function to parse strings into dates. At first, this function started with "dd/MM/yyyy HH:mm:ss". In a different record, I discovered "yyyyMMdd". In yet another place, I discovered only date (no time) "dd-MMM-yyyy". Given that I am in India, this is the defacto date format used, so no problems. All of these were very efficiently handled by DateTime.TryParse no problems, but then I started getting dates being sent as "MM/dd/yyyy HH:mm:ss" which is like a giant monkey spanner at TryParse regardless of the locale setting. If locale is set to American, 07/01 gets read as July 1. If I set locale to British, 07/01 gets read 7 January. At least some of the byte stream format will be read incorrectly if I use same locale setting!!! At least for first 12 days of all month, this would read date incorrectly!!! Cannot use TryParse. Cannot tell people sending me byte-stream to fix up the mess. I want data, so its my headache on how to read it... Fortunately, I do tag attributes on field on what format date is it going to be in. All in all, between 50 different byte-streams, I get string dates in formats listed below. List is sorted by frequency of occurrence. Rest of them come either as # of seconds from some epoch or pair of integers. "MM/dd/yyyy HH:mm:ss", "dd/MM/yyyy HH:mm:ss", "yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss.ff", "yyyy-MM-dd HH:mm:ss.f", "ddMMMyyyy", "yyyyMMdd", "dd-MMM-yyyy" fff are miliseconds and honestly only one should be needed, but I do get 1, 2 or 3 digits after the decimal!!! In my function, I've plonked the all format strings into a static String array and then loop over it like this ... try catch inside the loop allows loop to go to next format if current one fails. for (int i = 0; i < DateFormatStrings.Length; i++) { try { dt = DateTime.ParseExact(formatDate
-
This is one intriguing error that I do not even know whether to call it a bug or not ... It is fairly likely that this thing is already solved somehow by locale of which I am yet to get the precise clue. OK! all of the contents of this post (rant) revolves around DateTime, something that we, fortunately agree on values but just cannot have uniformity on how we'd like to store, read on screen and pass around. I am writing one .net application in C# that parses dates and times coming in from a ASCII bytestream. This problem only occurs when date is sent as ASCII string. As a part of early design decision,I had decided that I decided to keep will only keep one dedicated function to parse strings into dates. At first, this function started with "dd/MM/yyyy HH:mm:ss". In a different record, I discovered "yyyyMMdd". In yet another place, I discovered only date (no time) "dd-MMM-yyyy". Given that I am in India, this is the defacto date format used, so no problems. All of these were very efficiently handled by DateTime.TryParse no problems, but then I started getting dates being sent as "MM/dd/yyyy HH:mm:ss" which is like a giant monkey spanner at TryParse regardless of the locale setting. If locale is set to American, 07/01 gets read as July 1. If I set locale to British, 07/01 gets read 7 January. At least some of the byte stream format will be read incorrectly if I use same locale setting!!! At least for first 12 days of all month, this would read date incorrectly!!! Cannot use TryParse. Cannot tell people sending me byte-stream to fix up the mess. I want data, so its my headache on how to read it... Fortunately, I do tag attributes on field on what format date is it going to be in. All in all, between 50 different byte-streams, I get string dates in formats listed below. List is sorted by frequency of occurrence. Rest of them come either as # of seconds from some epoch or pair of integers. "MM/dd/yyyy HH:mm:ss", "dd/MM/yyyy HH:mm:ss", "yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss.ff", "yyyy-MM-dd HH:mm:ss.f", "ddMMMyyyy", "yyyyMMdd", "dd-MMM-yyyy" fff are miliseconds and honestly only one should be needed, but I do get 1, 2 or 3 digits after the decimal!!! In my function, I've plonked the all format strings into a static String array and then loop over it like this ... try catch inside the loop allows loop to go to next format if current one fails. for (int i = 0; i < DateFormatStrings.Length; i++) { try { dt = DateTime.ParseExact(formatDate
I just tried
DateTime dt = DateTime.ParseExact(
"2013-07-31 09:34:44.74", "yyyy-MM-dd HH:mm:ss.ff", false);which will not compile, as the third parameter is invalid. I changed it to
DateTime dt = DateTime.ParseExact(
"2013-07-31 09:34:44.74", "yyyy-MM-dd HH:mm:ss.ff", null);and it works fine, whether inside a
try {} catch {}
or not.Use the best guess
-
I just tried
DateTime dt = DateTime.ParseExact(
"2013-07-31 09:34:44.74", "yyyy-MM-dd HH:mm:ss.ff", false);which will not compile, as the third parameter is invalid. I changed it to
DateTime dt = DateTime.ParseExact(
"2013-07-31 09:34:44.74", "yyyy-MM-dd HH:mm:ss.ff", null);and it works fine, whether inside a
try {} catch {}
or not.Use the best guess
Yes ... you are correct. 3rd param is null. It is null in my code too. I guess I made a cut-copy error. Sorry for that!!! On my machine, it does not parse only when it is within the try catch block.... especially in the function body that I have shown above... When that failed, I added one line at beginning of Main method where it worked correctly So, something is happening within the loop... My guess is that it most likely something not being made volatile, but then my log messages should give a clue. Log messages are accurate. After pasting on code project, I tried with zero compile optimizations and will know what happens
-
This is one intriguing error that I do not even know whether to call it a bug or not ... It is fairly likely that this thing is already solved somehow by locale of which I am yet to get the precise clue. OK! all of the contents of this post (rant) revolves around DateTime, something that we, fortunately agree on values but just cannot have uniformity on how we'd like to store, read on screen and pass around. I am writing one .net application in C# that parses dates and times coming in from a ASCII bytestream. This problem only occurs when date is sent as ASCII string. As a part of early design decision,I had decided that I decided to keep will only keep one dedicated function to parse strings into dates. At first, this function started with "dd/MM/yyyy HH:mm:ss". In a different record, I discovered "yyyyMMdd". In yet another place, I discovered only date (no time) "dd-MMM-yyyy". Given that I am in India, this is the defacto date format used, so no problems. All of these were very efficiently handled by DateTime.TryParse no problems, but then I started getting dates being sent as "MM/dd/yyyy HH:mm:ss" which is like a giant monkey spanner at TryParse regardless of the locale setting. If locale is set to American, 07/01 gets read as July 1. If I set locale to British, 07/01 gets read 7 January. At least some of the byte stream format will be read incorrectly if I use same locale setting!!! At least for first 12 days of all month, this would read date incorrectly!!! Cannot use TryParse. Cannot tell people sending me byte-stream to fix up the mess. I want data, so its my headache on how to read it... Fortunately, I do tag attributes on field on what format date is it going to be in. All in all, between 50 different byte-streams, I get string dates in formats listed below. List is sorted by frequency of occurrence. Rest of them come either as # of seconds from some epoch or pair of integers. "MM/dd/yyyy HH:mm:ss", "dd/MM/yyyy HH:mm:ss", "yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss.ff", "yyyy-MM-dd HH:mm:ss.f", "ddMMMyyyy", "yyyyMMdd", "dd-MMM-yyyy" fff are miliseconds and honestly only one should be needed, but I do get 1, 2 or 3 digits after the decimal!!! In my function, I've plonked the all format strings into a static String array and then loop over it like this ... try catch inside the loop allows loop to go to next format if current one fails. for (int i = 0; i < DateFormatStrings.Length; i++) { try { dt = DateTime.ParseExact(formatDate
You are testing the value of
formatFailed
in yourtry
block, but you set it inside thecatch
block. This is not the way to code atry catch
sequence. You should be displaying the failure message in thecatch
block, and break out of the loop only when the parsing succeeds.Use the best guess
-
This is one intriguing error that I do not even know whether to call it a bug or not ... It is fairly likely that this thing is already solved somehow by locale of which I am yet to get the precise clue. OK! all of the contents of this post (rant) revolves around DateTime, something that we, fortunately agree on values but just cannot have uniformity on how we'd like to store, read on screen and pass around. I am writing one .net application in C# that parses dates and times coming in from a ASCII bytestream. This problem only occurs when date is sent as ASCII string. As a part of early design decision,I had decided that I decided to keep will only keep one dedicated function to parse strings into dates. At first, this function started with "dd/MM/yyyy HH:mm:ss". In a different record, I discovered "yyyyMMdd". In yet another place, I discovered only date (no time) "dd-MMM-yyyy". Given that I am in India, this is the defacto date format used, so no problems. All of these were very efficiently handled by DateTime.TryParse no problems, but then I started getting dates being sent as "MM/dd/yyyy HH:mm:ss" which is like a giant monkey spanner at TryParse regardless of the locale setting. If locale is set to American, 07/01 gets read as July 1. If I set locale to British, 07/01 gets read 7 January. At least some of the byte stream format will be read incorrectly if I use same locale setting!!! At least for first 12 days of all month, this would read date incorrectly!!! Cannot use TryParse. Cannot tell people sending me byte-stream to fix up the mess. I want data, so its my headache on how to read it... Fortunately, I do tag attributes on field on what format date is it going to be in. All in all, between 50 different byte-streams, I get string dates in formats listed below. List is sorted by frequency of occurrence. Rest of them come either as # of seconds from some epoch or pair of integers. "MM/dd/yyyy HH:mm:ss", "dd/MM/yyyy HH:mm:ss", "yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss.ff", "yyyy-MM-dd HH:mm:ss.f", "ddMMMyyyy", "yyyyMMdd", "dd-MMM-yyyy" fff are miliseconds and honestly only one should be needed, but I do get 1, 2 or 3 digits after the decimal!!! In my function, I've plonked the all format strings into a static String array and then loop over it like this ... try catch inside the loop allows loop to go to next format if current one fails. for (int i = 0; i < DateFormatStrings.Length; i++) { try { dt = DateTime.ParseExact(formatDate
-
You will also have a problem with the first two of your format strings when the month and day are both less than 13.
Use the best guess
Richard MacCutchan wrote:
You will also have a problem with the first two of your format strings when the month and day are both less than 13.
Actually, I did have that problem when I was using TryParse and using locale. What I've done is following. For each datetime field, I've added custom attribute that spells out which format is most likely to be most appropriate for that particular field. This way, on some fields, I do instruct it to read it as dd/mm and on others I do ask it to read mm/dd.
-
You are testing the value of
formatFailed
in yourtry
block, but you set it inside thecatch
block. This is not the way to code atry catch
sequence. You should be displaying the failure message in thecatch
block, and break out of the loop only when the parsing succeeds.Use the best guess
Richard MacCutchan wrote:
You are testing the value of
formatFailed
in yourtry
block, but you set it inside thecatch
block. This is not the way to code atry catch
sequence. You should be displaying the failure message in thecatch
block, and break out of the loop only when the parsing succeeds.Richard Actual code of the function is 150-200 lines with lots of Reflection and stuff. I had only posted tail portion of code which was the problem area. What happens is as follows. For each field, I have custom attribute that spells out what format is going to be present which I call tryFirstFormat. So, there is one another parseexact before code enters loop. If it enters the loop, it is 100% certain that formatFailed will be set to 1. Fortunately, C# will not let me compile without initialized variable antway. Lastly, Message that gets logged inside try block is actually to report a successful parse after blah-blah number of attempts. Message in catch block is when parsing fails where attempt count increases Tonight, I spent time thumbing thru few other sites and decided to change the loop index (i) to be a volatile member of class Will discover how this performs tomorrow.
-
This is one intriguing error that I do not even know whether to call it a bug or not ... It is fairly likely that this thing is already solved somehow by locale of which I am yet to get the precise clue. OK! all of the contents of this post (rant) revolves around DateTime, something that we, fortunately agree on values but just cannot have uniformity on how we'd like to store, read on screen and pass around. I am writing one .net application in C# that parses dates and times coming in from a ASCII bytestream. This problem only occurs when date is sent as ASCII string. As a part of early design decision,I had decided that I decided to keep will only keep one dedicated function to parse strings into dates. At first, this function started with "dd/MM/yyyy HH:mm:ss". In a different record, I discovered "yyyyMMdd". In yet another place, I discovered only date (no time) "dd-MMM-yyyy". Given that I am in India, this is the defacto date format used, so no problems. All of these were very efficiently handled by DateTime.TryParse no problems, but then I started getting dates being sent as "MM/dd/yyyy HH:mm:ss" which is like a giant monkey spanner at TryParse regardless of the locale setting. If locale is set to American, 07/01 gets read as July 1. If I set locale to British, 07/01 gets read 7 January. At least some of the byte stream format will be read incorrectly if I use same locale setting!!! At least for first 12 days of all month, this would read date incorrectly!!! Cannot use TryParse. Cannot tell people sending me byte-stream to fix up the mess. I want data, so its my headache on how to read it... Fortunately, I do tag attributes on field on what format date is it going to be in. All in all, between 50 different byte-streams, I get string dates in formats listed below. List is sorted by frequency of occurrence. Rest of them come either as # of seconds from some epoch or pair of integers. "MM/dd/yyyy HH:mm:ss", "dd/MM/yyyy HH:mm:ss", "yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss.ff", "yyyy-MM-dd HH:mm:ss.f", "ddMMMyyyy", "yyyyMMdd", "dd-MMM-yyyy" fff are miliseconds and honestly only one should be needed, but I do get 1, 2 or 3 digits after the decimal!!! In my function, I've plonked the all format strings into a static String array and then loop over it like this ... try catch inside the loop allows loop to go to next format if current one fails. for (int i = 0; i < DateFormatStrings.Length; i++) { try { dt = DateTime.ParseExact(formatDate
I would address this a different way, assuming each stream is identifiable and is internally consistent, I would register a format for each source.
Never underestimate the power of human stupidity RAH
-
I would address this a different way, assuming each stream is identifiable and is internally consistent, I would register a format for each source.
Never underestimate the power of human stupidity RAH
Mycroft Holmes wrote:
I would address this a different way, assuming each stream is identifiable and is internally consistent, I would register a format for each source.
They are consistent in a sense that if mm was before dd, it does seem to remain that way ... but I'd be in trouble if I assume that it will always be slash / between characters. Sometimes it is dash or space too. So, I weed out all unwanted characters using String.Replace and replace them with what slashes as I have 'em on my format string before even attempting to parse the date. Further, I do have custom attribute defined for each and every date/time field which essentially leads to one of the eight format strings as "tryFirstFormat". So, yes! I do have one format registered for each field although I know that expecting it to remain consistent is a bit-too-much at this point in time.... In the code, before the loop, I use parseExact to parse the date. Naturally that too is in its own try-catch block. Only if that fails, code will enter the loop. I did not post all of the above code assuming that more code will confuse people and felt that it was not relevant to problem. But it seems from the early responses that partial code is confusing ppl more.
-
This is one intriguing error that I do not even know whether to call it a bug or not ... It is fairly likely that this thing is already solved somehow by locale of which I am yet to get the precise clue. OK! all of the contents of this post (rant) revolves around DateTime, something that we, fortunately agree on values but just cannot have uniformity on how we'd like to store, read on screen and pass around. I am writing one .net application in C# that parses dates and times coming in from a ASCII bytestream. This problem only occurs when date is sent as ASCII string. As a part of early design decision,I had decided that I decided to keep will only keep one dedicated function to parse strings into dates. At first, this function started with "dd/MM/yyyy HH:mm:ss". In a different record, I discovered "yyyyMMdd". In yet another place, I discovered only date (no time) "dd-MMM-yyyy". Given that I am in India, this is the defacto date format used, so no problems. All of these were very efficiently handled by DateTime.TryParse no problems, but then I started getting dates being sent as "MM/dd/yyyy HH:mm:ss" which is like a giant monkey spanner at TryParse regardless of the locale setting. If locale is set to American, 07/01 gets read as July 1. If I set locale to British, 07/01 gets read 7 January. At least some of the byte stream format will be read incorrectly if I use same locale setting!!! At least for first 12 days of all month, this would read date incorrectly!!! Cannot use TryParse. Cannot tell people sending me byte-stream to fix up the mess. I want data, so its my headache on how to read it... Fortunately, I do tag attributes on field on what format date is it going to be in. All in all, between 50 different byte-streams, I get string dates in formats listed below. List is sorted by frequency of occurrence. Rest of them come either as # of seconds from some epoch or pair of integers. "MM/dd/yyyy HH:mm:ss", "dd/MM/yyyy HH:mm:ss", "yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss.ff", "yyyy-MM-dd HH:mm:ss.f", "ddMMMyyyy", "yyyyMMdd", "dd-MMM-yyyy" fff are miliseconds and honestly only one should be needed, but I do get 1, 2 or 3 digits after the decimal!!! In my function, I've plonked the all format strings into a static String array and then loop over it like this ... try catch inside the loop allows loop to go to next format if current one fails. for (int i = 0; i < DateFormatStrings.Length; i++) { try { dt = DateTime.ParseExact(formatDate
Will it help if I publish entire parsing code? ... Certainly there is little bit of refactoring that can reduce the lines which I've postponed until it works correctly? I had omitted code above the for loop because (a) it is working fine (as I coded it). (b) I did not want to post too big code here