Convert.ToDateTime causes FormatException on afternoon date/time values
Asked Answered
G

8

11

We have an application parsing date/time values in the following format:

2009-10-10 09:19:12.124
2009-10-10 12:13:14.852
2009-10-10 13:00:00
2009-10-10 15:23:32.022

One particular server all of the sudden (today) started failing to parse any times 13:00:00 or later. This particular client has five servers and only one has the problem. We have dozens of other clients with a total of hundreds of servers without the problem.

System.FormatException: String was not recognized as a valid DateTime.
at System.DateTimeParse.Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
at System.DateTime.Parse(String s, IFormatProvider provider)
at System.Convert.ToDateTime(String value, IFormatProvider provider)
at System.String.System.IConvertible.ToDateTime(IFormatProvider provider)
at System.Convert.ToDateTime(Object value)

I ran a test using DateTime.Parse(s, CultureInfo.CurrentCulture) comapred to DateTime.Parse(s, CultureInfo.InvariantCulture) and the problem only shows up with CurrentCulture. However, CurrentCulture is "en-US" just like all the other servers and there's nothing different that I can find in regional or language settings.

Has anyone seen this before? Suggestions related to what I can look into?

EDIT: Thank you for the answers so far. However, I'm looking for suggestions on what configuration to look into that could have caused this to suddenly change behavior and stop working when it's worked for years and works on hundreds of other servers. I've already changed it for the next version, but I'm looking for a configuration change to fix this in the interim for the current installation.

Gavel answered 16/10, 2009 at 19:2 Comment(0)
J
3

We also encountered the same problem. Just recycle your application pool.

Jaime answered 15/3, 2010 at 17:5 Comment(1)
Yes, but... why? We have the same problem sporadically. Our web service converts a C# DateTime object to a string and passes it to a SQL Server database procedure that expects a smalldatetime. For some reason, sometimes this shifts the time by 12 hours, so sending today's date goes across as today at noon (12:00:00 PM) instead of today at midnight (12:00:00 AM).Unaccountedfor
E
7

If you know the format exactly, tell the application what it is - use DateTime.ParseExact instead of just DateTime.Parse. (And as others have said, specify the invariant culture as well, to take away any more variation.) That gives you much more control:

using System;
using System.Globalization;

class Test
{
    static void Main()
    {
        Parse("2009-10-10 09:19:12.124");
        Parse("2009-10-10 12:13:14.852");
        Parse("2009-10-10 13:00:00");
        Parse("2009-10-10 15:23:32.022");
    }

    static readonly string ShortFormat = "yyyy-MM-dd HH:mm:ss";
    static readonly string LongFormat = "yyyy-MM-dd HH:mm:ss.fff";

    static readonly string[] Formats = { ShortFormat, LongFormat };

    static void Parse(string text)
    {
        // Adjust styles as per requirements
        DateTime result = DateTime.ParseExact(text, Formats, 
                                              CultureInfo.InvariantCulture,
                                              DateTimeStyles.AssumeUniversal);
        Console.WriteLine(result);
    }
}
Esma answered 16/10, 2009 at 19:11 Comment(0)
J
3

We also encountered the same problem. Just recycle your application pool.

Jaime answered 15/3, 2010 at 17:5 Comment(1)
Yes, but... why? We have the same problem sporadically. Our web service converts a C# DateTime object to a string and passes it to a SQL Server database procedure that expects a smalldatetime. For some reason, sometimes this shifts the time by 12 hours, so sending today's date goes across as today at noon (12:00:00 PM) instead of today at midnight (12:00:00 AM).Unaccountedfor
P
3

We have an C# .NET 2.0 web service running on a Windows 2003 server. That service has been running for more than two years. We recently srtarted experiencing errors in that application. The error message is "String was not recognized as a valid DateTime". Another web servie returns a date, and that function should return a value like

"5/10/2010 12:00:00 AM"

When the errors are occurring the function returns

"5/10/2010 12:00:00 "

The incorrect return has white space at the end and no AM.

This problem appeared and disappeared several times over the next couple of weeks. After examining the windows logs, we noticed that the start and end times of the errors coincided (within a minute or two) of an application pool recycle that is set (by default) to occur every 29 hours. This problem only occurred on the production web server, and not on the development or test servers. We tried replacing the server, and there were no errors for a month. Now the errors have started again. We manually reset the pool and the problem disappeared immediately. We would rather not view this as an acceptable solution, as the pool recycles regularly. We don't know if we need the pool recycle, but it is our understanding that regular recycles help with application performance.

The web application uses ParseExact() already, but the format string looks like this:

"yyyy-MM-ddHH:mm:ss.0Z"

instead of

"yyyy-MM-dd HH:mm:ss"

suggested by Jon Skeet in this thread. I don't know if this would make much difference.

We also checked the culture settings.

It seems clear that the problem begins with the application pool recycle, but I have no idea what occurs under the hood during that recycle. Most of the time the recycle has no negative effect, and when the errors do occur, the next recycle has always stopped the errors.

