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

前端 未结 3 525
半阙折子戏
半阙折子戏 2020-11-29 05:58

I have a date object in python and I need to generate a time stamp in the C locale for a legacy system, using the %a (weekday) and %b (month) codes. However I do not wish to

相关标签:
3条回答
  • 2020-11-29 06:25

    No, there is no way to call strftime() with a specific locale.

    Assuming that your app is not multi-threaded, save and restore the existing locale, and set your locale to 'C' when you invoke 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'))
    

    If you prefer with: to try:-finally:, you could whip up a context manager:

    #! /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'))
    
    0 讨论(0)
  • 2020-11-29 06:27

    take a look to the pytz package

    you can use like this

    import pytz
    UTC = pytz.timezone('UTC') # utc
    fr = pytz.timezone('Europe/Paris') #your local
    from datetime import datetime
    date = datetime.now(fr)
    dateUTC = date.astimezone(UTC)
    

    strftime will render in the timezone specified

    for have month name in the locale use calendar for example :

    import calendar
    print calendar.month_name[dateUTC.month] #will print in the locale
    

    inspect more deeply calendar for having more information

    0 讨论(0)
  • 2020-11-29 06:34

    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.

    0 讨论(0)
提交回复
热议问题