Locale Date Formatting in Python

Locale date formatting in Python

You can just set the locale like in this example:

>>> import time
>>> print time.strftime("%a, %d %b %Y %H:%M:%S")
Sun, 23 Oct 2005 20:38:56
>>> import locale
>>> locale.setlocale(locale.LC_TIME, "sv_SE") # swedish
'sv_SE'
>>> print time.strftime("%a, %d %b %Y %H:%M:%S")
sön, 23 okt 2005 20:39:15

python-plotly date formatting with respect to locale

From what I can find at this time, Plotly does not seem to change date formats, etc. when changing locales. The only way to deal with this seems to be to convert strings. The basis for this answer comes from the community. The developer's comments are as of July 2021, so it is possible that this will be improved in the future. Also, my response may help other respondents to get a solution to this issue.

import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime
import locale

#Get information on the actual locale setting:
print(locale.getlocale())

#Set locale for another country:
locale.setlocale(locale.LC_TIME, 'de_DE.UTF-8')
# this sets the date time formats to Germany; there are many other options for currency, numbers etc.
# for any other locale settings see: https://docs.python.org/3/library/locale.html

d = {'Time': [datetime(2020, k, 15) for k in range(2,7)],
'value': np.random.rand(5)}
df=pd.DataFrame(d)
print(df)
print(df.info())
print(df["Time"].dt.strftime("%a %H:%M"))

#fig = px.line(df, y="value", x="Time")
# Update
fig = go.Figure(go.Scatter(mode='lines', x=[d.strftime('%a\n%H:%M') for d in df['Time']], y=df['value']))
#fig.update_xaxes(tickformat="%a\n%H:%M",)
fig.show()

Sample Image

Format date based on locale in python

The strftime methods always use the current locale. For example:

from datetime import date
d = date.today()
print d.format("%B %d")

will output "July 19" (no "'th", sorry...) if your locale is en_US, but "juillet 19" if the locale uses French.

If you want to make the order of the different parts also dependent on the locale, or other more advanced things, I suggest you have a look at the babel library, which uses data from the Common Locale Data Repository and allows you to do things like:

from babel.dates import dateformat
format_date(d, format="long", locale="en_US")

which would output "July 19, 2010", but "19 juillet 2010" for French, etc... Note that you have to explicitly request a specific locale though (or rather the language code)
Alas, this doesn't allow leaving off the year. If you delve further into babel however, there are ways to get the patterns for a specific locale (babel.dates.get_date_format("long", locale="en_US").pattern would give you "EEEE, MMMM d, yyyy" for example, which you could use for the format argument instead of "long"). This still leaves you with the task of stripping "yyyy" out of the format, along with the comma's etc... that might come before or after. Other than that, I'm afraid you would have to make your own patterns for each locale.

How do I strftime a date object in a different locale?

The example given by Rob is great, but isn't threadsafe. Here's a version that works with threads:

import locale
import threading

from datetime import datetime
from contextlib import contextmanager

LOCALE_LOCK = threading.Lock()

@contextmanager
def setlocale(name):
with LOCALE_LOCK:
saved = locale.setlocale(locale.LC_ALL)
try:
yield locale.setlocale(locale.LC_ALL, name)
finally:
locale.setlocale(locale.LC_ALL, saved)

# Let's set a non-US locale
locale.setlocale(locale.LC_ALL, 'de_DE.UTF-8')

# Example to write a formatted English date
with setlocale('C'):
print(datetime.now().strftime('%a, %b')) # e.g. => "Thu, Jun"

# Example to read a formatted English date
with setlocale('C'):
mydate = datetime.strptime('Thu, Jun', '%a, %b')

It creates a threadsafe context manager using a global lock and allows you to have multiple threads running locale-dependent code by using the LOCALE_LOCK. It also handles exceptions from the yield statement to ensure the original locale is always restored.

Python datetime.strptime with Korean locale on Windows

Apply locale.setlocale(locale.LC_ALL, 'kor') instead of locale.setlocale(locale.LC_TIME, 'kor') as follows:

