web-dev-qa-db-fra.com

Comment strime-t-on un objet date dans un environnement local différent?

J'ai un objet date dans python et j'ai besoin de générer un horodatage dans les paramètres régionaux C pour un système hérité, en utilisant les codes% a (jour de semaine) et% b (mois). Cependant, je ne souhaite pas modifier les paramètres régionaux de l'application, car les autres parties doivent respecter les paramètres régionaux actuels de l'utilisateur. Existe-t-il un moyen d'appeler strftime () avec certains paramètres régionaux?

27
MagerValp

L'exemple donné par Rob est génial, mais n'est pas threadsafe. Voici une version qui fonctionne avec les 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')

Il crée un gestionnaire de contexte threadsafe à l'aide d'un verrou global et vous permet d'avoir plusieurs threads exécutant du code dépendant des paramètres régionaux à l'aide de LOCALE_LOCK. Il gère également les exceptions de l'instruction yield pour garantir que les paramètres régionaux d'origine sont toujours restaurés.

33
Daniel

Non, il n'y a aucun moyen d'appeler strftime() avec un paramètre régional spécifique.

En supposant que votre application n'est pas multithread, enregistrez et restaurez les paramètres régionaux existants et définissez vos paramètres régionaux sur 'C' lorsque vous appelez strftime.

#! /usr/bin/python3
import time
import locale


def get_c_locale_abbrev():
  lc = locale.setlocale(locale.LC_TIME)
  try:
    locale.setlocale(locale.LC_TIME, "C")
    return time.strftime("%a-%b")
  finally:
    locale.setlocale(locale.LC_TIME, lc)

# Let's suppose that we're french
locale.setlocale(locale.LC_ALL, 'fr_FR.utf8')

# Should print french, english, then french
print(time.strftime('%a-%b'))
print(get_c_locale_abbrev())
print(time.strftime('%a-%b'))

Si tu préfères with: à try:-finally:, vous pouvez créer un gestionnaire de contexte:

#! /usr/bin/python3
import time
import locale
import contextlib

@contextlib.contextmanager
def setlocale(*args, **kw):
  saved = locale.setlocale(locale.LC_ALL)
  yield locale.setlocale(*args, **kw)
  locale.setlocale(locale.LC_ALL, saved)

def get_c_locale_abbrev():
  with setlocale(locale.LC_TIME, "C"):
    return time.strftime("%a-%b")

# Let's suppose that we're french
locale.setlocale(locale.LC_ALL, 'fr_FR.utf8')

# Should print french, english, then french
print(time.strftime('%a-%b'))
print(get_c_locale_abbrev())
print(time.strftime('%a-%b'))
14
Robᵩ