Formatting date, time, currency in various cultures

In today’s interconnected world, it’s important that online applications support different cultures.

Even if most of us that spend a lot of time online are accustomed to the USA date and number formats, people always prefer to see numbers and dates formatted in a familiar way. People don’t like to think about if the date’s first digit is day or month, or if it’s decimal delimiter or digit grouping mark.

The date 03/02/2010 means completely different thing in Australia and USA – it’s February the 3rd in the former and March the 2nd in latter! (dd/mm/yyyy vs mm/dd/yyyy)

Even if we assume that the common internet user can read the shown format based on the website’s supposed location, localization and internationalization (i18n) could greatly improve readability and usability.

Some cultures supported in Windows

I have been working on a problem considering DateTime formatting in .NET recently, and I decided to have a look at the cultures and formats that are supported on my machine.

It’s really interesting to see this, here is a subset with interesting formats highlighted. If you like, you can see the full results here.

Name DisplayName ShortDatePattern FullDateTimePattern Currency (decimals) NaNSymbol RTL
am-ET Amharic (Ethiopia) d/M/yyyy dddd ‘፣’ MMMM d ‘ቀን’ yyyy h:mm:ss tt ETB (2) NAN  
ar-AE Arabic (U.A.E.) dd/MM/yyyy dd MMMM, yyyy hh:mm:ss tt د.إ.‏ (2) ليس برقم RTL
ar-BH Arabic (Bahrain) dd/MM/yyyy dd MMMM, yyyy hh:mm:ss tt د.ب.‏ (3) ليس برقم RTL
az-Cyrl-AZ Azeri (Cyrillic, Azerbaijan) dd.MM.yyyy d MMMM yyyy H:mm:ss ман. (2) NaN  
bg-BG Bulgarian (Bulgaria) d.M.yyyy ‘г.’ dd MMMM yyyy ‘г.’ HH:mm:ss ‘ч.’ лв. (2) NaN  
bo-CN Tibetan (PRC) yyyy/M/d yyyy’ལོའི་ཟླ’ M’ཚེས’ d HH:mm:ss ¥ (2) ཨང་ཀི་མིན་པ།  
ca-ES Catalan (Catalan) dd/MM/yyyy dddd, d’ / ‘MMMM’ / ‘yyyy HH:mm:ss € (2) NeuN  
co-FR Corsican (France) dd/MM/yyyy dddd d MMMM yyyy HH:mm:ss € (2) Mica numericu  
cs-CZ Czech (Czech Republic) d.M.yyyy d. MMMM yyyy H:mm:ss Kč (2) Není číslo  
de-AT German (Austria) dd.MM.yyyy dddd, dd. MMMM yyyy HH:mm:ss € (2) n. def.  
dsb-DE Lower Sorbian (Germany) d. M. yyyy dddd, ‘dnja’ d. MMMM yyyy H:mm:ss € (2) njedefinowane  
el-GR Greek (Greece) d/M/yyyy dddd, d MMMM yyyy h:mm:ss tt € (2) μη αριθμός  
en-IN English (India) dd-MM-yyyy dd MMMM yyyy HH:mm:ss Rs. (2) NaN  
en-ZA English (South Africa) yyyy/MM/dd dd MMMM yyyy hh:mm:ss tt R (2) NaN  
es-AR Spanish (Argentina) dd/MM/yyyy dddd, dd’ de ‘MMMM’ de ‘yyyy hh:mm:ss tt $ (2) NeuN  
et-EE Estonian (Estonia) d.MM.yyyy d. MMMM yyyy’. a.’ H:mm:ss kr (2) avaldamatu  
fy-NL Frisian (Netherlands) d-M-yyyy dddd d MMMM yyyy H:mm:ss € (2) NaN  
gsw-FR Alsatian (France) dd/MM/yyyy dddd d MMMM yyyy HH:mm:ss € (2) Ohne Nummer  
gu-IN Gujarati (India) dd-MM-yy dd MMMM yyyy HH:mm:ss રૂ (2) NaN  
hu-HU Hungarian (Hungary) yyyy.MM.dd. yyyy. MMMM d. H:mm:ss Ft (2) nem szám  
it-CH Italian (Switzerland) dd.MM.yyyy dddd, d. MMMM yyyy HH:mm:ss fr. (2) Non un numero reale  
ja-JP Japanese (Japan) yyyy/MM/dd yyyy’年’M’月’d’日’ H:mm:ss ¥ (0) NaN (非数値)  
ka-GE Georgian (Georgia) dd.MM.yyyy yyyy ‘წლის’ dd MM, dddd H:mm:ss Lari (2) NaN  
nl-BE Dutch (Belgium) d/MM/yyyy dddd d MMMM yyyy H:mm:ss € (2) NaN (Niet-een-getal)  

Here’s the code I have used. I ran it in LinqPad, the output is provided using the Dump extension method and then exported the results to HTML.

var cultures = System.Globalization.CultureInfo.
                GetCultures(System.Globalization.CultureTypes.SpecificCultures).
                Select(c =>
                    {
                        return new {
                            Name = c.Name,
                            DisplayName = c.DisplayName,
                            ShortDatePattern = c.DateTimeFormat.
                                                ShortDatePattern,
                            FullDateTimePattern = c.DateTimeFormat.
                                                    FullDateTimePattern,
                            Currency = String.Format(
                                                "{0} ({1})",
                                                c.NumberFormat.CurrencySymbol,
                                                c.NumberFormat.CurrencyDecimalDigits
                                                ),
                            NaNSymbol = c.NumberFormat.NaNSymbol,
                            RTL = c.TextInfo.IsRightToLeft ? "RTL" : ""
                            };
                    }
                ).OrderBy(c => c.Name).ToList();
