Serendipity running machine progressing toward accomplishments.

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!

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.

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.

NameDisplayNameShortDatePatternFullDateTimePatternCurrency (decimals)NaNSymbolRTL
am-ETAmharic (Ethiopia)d/M/yyyydddd ‘፣’ MMMM d ‘ቀን’ yyyy h:mm:ss ttETB (2)NAN
ar-AEArabic (U.A.E.)dd/MM/yyyydd MMMM, yyyy hh:mm:ss ttد.إ.‏ (2)ليس برقمRTL
ar-BHArabic (Bahrain)dd/MM/yyyydd MMMM, yyyy hh:mm:ss ttد.ب.‏ (3)ليس برقمRTL
az-Cyrl-AZAzeri (Cyrillic, Azerbaijan)dd.MM.yyyyd MMMM yyyy H:mm:ssман. (2)NaN
bg-BGBulgarian (Bulgaria)d.M.yyyy ‘г.’dd MMMM yyyy ‘г.’ HH:mm:ss ‘ч.’лв. (2)NaN
bo-CNTibetan (PRC)yyyy/M/dyyyy’ལོའི་ཟླ’ M’ཚེས’ d HH:mm:ss¥ (2)ཨང་ཀི་མིན་པ།
ca-ESCatalan (Catalan)dd/MM/yyyydddd, d’ / ‘MMMM’ / ‘yyyy HH:mm:ss€ (2)NeuN
co-FRCorsican (France)dd/MM/yyyydddd d MMMM yyyy HH:mm:ss€ (2)Mica numericu
cs-CZCzech (Czech Republic)d.M.yyyyd. MMMM yyyy H:mm:ssKč (2)Není číslo
de-ATGerman (Austria)dd.MM.yyyydddd, dd. MMMM yyyy HH:mm:ss€ (2)n. def.
dsb-DELower Sorbian (Germany)d. M. yyyydddd, ‘dnja’ d. MMMM yyyy H:mm:ss€ (2)njedefinowane
el-GRGreek (Greece)d/M/yyyydddd, d MMMM yyyy h:mm:ss tt€ (2)μη αριθμός
en-INEnglish (India)dd-MM-yyyydd MMMM yyyy HH:mm:ssRs. (2)NaN
en-ZAEnglish (South Africa)yyyy/MM/dddd MMMM yyyy hh:mm:ss ttR (2)NaN
es-ARSpanish (Argentina)dd/MM/yyyydddd, dd’ de ‘MMMM’ de ‘yyyy hh:mm:ss tt$ (2)NeuN
et-EEEstonian (Estonia)d.MM.yyyyd. MMMM yyyy’. a.’ H:mm:sskr (2)avaldamatu
fy-NLFrisian (Netherlands)d-M-yyyydddd d MMMM yyyy H:mm:ss€ (2)NaN
gsw-FRAlsatian (France)dd/MM/yyyydddd d MMMM yyyy HH:mm:ss€ (2)Ohne Nummer
gu-INGujarati (India)dd-MM-yydd MMMM yyyy HH:mm:ssરૂ (2)NaN
hu-HUHungarian (Hungary)yyyy.MM.dd.yyyy. MMMM d. H:mm:ssFt (2)nem szám
it-CHItalian (Switzerland)dd.MM.yyyydddd, d. MMMM yyyy HH:mm:ssfr. (2)Non un numero reale
ja-JPJapanese (Japan)yyyy/MM/ddyyyy’年’M'月’d'日’ H:mm:ss¥ (0)NaN (非数値)
ka-GEGeorgian (Georgia)dd.MM.yyyyyyyy ‘წლის’ dd MM, dddd H:mm:ssLari (2)NaN
nl-BEDutch (Belgium)d/MM/yyyydddd 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();

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.

NameDisplayNameShortDateFullDateTimePatternCurrency
am-ETAmharic (Ethiopia)16/12/2010ሐሙስ ፣ ዲሴምበር 16 ቀን 2010 1:25:43 ከሰዓትETB578349,026.76
ar-AEArabic (U.A.E.)16/12/201016 ديسمبر, 2010 01:25:43 مد.إ.‏ 578,349,026.76
ar-BHArabic (Bahrain)16/12/201016 ديسمبر, 2010 01:25:43 مد.ب.‏ 578,349,026.758
az-Cyrl-AZAzeri (Cyrillic, Azerbaijan)16.12.201016 декабр 2010 13:25:43578 349 026,76 ман.
bn-BDBengali (Bangladesh)16-12-1016 ডিসেম্বর 2010 13.25.43৳ 57,83,49,026.76
bo-CNTibetan (PRC)2010/12/162010ལོའི་ཟླ 12ཚེས 16 13:25:43¥578349,026.76
de-ATGerman (Austria)16.12.2010Donnerstag, 16. Dezember 2010 13:25:43€ 578.349.026,76
de-CHGerman (Switzerland)16.12.2010Donnerstag, 16. Dezember 2010 13:25:43Fr. 578’349’026.76
de-DEGerman (Germany)16.12.2010Donnerstag, 16. Dezember 2010 13:25:43578.349.026,76 €
en-CAEnglish (Canada)16/12/2010December-16-10 1:25:43 PM$578,349,026.76
eu-ESBasque (Basque)2010/12/16osteguna, 2010.eko abenduak 16 13:25:43578.349.026,76 €
fa-IRPersian12/16/2010الخميس, ديسمبر 16, 2010 01:25:43 ب.ظريال 578,349,026/76
gu-INGujarati (India)16-12-1016 ડિસેમ્બર 2010 13:25:43રૂ 57,83,49,026.76
hr-HRCroatian (Croatia)16.12.2010.16. prosinca 2010. 13:25:43578.349.026,76 kn
hu-HUHungarian (Hungary)2010.12.16.2010. december 16. 13:25:43578 349 026,76 Ft
ig-NGIgbo (Nigeria)16/12/2010Ojo’bo, Onwa iri n’ibua 16, 2010 1:25:43 EfifieN 578,349,026.76
ja-JPJapanese (Japan)2010/12/162010年12月16日 13:25:43¥578,349,027
kk-KZKazakh (Kazakhstan)16.12.201016 желтоқсан 2010 ж. 13:25:43Т578 349 026-76
prs-AFDari (Afghanistan)10/01/3210/01/1432 1:25:43 غ.و؋578,349,026.76
zh-CNChinese (Simplified, PRC)2010/12/162010年12月16日 13:25:43¥578,349,026.76

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:

Bojan Bjelić

I'm a software architect, blogging about software, productivity and digital world.

More Posts - Website - Twitter



Leave a Reply

Note that I moderate all comments, so this may not appear immediately. I reserve the right to not publish comments that I consider aggressive, off-topic, or that don't contribute directly to the discussion. I will not publish anonymous posts, or comments where you didn't provide a real email address. I may contact you by email before publishing.