Phytogeography answered 21/5, 2010 at 20:40 Comment(2)
@Dan Bruton We have not fixed it. The problem has kicked in a couple more times since I wrote this, and recycling does fix the problem temporarily. We're considering changing the timing of the recycle to insure that it happens at the same time each week and we're ready for it, but we still have no idea what the real problem is. We also worked with Microsoft on this, and they don't seem to have any better idea than we do.Phytogeography
Any other updates on this? I have witnessed this same problem myself, and took a memory dump of the process at the time it was happening. What I saw there was that storing a datetime as a generic object, then pulling it back out as a datetime was losing the culture information (very randomly, of course... seemingly impossible to reproduce)Alister
T
2

The solution is very simple, use CultureInfo.InvariantCulture. For the sample data that is the only sensible thing to do.

I know this doesn't explain the difference, but your software really shouldn't rely on the 'default' culture (except maybe in the UI).

Trounce answered 16/10, 2009 at 19:12 Comment(1)
Even with the invariant culture I wouldn't rely on the default formats - specify the format explicitly, then it's clear what you expect.Esma
U
1

I've just found some information about what is causing this issue. Our C# client sends a business date (date only) as a string value to a web service. The web service passes this string in a SqlParameter to a SqlCommand to a stored procedure that accepts a datetime parameter for the business date.

A customer's system was suddenly misbehaving. I used the SQL Server Profiler to watch the RPC calls and noticed that the date parameter suddenly had a time component. This is supposed to be a date only value-- i.e. 10/27/2012 12:00:00 AM.

I modified the stored procedure to add a WAITFOR DELAY '00:01:00'. I then acquired a memory dump of the web service while it was making the call to this stored procedure.

Examining the memory dump, I found that the client had passed in the correct date string of "2012-10-25 00:00:00" in a DataSet of parameters. The web service somehow messed up the conversion of these dates when it called the stored procedure. I found the SqlCommand in the dump and examined the SqlParameter corresponding to the stored procedure's date parameter. The value was "10/25/2012 12:00:00 PM".

Looking at all the CultureInfo objects, I found locale 1033 for "en-US" had a long time string of "h:mm:ss tt". The AMDesignator was "AM", but the PMDesignator was an empty string! I verified this was the cause of the bad date in C# by running the following command:

// clear the PM designator
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator = ""
// this will yield "12/25/2012 12:00:00 " (note the extra space at the end)
Convert.ToDateTime("10/25/2012").ToString()

The result was "10/25/2012 12:00:00 " which corresponds to what Brian Begley in his answer. Using the invariant format yields a very similar result:

// clear the PM designator
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator = ""
// this will yield "10/25/2012 12:00:00"
Convert.ToDateTime("10/25/2012").ToString(System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat)
// restore the PM designator to "PM"
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator = "PM"
// this will yield "10/25/2012 00:00:00"
Convert.ToDateTime("10/25/2012").ToString(System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat)

I have yet to determine what is causing the CultureInfo to be corrupted.

Note that Microsoft is aware of this issue. The article linked says it applies only to Windows Server 2003, and there is a hotfix available.

Unaccountedfor answered 25/10, 2012 at 21:39 Comment(0)
A
0

It sounds like somehow the culture object isn't understanding military time notation. I'm honestly not sure where to go from there, but it may give you a starting point.

Assort answered 16/10, 2009 at 19:5 Comment(0)
H
0

What's the value of the CultureInfo.DateTimeFormat property? According to MSDN:

"The user might choose to override some of the values associated with the current culture of Windows through the regional and language options portion of Control Panel. For example, the user might choose to display the date in a different format or to use a currency other than the default for the culture.

If UseUserOverride is true and the specified culture matches the current culture of Windows, the CultureInfo uses those overrides, including user settings for the properties of the DateTimeFormatInfo instance returned by the DateTimeFormat property, and the properties of the NumberFormatInfo instance returned by the NumberFormat property. If the user settings are incompatible with the culture associated with the CultureInfo, for example, if the selected calendar is not one of the OptionalCalendars, the results of the methods and the values of the properties are undefined.

The value of the DateTimeFormat property and the NumberFormat property is not calculated until your application accesses the property. If the user can change the current culture to a new culture while the application is running and then the application accesses the DateTimeFormat or NumberFormat property, the application retrieves the defaults for the new culture instead of the overrides for the original culture. To preserve the overrides for the original current culture, the application should access the DateTimeFormat and NumberFormat properties before changing the current culture."

Could it be some user setting is over-riding this?

Halo answered 16/10, 2009 at 19:13 Comment(0)
B
0

It's a wild guess, but maybe something like this sequence of events might have caused the problem:

  1. An administrator goes into Control Panel International settings on all servers and changes the time format from "HH:mm:ss" to "hh:mm:ss tt".
  2. The administrator recycles the application pool (or the IIS service, or the machine) on only one of the servers.

All new ASP.NET worker threads on the recycled server will now see the changed time format and their DateTime.Parse methods will fail. However, if the other servers are still using the original worker threads, then they have not yet detected the changes to the current culture DateTimeFormatInfo.

It's a very unlikely scenario, but then again, you have a very unlikely situation. You could try recycling the relevant application pool on all the servers and see if anything changes.

Bowse answered 19/10, 2009 at 16:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.