6

I'm attempting to format dates for a French customer.

I need to format Times as shown in the following examples...

06:00 -> 6 h
08:45 -> 8 h 45
10:30 -> 10 h 30
15:00 -> 15 h
17:22 -> 17 h 22
18:00 -> 18 h

I've been able to use Custom Date and Time Formatting. But I seem to be stuck on this notation that the French (Canadian at least) don't show the Minutes if they are zero "00".

Currently I'm using the following format.

myDateTime.ToString("H \h mm")

How can I make it so "mm" only appears when > 00?

I'd like to avoid the use of an extension method or proxy class since I feel this should be built into the framework. Apparently its standard formatting for French times.

My string "H \h mm" is actually coming from a resource file. ie...

myDateTime.ToString(Resources.Strings.CustomTimeFormat);
Marcel Gosselin
  • 4,610
  • 2
  • 31
  • 54
Justin
  • 10,667
  • 15
  • 58
  • 79

5 Answers5

4

I have some bad news for you. The framework does not support the format you are looking for. The following code proves this:

using System;
using System.Globalization;

namespace ConsoleApplication1
{
    public class Program
    {
        static void Main(string[] args)
        {
            // FR Canadian
            Console.WriteLine("Displaying for: fr-CA");
            DisplayDatesForCulture("fr-CA");

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine();

            // FR French
            Console.WriteLine("Displaying for: fr-FR");
            DisplayDatesForCulture("fr-FR"); 

            Console.WriteLine();
            Console.WriteLine("Press enter to exit.");
            Console.ReadLine();
        }

        static void DisplayDatesForCulture(string culture)
        {
            var ci = CultureInfo.GetCultureInfo(culture);
            var dt = new DateTime(2010, 10, 8, 18, 0, 0);

            foreach (string s in ci.DateTimeFormat.GetAllDateTimePatterns())
                Console.WriteLine(dt.ToString(s));
        }
    }
}

The app displays all supported datetime formats. None of them support the concept of 18:00 ==> 18 h, etc.

Your best option is to write an extension method or similar approach.

Culture sensitive approach: build an extension helper class:

public static class DateHelper
{
    public static string ToLocalizedLongTimeString(this DateTime target)
    {
        return ToLocalizedLongTimeString(target, CultureInfo.CurrentCulture);
    }

    public static string ToLocalizedLongTimeString(this DateTime target, 
        CultureInfo ci)
    {
        // I'm only looking for fr-CA because the OP mentioned this 
        // is specific to fr-CA situations...
        if (ci.Name == "fr-CA")
        {
            if (target.Minute == 0)
            {
                return target.ToString("H' h'");
            }
            else
            {
                return target.ToString("H' h 'mm");
            }
        }
        else
        {
            return target.ToLongTimeString();
        }
    }
}

You can test like so:

var dt = new DateTime(2010, 10, 8, 18, 0, 0);

// this line will return 18 h
Console.WriteLine(dt.ToLocalizedLongTimeString(CultureInfo.GetCultureInfo("fr-CA")));

// this line returns 6:00:00 PM
Console.WriteLine(dt.ToLocalizedLongTimeString());

var dt2 = new DateTime(2010, 10, 8, 18, 45, 0);

// this line will return 18 h 45
Console.WriteLine(dt2.ToLocalizedLongTimeString(CultureInfo.GetCultureInfo("fr-CA")));

// this line returns 6:45:00 PM
Console.WriteLine(dt2.ToLocalizedLongTimeString());
code4life
  • 15,655
  • 7
  • 50
  • 82
  • Big points for your answer its very well written and I love the included tests. I did post my own answer which is a little more generic to hopefully accommodate all custom DateTime formats the user may wish to use. – Justin Oct 08 '10 at 22:11
2

Following on code4life's extension method idea, here's an extension method. =p

public static string ToCanadianTimeString(this DateTime source)
{
    if (source == null)
        throw new ArgumentNullException("source");

    if (source.Minute > 0)
        return String.Format("{0:hh} h {0:mm}", source);

    else
        return String.Format("{0:hh} h", source);
}
Moudis
  • 86
  • 3
  • Muhahaha, it is: "ToCanadianTimeString". – Hans Passant Oct 08 '10 at 20:58
  • @code4life: I can think of a couple of ways to either query the current culture or pass in a culture. I'll update the example to one of those a bit later if that's what you mean. – Moudis Oct 08 '10 at 21:01
  • If I have to revert to an extension method it should handle ALL cultures. Perhaps have 2 localized formats Strings.NoShowMinutesTimeFormat and Strings.HasMinutesTimeForm. The problem with this is that sometimes the Time is combined with a Date. So the format include something like "dddd d MMMM yyyy" whereas other parts of the app may use "d MMMM yyyy". Looks like I'll have to edit the format to remove "mm" from the format when the culture is fr-ca and the minutes are zero. I'll post my solution soon. – Justin Oct 08 '10 at 21:05
  • Man, that was inspired, ToCanadianTimeString...! – code4life Oct 08 '10 at 21:07
1

It might not be pretty but if they insist

if (Locality == france)
myDateTime.ToString(Resources.Strings.CustomTimeFormat).Replace("00","") ;
else 
myDateTime.ToString(Resources.Strings.CustomTimeFormat);
Roadie57
  • 324
  • 1
  • 6
1

Here is the solution I'm going with:

public static string ToStringOverride(this DateTime dateTime, string format)
{
    // Adjust the "format" as per unique Culture rules not supported by the Framework
    if (CultureInfo.CurrentCulture.LCID == 3084) // 3084 is LCID for fr-ca
    {
        // French Canadians do NOT show 00 for minutes.  ie.  8:00 is shown as "8 h" not "8 h 00"
        if (dateTime.Minute == 0)
        {
            format = format.Replace("mm", string.Empty);
        }
    }

    return dateTime.ToString(format);
}

It will at least work for different DateTime formats such as...

  • H \h mm
  • dddd d MMMM yyyy H \h mm tt

The idea here is I modify the FormatString to remove "mm" if minutes are zero. Still letting the framework do the hard work.

Justin
  • 10,667
  • 15
  • 58
  • 79
0

This is not pretty either:

myDateTime.ToString(myDateTime.Minute == 0 ? @"H \h" : @"H \h mm")
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181