Accueil Nos publications Blog [C#] – Un petit problème de DateTime et Culture

[C#] – Un petit problème de DateTime et Culture

La manipulation des dates est aisée et pratique quand on utilise .NET mais par contre, quand on manipule des dates et des cultures différentes que la sienne, on peut avoir des effets de bords particuliers selon les versions du Framework que vous utilisez.
J’étais récemment tombé sur des problématiques qui faisaient planter mon site web en manipulant des dates au format Italien. En essayant de le reproduire (je n’y arrive plus), j’ai découvert un effet de bord un peu désagréable…

Imaginons, une application localisée. Pour pouvoir adapter votre contexte à une culture spécifique, vous devrez surcharger la méthode InitializeCulture de l’objet Page. Voici ce que l’on peut faire de façon basique :


public class BasePage : Page
{
protected override void InitializeCulture() {
CultureInfo culture = CultureInfo.CreateSpecificCulture("it");
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
}

Ici, j’ai créé une classe héritant de l’objet Page. C’est une classe de base où je force la culture en Italien (car, c’est avec cette culture que j’ai eu le souci) et dont hériteront mes autres pages de tests. Voyons maintenant de près le problème.

Au sein de Visual Studio 2010

En utilisant le Framework 3.5, en mode debug, quand j’accède à mon objet DateTime, ce dernier est transformé selon le contexte dans lequel il est exécuté :

En utilisant le Framework 4.0, toujours dans le même mode, le fonctionnement est différent :

On remarque que j’ai perdu ici mon séparateur pour l’heure.

Et au sein de ma page web ?

Sur la page ou j’affiche mes données, la date est affichée pour le framework 3.0 au format de base italien :

Et pour le framework 4.0. Vous, vous en serez douté, mais, il m’affiche les 2 points comme séparateurs d’heure.

La 1ière solution que j’avais trouvée était d’utiliser le pattern DateTime italien lors de la manipulation de ma date:


String italianShortDateTimePattern = "MM'/'dd'/'yyyy HH.mm.ss";

//BIrthDate est un objet DateTime
BirthDate.ToString("italianShortDateTimePattern", MyCulture)

Toutefois, ça ne m’a pas suffi, et je me suis mis à rechercher s’il s’agissait d’un problème lié au Framework 4. J’ai trouvé cet article : Microsoft .NET Framework 4: What is New in Globalization. Outre le fait qu’il m’a permis d’apprendre quelles étaient en partie les évolutions apportées au namespace System.Globalization par le framework .NET 4, j’ai aussi remarqué ça :

The globalization information retrieval mechanism is changing in the .NET Framework 4. When running on Windows 7 and up, the globalization information will be retrieved directly from Windows. When running on pre-Windows 7 releases (such as Vista, XP, server 2003 and 2008), the globalization information will be retrieved from an internal data store to ensure that your application is not retrieving very old data. The following architectural diagram visualizes the globalization information retrieval model.

With this new design, the definition of some of the CultureTypes will change since the globalization information will be retrieved from different locations depending on the hosting operating system. Culture Types: WindowsOnlyCultures and FrameworkCultures are now obsolete. If you try to use those CultureTypes, the compiler will give you a warning; however, the compilation will succeed. Using WindowsOnlyCultures will return no cultures but FrameworkCultures will return the same results as .NET Framework 2. Other CultureTypes will continue to have the same definition as before.

J’utilise Windows Seven, et je n’ai pas des paramètres de culture italienne installés sur mon poste. Le problème est donc résolu. Et pour pouvoir donc le régler, et aussi assurer une réelle portabilité de vos applications, il faut lorsque vous initialisez votre culture, utiliser un pattern (et aussi des séparateurs) :


protected override void InitializeCulture()
{
base.InitializeCulture();

CultureInfo culture = CultureInfo.CreateSpecificCulture("it");

culture.DateTimeFormat.TimeSeparator = ".";
culture.DateTimeFormat.ShortDatePattern = "MM'/'dd'/'yyyy";

Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}

Et tout rentre dans l’ordre …

A bientôt !