How to format a datetime data binding

By default, the DatePicker is displayed in my localized format.
However, a text label with data bound from the database is displayed in the format YYYY-MM-DD, and not accordingly to my browser.

Is there a way to display this date in a localized format?

(Chatbeaverbot is such a great help for me, a big thank you! :smiley:
I rely on it so much, but in this case, it couldn’t assist me
)

My form, a date picker and a label bound to a column in the database:
Capture

The data binding:
Capture 2

Have a look through the custom component that does this conversion to see the technique used there and adapt it to your use case: Local Timezone Display in Data Grids

2 Likes

Try this (untested):

# add this import to the form
import anvil.tz

# use this in the databinding
self.item['added'].astimezone(anvil.tz.tzlocal()).strftime("%Y-%m-%d %H:%M:%S")
1 Like

Many thanks you both for you answers.
Based on your replies, I went a step further and started a little localization mechanism:

Client side:
self.label_dateAdded.text = anvil.server.call( 'format_locale_datetime', self.item['added'] )

Server side:

@anvil.server.callable
def get_preferred_locale():
  country = anvil.server.context.client.location.country  
  if country in ['Germany', 'Austria', 'Switzerland']:
    return 'DE'
  elif country in ['France', 'Belgium', 'Luxembourg']:
    return 'FR'
  elif country in ['Spain', 'Mexico', 'Argentina']:
    return 'ES'
  elif country in ['Italy']:
    return 'IT'
  elif country in ['Sweden']:
    return 'SV'
  elif country in ['Norway']:
    return 'NO'
  elif country in ['Greece']:
    return 'EL'
  else:
    return 'EN'


@anvil.server.callable
def format_locale_datetime(myDatetime):
  preferred_locale = anvil.server.call('get_preferred_locale')

  if preferred_locale in ['FR', 'CA', 'BE', 'LU', 'CH_FR', 'ES', 'IT', 'EL']:
    return myDatetime.strftime("%d/%m/%Y %H:%M")
  elif preferred_locale in ['DE', 'CH', 'AT', 'NO']:
    return myDatetime.strftime("%d.%m.%Y %H:%M")
  elif preferred_locale in ['SV']:
    return myDatetime.strftime("%Y-%m-%d %H:%M")
  else:  # English by default
    return myDatetime.strftime("%b %d %Y %I:%M %p")

A couple of things to note about your solution.

  1. When you’re in a server function, don’t use anvil.server.call to call another server function, that just adds overhead. Just call the server function like a normal function, e.g.:
@anvil.server.callable
def format_locale_datetime(myDatetime):
  preferred_locale = get_preferred_locale()
  1. The client context isn’t going to change for a user during a session, so you could make that get_preferred_locale call once on startup and cache the value in a client module, and then use client code for the strftime calls, avoiding the overhead of the frequent server calls.

As is, there’s going to be a delay each time you set the text for a datetime because of the server call.

2 Likes

Oh you’re right.

  1. fixed
  2. yes it’s useless to fetch locale things each time. Furthermore countries like Switzerland make it difficult, as there is not a single language.

I will rework it so that the user can choose his own locale settings in a parameter form.
If not set by the user, then use get_preferred_locale() and store it in my user table in database.

I noticed I also need to fix the date picker, and this will be very helpfull:

You can also use the browser to get the local format
This could work nicely in conjunction with @jshaffstall suggestion above

from anvil.js.window import Date

def get_locale_format(tz=None):
    d = Date(1999, 2, 17) # 1999-03-17
    s = d.toLocaleDateString(tz) if tz else d.toLocaleDateString()
    return s.replace("1999", "%Y").replace("99", "%y").replace("17", "%d").replace("03", "%m").replace("3", "%m")


get_locale_format() # your browser locale format
get_locale_format("en-US") # '%m/%d/%Y'
get_locale_format("en-GB") # '%d/%m/%Y'
get_locale_format("de-DE") # '%d.%m.%Y'

(yes javascript is 0 indexed for months :roll_eyes: )

It uses the magic date from the _strptime.LocaleTime implementation

3 Likes