d:\bat> python -q
>>>
>>> import locale
>>> from datetime import datetime
>>>
>>> ### generate a date string with datetime.strftime
...
>>> locale.setlocale(locale.LC_ALL, 'kor') ### crucial point ###
'Korean_Korea.949'
>>> locale.getlocale(locale.LC_TIME)
('Korean_Korea', '949')
>>> print(datetime.now().strftime('%A')) # Prints 월요일 (right!)
월요일
>>>
>>> ### parsing korean date string
...
>>> date_string = '월요일, 2019년 08월 05일 09:33:39'
>>> fromat = '%A, %Y년 %m월 %d일 %H:%M:%S'
>>>
>>> time = datetime.strptime(date_string, fromat)
>>> print(time)
2019-08-05 09:33:39
>>>

FYI, here are some other test cases (Python 3.5.1 64 bit (AMD64) on win32):

import locale
from datetime import datetime

locale.getdefaultlocale() # Echoes ('cs_CZ', 'cp65001')
locale.getlocale(locale.LC_TIME) # Echoes (None, None)
print(datetime.now().strftime('%A')) # Prints Monday (wrong?)

# user’s default setting for LC_TIME category
locale.setlocale(locale.LC_TIME, '') # Echoes 'Czech_Czechia.utf8'
locale.getlocale(locale.LC_TIME) # Echoes ('Czech_Czechia', 'utf8')
print(datetime.now().strftime('%A')) # Prints pondÄí (wrong!)

# user’s default setting for all categories
locale.setlocale(locale.LC_ALL, '') # Echoes 'Czech_Czechia.utf8'
locale.getlocale(locale.LC_TIME) # Echoes ('Czech_Czechia', 'utf8')
print(datetime.now().strftime('%A')) # Prints pondělí (right!)

################################################

locale.setlocale(locale.LC_TIME, 'kor')
locale.getlocale(locale.LC_TIME)
print(datetime.now().strftime('%A')) # Prints ¿ù¿äÀÏ (wrong!)

################################################

How do I get the correct date format string for a given locale without setting that locale program-wide in Python?

There is the non-standard babel module which offers this and a lot more:

>>> import babel.dates
>>> babel.dates.format_datetime(locale='ru_RU')
'12 мая 2014 г., 8:24:08'
>>> babel.dates.format_datetime(locale='de_DE')
'12.05.2014 08:24:14'
>>> babel.dates.format_datetime(locale='en_GB')
'12 May 2014 08:24:16'
>>> from datetime import datetime, timedelta
>>> babel.dates.format_datetime(datetime(2014, 4, 1), locale='en_GB')
'1 Apr 2014 00:00:00'
>>> babel.dates.format_timedelta(datetime.now() - datetime(2014, 4, 1),
locale='en_GB')
'1 month'

Get date format in Python in Windows

Your problem is probably the fact that locale.nl_langinfo doesn't appear to be available in Windows Python 2.7.x (I don't see it in my copy of Windows 64-bit Python 2.7.3). Looking at the docs at http://docs.python.org/2.7/library/locale.html#locale.nl_langinfo, they specifically say:

This function is not available on all systems, and the set of possible options might also vary across platforms.

Once you've set the locale up with something along the lines of:

locale.setlocale(locale.LC_ALL, 'english')

Then calls to some_date.strftime() will use correct locale specific formatting and strings. So if you want the date in string format, call some_date.strftime('%x') replace the %x with %X for time or %c for both. The full list of strftime formats are documented here.

>>> d = datetime.datetime.now()
... for loc in ('english', 'german', 'french'):
... locale.setlocale(locale.LC_ALL, loc)
... print loc, d.strftime('%c -- %x -- %X -- %B -- %A')
english 11/15/2012 4:10:56 PM -- 11/15/2012 -- 4:10:56 PM -- November -- Thursday
german 15.11.2012 16:10:56 -- 15.11.2012 -- 16:10:56 -- November -- Donnerstag
french 15/11/2012 16:10:56 -- 15/11/2012 -- 16:10:56 -- novembre -- jeudi
14: 'French_France.1252'

Python: date formatted with %x (locale) is not as expected

After reading the setlocale() documentation, I understood that the default OS locale is not used by Python as the default locale. To use it, I had to start my module with:

import locale
locale.setlocale(locale.LC_ALL, '')

Alternatively, if you intend to only reset the locale's time settings, use just LC_TIME as it breaks many fewer things:

import locale
locale.setlocale(locale.LC_TIME, '')

Surely there will be a valid reason for this, but at least this could have been mentioned as a remark in the Python documentation for the %x directive.



Related Topics



Leave a reply



Submit