cultures.Dump();

The cultures applied

Then I wanted to see these formats in action. So I altered the program a bit.

var cultures = System.Globalization.CultureInfo.
            GetCultures(System.Globalization.CultureTypes.SpecificCultures).
            Select(c =>
            {
                return new {
                        Name = c.Name,
                        DisplayName = c.DisplayName,
                        ShortDate = DateTime.Parse("2010-12-16T13:25:43").
                                        ToString(c.DateTimeFormat.
                                                    ShortDatePattern, c),
                        FullDateTimePattern = DateTime.Parse("2010-12-16T13:25:43").
                                                ToString(c.DateTimeFormat.
                                                    FullDateTimePattern, c),
                        Currency = (578349026.7584901).ToString("c", c)
                    };
            }
        ).OrderBy(c => c.Name).ToList();
cultures.Dump();

Here are some interesting results produced this way, again a highlighted subset, while you can see the full results here.

Name DisplayName ShortDate FullDateTimePattern Currency
am-ET Amharic (Ethiopia) 16/12/2010 ሐሙስ ፣ ዲሴምበር 16 ቀን 2010 1:25:43 ከሰዓት ETB578349,026.76
ar-AE Arabic (U.A.E.) 16/12/2010 16 ديسمبر, 2010 01:25:43 م د.إ.‏ 578,349,026.76
ar-BH Arabic (Bahrain) 16/12/2010 16 ديسمبر, 2010 01:25:43 م د.ب.‏ 578,349,026.758
az-Cyrl-AZ Azeri (Cyrillic, Azerbaijan) 16.12.2010 16 декабр 2010 13:25:43 578 349 026,76 ман.
bn-BD Bengali (Bangladesh) 16-12-10 16 ডিসেম্বর 2010 13.25.43 ৳ 57,83,49,026.76
bo-CN Tibetan (PRC) 2010/12/16 2010ལོའི་ཟླ 12ཚེས 16 13:25:43 ¥578349,026.76
de-AT German (Austria) 16.12.2010 Donnerstag, 16. Dezember 2010 13:25:43 € 578.349.026,76
de-CH German (Switzerland) 16.12.2010 Donnerstag, 16. Dezember 2010 13:25:43 Fr. 578’349’026.76
de-DE German (Germany) 16.12.2010 Donnerstag, 16. Dezember 2010 13:25:43 578.349.026,76 €
en-CA English (Canada) 16/12/2010 December-16-10 1:25:43 PM $578,349,026.76
eu-ES Basque (Basque) 2010/12/16 osteguna, 2010.eko abenduak 16 13:25:43 578.349.026,76 €
fa-IR Persian 12/16/2010 الخميس, ديسمبر 16, 2010 01:25:43 ب.ظ ريال 578,349,026/76
gu-IN Gujarati (India) 16-12-10 16 ડિસેમ્બર 2010 13:25:43 રૂ 57,83,49,026.76
hr-HR Croatian (Croatia) 16.12.2010. 16. prosinca 2010. 13:25:43 578.349.026,76 kn
hu-HU Hungarian (Hungary) 2010.12.16. 2010. december 16. 13:25:43 578 349 026,76 Ft
ig-NG Igbo (Nigeria) 16/12/2010 Ojo’bo, Onwa iri n’ibua 16, 2010 1:25:43 Efifie N 578,349,026.76
ja-JP Japanese (Japan) 2010/12/16 2010年12月16日 13:25:43 ¥578,349,027
kk-KZ Kazakh (Kazakhstan) 16.12.2010 16 желтоқсан 2010 ж. 13:25:43 Т578 349 026-76
prs-AF Dari (Afghanistan) 10/01/32 10/01/1432 1:25:43 غ.و ؋578,349,026.76
zh-CN Chinese (Simplified, PRC) 2010/12/16 2010年12月16日 13:25:43 ¥578,349,026.76

Lessons learned

Some things I learned with this experiment –

  • Same language or country doesn’t mean same formatting if there are different cultures.
  • Date patterns are more versatile then I could have imagined.
  • Arabic cultures have a completely different calendar then the western world, for example, 16th December 2010 is 10th Haram 1432 in Afghanistan.
  • Date part order is completely arbitrary, “M/d/y”, “y/M/d”, “d/M/y/” and so on.
  • Date part separator could be a dot, slash, dash…
  • Japanese Yen is shown only as a rounded number.
  • Germans write Euro symbol (€) before the amount, while the Austrians write it afterwards.
  • Decimal grouping symbol is really versatile, could be a dot, a comma, single quote, blank space… For example, Swiss use single quote (‘).
  • Decimal separator could be a comma, dot, slash or dash…
  • While most  cultures group digits by three, some group them by two like Bengali (Bangladesh).

There is A LOT of different formats out there, so if you want to do any kind of custom formatting and keep the culture specific formats, you have to keep this in mind and deploy a solution accordingly. Additional links on this subject:


Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.